在此, 所謂一個 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