__________________ 學號: 姓名: 思考和讀書都很重要! ___________ ______________ 阿就是不要只是死讀書啦! 我們常常推薦使用的 fgets(char* s, int n, FILE* fp) 函數也很值得研究!思考! 這函數(function;函式)其實很單純, 它只是利用 fgetc(FILE* fp) 一直讀 char放入 s, 直到讀到 '\n' 或是已經讀進了 n-1 個 char 就不再讀, 這時不論是因已經讀入 '\n' 或是已經讀了 n-1 個 char 都要補上 '\0' 做為 字串 s 的結束! 還有, 依照 fgets( ) 的手冊, 若啥都沒讀到(遇到 EOF)則回傳 0, 否則須回傳 s 的起始位址。參看 K&R 課本 7.7 節的詳細說明與 fgets( ) 程式碼。 /** 關於 fgetc(FILE* fp) 與 getc(FILE* fp) 以及 getchar( ); Declaration: int getc(FILE *stream); // 參看 K&R 課本 7.5節 int fgetc(FILE *stream); getchar( ) is a macro defined as getc(stdin); getc is a macro that gets one character from stream. fgetc returns the next character on the named input stream. It is a function version of the getc macro. On end-of-file or error, fgetc returns EOF ( 註: EOF 就是整數 -1 ) __________________________ char* fgets(char* s, int n, FILE* stream); *** 以下抄自 TC 內打 fgets 敲 Control_F1 後看到的說明 (用 TC++3.0的IDE整合環境) fgets reads characters from stream into the string s. It stops when it reads either n - 1 characters or a newline character, whichever comes first. fgets retains the newline character at the end of s and appends a null byte to s to mark the end of the string. ... Return Value: ■ On success, ■ fgets returns the string pointed to by s. ■ On end-of-file or error, fgets returns null. // 就是 '\0' 也是 0 啦! ***************************************************************************/ (1)請把上面這段抄自 TC 內關於 fgets( )的 help 翻譯成中文。 (2)函數 fgets( ) 其實是叫別人去一次讀入一char然後放入第一個參數所指之處! 請用fgetc(FILE* fp)寫出 char * fgets(char* s, int n, FILE* fp); 這函數, 這題現在規定用 for( ;; ) 做一直讀的工作, 當然裡面要用到 if(...)break; 不太會的請參考 K&R 課本 1.9 節的 getline( ) 和 4.1 節的 getline( ); 但是注意 K&R 課本的 getline( )只有兩個參數, 因它們是用 getchar( ) 從鍵盤讀, 但 fgetc( ) 與 getc( )和 fgets( )是從參數的檔案串流(FILE stream)讀取! 所以要用 fgetc(FILE* fp) 或是 getc(FILE* fp); 其實 fgetc 和 getc 是同一個! 還有, 課本上的 getline 是傳回讀到幾個字, 但 fgets( ) 是傳回一個 char*, 它要指向第一個參數最開始的位址, 也就是你必須寫成像如下: char * fgets(char* s, int n, FILE* fp) { char* p = s; // 就是 p = &s[0]; // p points to s[0]; for( ;; ) { // ...用 fgetc(fp) 至多讀取 n-1 個字 // ..注意不可以改 s, 因最後要 return s; 但你可以改它的複製品 p // ..可參看 K&R 課本7.7節 fgets( ) 以及 1.9 節與 4.1 節的getline( ) // ..但這題現在規定不可用像課本範例用精簡寫法! 要寫得讓人容易看懂!!! } // 若啥都沒讀到就遇到 EOF 則回傳 0, 且不可把 EOF 與 '\0' 填入 s 喔 // 記得最後要補上 '\0' 讓字串結束! 課本7.7節啥都沒讀到也會塞0是不對的! return s; // 若你在上面 for LOOP 中也沒改 p, 則不必複製 p } (3)請用中文說明 int fgetc(FILE* fp); 這函數大概怎麼寫的? 可以用中文pseudo code 寫, 不必真的寫C程式! Hint: 看 K&R 課本 8.5 節。 (4)研究 K&R 課本3.4 節 用 switch .. case 以及 1.6 節用 if..else 寫的 統計讀入資料中各種字出現次數的程式, 然後寫出至少 88 字的研究心得。 注意該兩個範例檢查 white space 只有看三個: ' ', '\t', '\n' 這樣不夠! 但是依照 white space 的定義, 應該有六個, 另外三個是 '\v', '\r', '\f' 所以課本上有強調該統計程式並不實用! 關於 white space(廣義空白;不是白色恐怖), 可以使用 Library 的 isspace(int) 檢查, 這樣會使程式更容易讓人了解! 關於 isspace(int) 及其他類似函數以及大小寫轉換可以參看 K&R 課本附錄 B.2節。 isspace(int), isalpha(int), toupper(int), ... 等宣告在 內。 (5)寫一個程式可以把 white space 的六個字符(字元)的 ASCII值依序用整數印出對照。 Hint: printf("TAB == '\\t' == %d\n", '\t' ); // 程式內寫六個 printf ANS: (請依序作答, 請寫到背面! 不可再用其它紙!) 寫上學號姓名, 下次上課拿來繳交!