/****** 在身分證檢查程式中, 為了讓使用者輸入更方便, 通常我們會允許輸入身分證號碼中可任意插入空白, 例如A123456789 可以打成A123 456 789 這樣很容易肉眼查看, 然後程式中只要先做簡單處理即可: 把空白去掉! 所以我們也寫過一個 squeeze(char*buf)可以把字串 buf 中所有的空白去掉! 再複習一次這函數: (註: 有些語言有提供, 但 C 語言程式庫沒有這種函數) #include char* squeeze(char*buf) { char* p = buf, *p2 = buf; // 注意 *p2 才對, 不要忘了 p2左邊的"*" while(*p) { // *p 不是 0 if( isspace(*p) ) { ++p; continue; } // continue 會到 Loop 頭! *p2 = *p; p2++; ++p; } // while *p2 = 0; // NULL terminated, 重要 return buf; // 回傳該字串的頭方便使用, 當然你不用也沒關係 ! } // squeeze 擠壓 在這例子中用到了宣告於 的 isspace(int) 函數, 共有六個符號會被判定為是 space (或稱 white space), 參看 K&R 第二章, 或看以下的 isspace.c 程式! 另外, 身分證檢查程式中我們也用了 isalpha(int x), isdigit(int x), 分別可查知 x 是 否為 "字母" 和 "數字"; 類似的還有 isupper(int), islower(int) 等從名稱就知道做啥了! 我們還用了 toupper(int x) 可以在 x 是小寫字母時轉為大寫字母, 當然也有tolower(int) 這類似函數, 這些函數的宣告通通被收集在 內; 再提醒一次, 只有宣告在 內, 沒有程式的身體(或說沒有程式的"定義")! 程式的身體是早就被另外編譯成機器碼(Object code)放在程式庫目錄中! 讓我們先來看看 toupper(int) 這函數的程式碼: int toupper(int x) { if(x >= 'a' && x <= 'z') return x - 'a' + 'A'; return x; // otherwise } 或是更簡單的寫法: (使用 conditional expression) int toupper(int x) { return (x >= 'a' && x <= 'z') ? x - 'a' + 'A' : x; } 就這樣喔? 沒錯啊! 就是這樣簡單, 如果你不懂三元運算子 Ternary operator ?: 請參看 K&R 2.11 節! 或是自己用 gogle.com 上網查詢"三元運算子" 或 "Ternary operator"或 "Trinary operator" 以下是 tolower(int): int tolower(int x) { return (x >= 'A' && x <= 'Z') ? x - 'A' + 'a' : x; } 標準 C 的程式庫中共有大約一百多個 functions, 其中有一百多個都是像這樣一兩列就寫完的! 以下的 isspace.c 程式是用來研究哪些 char 被認定為 white space: ** 看不懂的記得在演習課時舉手找個助教來問! ******/ //isspace.c -- @CopyLeft by tsaiwn@csie.nctu.edu.tw // 測試程式庫中宣告於 內的一些函數 // 例如, isspace(x) 可以查詢 x 是否為 white space(空白, 廣義空白) // 注意是"白色空白", 不是"白色恐怖"喔! 但是稱白色空白太囉嗦, 通常簡稱空白, // 空白符號有六個: (1)空格 space, (2)往右跳定位 Tab (就是 CTRL_I),用 '\t' 表示; // (3)往下垂直跳定位 Vertical Tab, 用 '\v' 表示; // (4)新列符號 New Line, 用 '\n' 表示, 就是換到下一列(有些稱下一行); // (5)歸位字符(Carriage Return), 用 '\r' 表示, 又叫"回車", 就是回到最左邊! // (6)跳頁字符(Form Feed), 用 '\f' 表示, 就是往下跳到下一頁的意思 ///P.S. 輸出資料時常常用 \n 換到下一列, /// 但很多們不知道 \t 很有用, 如果你想把資料印整齊, \t 就很好用! /// 例如, 你可以試試 printf("123\t45678\tab\thahaha\thehe看看\n"); ///// // 在 Windows/DOS 系統下, 按 ENTER 鍵會產生 '\r' 和 '\n' 或稱 CR LF, // 但是, 在 Unix 系統則只有 '\n' (NewLine, 或稱 LF, Line Feed) 一個 char // 所以用FTP軟體把文字檔用ASCII文字模式從Windows/DOS 送到Unix時檔案大小會變小! /// 但是, 請注意, 你用 fgetc 或是 getchar 去讀資料的時候, /// 你可能發現即使在 Windows 之下也讀不到 '\r', 這是因為它會把 '\r' 與 '\n' /// 合起來看做一個 char '\n', 這樣用起來會與 Unix 一樣! ///// 如果你堅持一定要讓 fgetc 可以讀到 '\r' (內碼是 13), ///// 那你必須先把檔案開啟成 Binary 模式! 例如: ///// FILE * fp = fopen("ggyy.txt", "rb"); // read, binary mode ///// 這樣, 用 int c = fgetc(fp); 就有可能讀到 '\r' ////// 又請注意, getchar( ) 是等於 fgetc(stdin), 且 stdin (鍵盤, 標準輸入)是 ////// 被預設開啟為文字模式 (Text mode, 又稱 ASCII mode, 雖然並非所有電腦都用 ASCII!) ////// 所以, 若你想從鍵盤讀資料也要能讀到 '\r', 可以這樣: ////// FILE* fp = fopen("con", "rb"); //////// ==> con 就是鍵盤在 Windows/DOS 的名稱 ! 所以無法生出名稱 con 的檔案 ////// 然後 int c = fgetc(fp); 就會從鍵盤讀任何資料, 這時按 ENTER 鍵會等於兩個 char, ////// 會先讀到 '\r' (內碼是 13), 然後又讀到 '\n' (內碼是 10) ////// 最後還要注意, EOF 在 DOS/Windows 是以敲入 CTRL_Z 代表,UNIX 用 CTRL_D 代表! ////// fgetc 或 getchar 讀到 EOF 時是傳回來整數的 -1, ////// 這時用 feof(fp) 也會查到 EOF (End Of File) 是成立的! 若從鍵盤則 fp 是 stdin #include #include int main( ) { int i, kk; printf("123\t45678\tab\thahaha\thehe看看\\t\n"); printf(" code of \\f is %d\n", '\f'); printf(" code of \\n is %d, code of \\r is %d\n", '\n', '\r'); printf(" code of \\t is %d, code of \\v is %d\n", '\t', '\v'); printf("Test isupper(int)... %c %d : %d", 'A', 'A', isupper('A')); printf("\nTest isupper(int)... %c %d : %d", 'a', 'a', isupper('a')); printf("\nTest islower(int)... %c %d : %d", 'A', 'A', islower('A')); printf("\nTest islower(int)... %c %d : %d", 'a', 'a', islower('a')); printf("\nTest isalpha(int)... %c %d : %d", 'A', 'A', isalpha('A')); printf("\nTest isalpha(int)... %c %d : %d", 'a', 'a', isalpha('a')); printf("\nTest isdigit(int)... %c %d : %d", 'a', 'a', isdigit('a')); printf("\nTest isdigit(int)... %c %d : %d", '3', '3', isdigit('3')); printf("\nTest isspace(int)...空白是 %d\n", ' '); for(i=0; i<=127; ++i) { kk = isspace(i); if(kk) printf("%3d :%d ", i, kk); } printf("\nTest isdigit(int)...\n"); for(i=0; i<=127; ++i) { kk = isdigit(i); if(kk) printf("%3d :%d ", i, kk); } printf("\nTest iscntrl(int)...控制符號\n"); for(i=0; i<=127; ++i) { kk = iscntrl(i); if(kk) printf("%3d :%d ", i, kk); } printf("\nHit ENTER key..."); getchar( ); } int myIsUp(int x) { return x>='A' && x<='Z'; } // 1 or 0 int myIsLow(int x) { return x>='a' && x<='z' ? 2 : 0; } // 2 or 0 int myIsAlpha(int x) { if( myIsUp(x) ) return myIsUp(x); if( myIsLow(x) ) return myIsLow(x); return 0; } // OK int myIsDigit(int x) { return x>='0' && x<='9' ? 4 : 0; } // 4 or 0 int myIsSp(int x) { // isspace(int) if(x=='\t' || x == '\n' || x == '\r') return 8; if(x=='\v' || x == '\f' || x == ' ') return 8; return 0; } // 8 or 0 for isspace(int) /***** 123 45678 ab hahaha hehe看看\t code of \f is 12 code of \n is 10, code of \r is 13 code of \t is 9, code of \v is 11 Test isupper(int)... A 65 : 1 Test isupper(int)... a 97 : 0 Test islower(int)... A 65 : 0 Test islower(int)... a 97 : 2 Test isalpha(int)... A 65 : 1 Test isalpha(int)... a 97 : 2 Test isdigit(int)... a 97 : 0 Test isdigit(int)... 3 51 : 4 Test isspace(int)...空白是 32 9 :8 10 :8 11 :8 12 :8 13 :8 32 :8 Test isdigit(int)... 48 :4 49 :4 50 :4 51 :4 52 :4 53 :4 54 :4 55 :4 56 :4 57 :4 Test iscntrl(int)...控制符號 0 :32 1 :32 2 :32 3 :32 4 :32 5 :32 6 :32 7 :32 8 :32 9 :32 10 :32 11 :32 12 :32 13 :32 14 :32 15 :32 16 :32 17 :32 18 :32 19 :32 20 :32 21 :32 22 :32 23 :32 24 :32 25 :32 26 :32 27 :32 28 :32 29 :32 30 :32 31 :32 127 :32 Hit ENTER key... == =============== === *******************************/