補充: Input from a text file 基礎講解 Text file 的構造與讀取 讀資料函數 (scanf & gets) 基本字串教學 例題講解: H.88.1 歷年題目
Text file 的構造與讀取 Text file 由 ASCII code 組成 英文字母 ('A' - 'Z','a' - 'z') 數字 ('0' - '9') 常用符號 (如分號,逗號等等) 控制字元 (如換行,檔案結束, tab等等)
用 notepad 寫的 text file 的例子 h i s a m p l e
Text file 實際儲存的狀況 End of Line EOF T h i s a m p l e
開檔與讀檔時的內部動作 開檔 讀檔 檔案指標 (file descriptor pointer) 指向檔案開頭 (0) 依照函數的定義,從目前 fp 所在的位址,向後讀取資料 1 2 3 4 5 6 7 8 T h i s 9 10 11 12 13 14 15 16 17 a 18 19 20 21 22 23 24 25 26 m p l e 27
讀資料函數 - scanf() char buf[100]; int i; scanf(“%s”, buf); double f; 找到第一個非空白字元,向後讀一個 block,碰到空白,tab,換行符號,檔案結尾 (EOF) 停下 鍵盤輸入 s abc df buf = “abc” int i; double f; scanf(“%d”, &i); scanf(“%lf”, &f); 讀一個 integer/ double 鍵盤輸入 332 22 i = 332
scanf(“%c”, &ch); 讀一個 character,空白, tab,換行符號都會被讀入 H e l o Enter ch = ‘H’ ch = ‘l’ ch = ‘l’ ch = ‘e’ ch = ‘l’ ch = ‘\n’
練習 scanf(“%c”, &c); scanf(“%s”, buf); scanf(“%d”, &i); a b c 3 1 2 d e
答案 scanf(“%c”, &c); //a scanf(“%s”, buf); //bc scanf(“%d”, &i); //3 scanf(“%s”, buf); //dd a b c 3 1 2 d e
讀資料函數 - gets() gets(buf); 鍵盤 abcd ef s gh ijkl m buf = " abcd ef " buf = " gh ijkl" buf = "m"
scanf() gets() 讀到檔案結尾 (EOF) 回傳 EOF 從目前的位置到讀完換行 讀到檔案結尾 (EOF) 回傳 NULL
綜合練習 scanf(“%c”, &c); scanf(“%s”, buf); gets(buf); scanf(“%d”, &i); a 3 1 2 d e
答案 scanf(“%c”, &c); //a scanf(“%s”, buf); //bc gets(buf); // “ 3” scanf(“%d”, &i); //123 gets(buf); //空字串 gets(buf); //dd e s scanf(“%c”, &c); //return EOF a b c 3 1 2 d e
程式須知 scanf() 與 gets() 避免混用 gets() 讀到比預設長度還大的字串,會發生不可預知的結果 換行與 EOF 兩者處理方式不同,易出錯 gets() 讀到比預設長度還大的字串,會發生不可預知的結果
基本字串教學: 字串陣列的表示方式 str = “hello world” C從0開始算 結束字元 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 11 h e l o w r d \0
結束字元 字串 array 的最後字元 要放長度 20 的字串,需要宣告 21 個字元組 (bytes)
字串可當作陣列存取 str = “hello world” str[2] = ‘l’, str[5] = ‘ ‘, str[11] = ‘\0’ C 中用雙引號括字串,單引號括字元 1 2 3 4 5 6 7 8 9 10 11 h e l o w r d \0
宣告字串並同時給予初始值 將 "abc" 於宣告時存入 str 中的兩個方式 main() { char str[100] = “abc”; }
程式中間字串給予值 程式中將 "abc" 存入 str 的兩種方式 一定要加入結束字元 main() { char str[100]; str[0] = ‘a’; str[1] = ‘b’; str[2] = ‘c’; str[3] = ‘\0’; //strcpy(str, "abc"); } 一定要加入結束字元
例題講解: A.455 (http://acm.uva.es/p/v4/455.html) 給 n 個字串,求每個字串的最短重複週期 長度相等 abcabcabcabc abc abcabc abcabcabcabc
Sample input/output Sample input: 1 HoHoHo Sample output: 2 總共會有幾組 test case 輸入字串
讀進 input 需要的資料結構 int str_num 總共有幾個 test case char str[100] 字串最長 80
解法 只有字串長度的因數才有可能是週期 將可能的週期由小到大測試,找到答案就停止
Program structure read_str_num(); for ( i = 0; i < str_num; i++){ len = strlen(str); for (j = 1; j < len; j++){ if(( len% j ) == 0){ //只有因數才測 if(str_period(str, j) == 1) // j是否 str 的週期 break; //跳出 for 迴圈 } printf(“%d\n\n”, j);
測週期 int str_period(str, j) { int k; for(k = j ; k < len ; k++) if(buf[k] != buf[k%j]) break; //不相等跳 //出 for 迴圈 if(k == len) return 1; //字串結束都相等 else return 0; }
Program #include <stdio.h> #include <string.h> int main(void) { int str_num, i, j, k, len; char str[100]; scanf(“%d”, &str_num); for(i = 0; i < str_num ; i++) { scanf(“%s”, str); len = strlen(str); for(j = 1; j < len ; j++) { if((len% j ) == 0) { //只有因數才測 for(k = i ; k < len ; k++) if(buf[k] != buf[k%j]) break; //不相等跳出 for 迴圈 if(k == len) break; //字串結束都相等 } printf(“%d\n\n”, j); //題目要求多印一個空白行
歷年題目 練習題 挑戰題 其他歷年題目 A.455 Periodic String A.458 The Decoder http://acm.uva.es/p/v4/455.html A.458 The Decoder http://acm.uva.es/p/v4/458.html A.401 Palindromes http://acm.uva.es/p/v4/401.html 挑戰題 A.400 Unix ls http://acm.uva.es/p/v4/400.html 其他歷年題目 無