在此, 所謂一個 S-string 就是一個整數序列, 其最後一個整數是 0 (NULL). 簡稱 S-string. 每一個 S-string 有一個長度, 意即序列中整數的個數 (不含 NULL); 有一個寬度, 意即序列中每個 S-code 所佔的字元寬度和.
int s_wd(int s); int s_punct(int s); int s_digit(int s); int s_space(int s);
這些方程像是
s_digit 檢查是否為數目字符號 --- 0 代表不是, 1 代表是半形的阿拉伯數目字,
2 代表是全形的阿拉伯數目字.
s_space 檢查是否為空白符號 --- 0 代表不是, 1 代表是 ASCII 碼被
int s_len(int *ss); int s_width(int *ss);
這兩個方程很像
int char2s(unsigned char *cs, int *ss, int catg);
將一個 character string (cs) 轉換到一個 S-string (ss). 假設原來的 cs 是以 catg 編碼. 此方程還回去的整數是 ss 的字元寬度, 等於 strlen(cs).
int s_getline(FILE *fp, int *ss, int lim, int catg)
從 fp 讀一行, 存入 S-string s, 假設原檔案的編碼是 catg, 預設一行的 S-code 長度不得超過 lim-1 (包括 \n); 注意, 是 S-code 長度而非字元寬度. 這樣的設計是因為主程式中必須確定此整數序列的長度, 而 lim 在此是保衛此序列不致脹破. 但是在檔案中若有中英夾雜, 此長度沒什麼意義. 所以, 建議設定 lim 為即使一行中全是英文時的最大長度; 如此, 則若一行中全是中文時, 只須大約 lim/2 個 S-code. 此程式不檢查 fp 是否可讀, 亦不能檢查 s 是否足夠長. 如果檔案中有一行太長, 會自動切斷成兩行, 給警告訊息. 此方程還回去的整數是 ss 的長度, 等於 s_len(ss). 我們沒有提供一個專門從 stdin 讀入的方程, 請將 fp 寫成 stdin 即可.
int s_putstr(int *ss, FILE *fp, int catg);
將一個 S-string ss 以 catg 編碼寫入檔案 fp. 字串後並沒有加 \n, 完全由 ss 決定. 還回去列印字元數, 有如 s_width(ss); 若是有誤則還回去 EOF. 此程式並不檢查 fp 是否可寫. 我們沒有提供一個專門寫到 stdout 的方程, 請將 fp 寫成 stdout 即可.
#include "s_code.h" #include <ctype.h> #define iny(n) (((BL0 <= n) && (n <= BL1)) || ((BH0 <= n) && (n <= BH1))) int s_wd(int s) { return ((s&SM) == 0) ? 1 : 2; } int s_punct(int s) { int c=0, t; if ((s&SM) == 0) if (ispunct(s) != 0) c = 1; else if (s_gets(s) == SF) { t = (s&TM); if ((0x01000000 < t) && (t < 0x10000000)) { switch(t) { case PUNRF: c=3; break; case PUNRL: c=4; break; case PUNCF: c=5; break; case PUNCL: c=6; break; default: c=2; break; } } } return c; } int s_digit(int s) { int c=0; if ( ((s&SM) == 0) && (isdigit(s) != 0) ) c = 1; else if ( (s_gets(s) == SF) && ((s&TM) == NUMARB) ) c = 2; return c; } int s_space(int s) { int c=0; if ( ((s&SM) == 0) && (isspace(s) != 0) ) c = 1; else if ( (s_gets(s) == SF) && ((s&TM) == WHITE) ) c = 2; return c; } int s_len(int *s) { int *t; t=s; while (*t++ != 0); return t-s-1; } int s_width(int *s) { int *t, x, n=0; t=s; while ((x = *t++) != 0) n += s_wd(x); return n; } int char2s(char *cs, int *ss, int catg) { void *v; unsigned char *c, *s; int *t, x; v = cs; c = (unsigned char*) v; s = c; t = ss; switch(catg) { case BIG5: while ((x = *c++) != '\0') { if ( ((BX0 <= x) && (x <= BX1)) && iny(*c) ) *t++ = big5_s(x, *c++); else *t++ = x; } *t = 0; break; default: fprintf(stderr, "ERROR. char2s: unknown category %d.\n", catg); exit(5); } return (c-s)-1; } int s_getline(FILE *fp, int *ss, int lim, int catg) { int *s, len=lim, c, n=0; s = ss; while (--lim>1 && (c=s_getc(fp, catg)) != EOF && c != '\n') *s++ = c; if (c == '\n') *s++ = c; else if (lim == 1) { *s++ = '\n'; fprintf(stderr, "WARNING. s_getline: Line too long, splitted.\n"); } *s = 0; return s - ss; } int s_putstr(int *ss, FILE *fp, int catg) { int *s, x, n; s = ss; while ((x=*s++) != 0) if (s_putc(x, fp, catg) == EOF) return EOF; else n += s_wd(x); return n; }
Created: Jan 14, 1996
Last Revised: Jan 14, 1996
© Copyright 1996 Wei-Chang Shann