複習 struct score_Type{ int chinese,english; }; struct my_Type{ char name[128]; int age; score_Type score; int main(){ struct my_Type student; strcpy(student.name,”David”); student.age=25; scanf(“%d %d”,&student.score.chinese,& student.score.english); }
複習 enum color{ RED, GREEN,BLUE }; int main(){ color background; scanf(“%d”,&background); if(background==RED){ printf(“RED\n”); } else if(background==GREEN){ printf(“GREEN\n”); else{ printf(“BLUE\n”);
Class 8 檔案處理
想一想 如果我們不僅僅想要將程式執行的結果輸出在螢幕上,而是想輸出到檔案中,該怎麼做呢? C語言提供了許多檔案處理的函式 把printf的結果轉到一個檔案中 檔案處理 C語言提供了許多檔案處理的函式 需要搭配一個資料型態為FILE的指標來使用
檔案指標 檔案指標指向一個含有檔案資訊的結構 資訊包括 使用者不需知道檔案指標的細節,所有定義可由<stdio.h>獲得 緩衝區的位置 緩衡區內現在字元的位置 目前檔案正在被讀取、寫入或檔案結束 使用者不需知道檔案指標的細節,所有定義可由<stdio.h>獲得 就像printf()我們只需include而不需寫定義一樣
檔案指標 2 FILE *fp; fp是一個指標指向FILE FILE就像int只是一個型別名稱 在<stdio.h>中用typedef定義,而不是一個結構標籤 C函式庫中已經宣告好3個FILE *的指標,分別是stdin、stdout、stderr printf("...")事實上是呼叫fprintf( stdout, "....") scanf("...")事實上是呼叫fsanf( stdin, "..." ) fprintf( stderr, "....")所印在螢幕上的東西不會被輸出轉向所影響
檔案格式 C的函式可以用來建立兩種格式的檔案 文字檔案格式(text file) 二元檔案格式(binary file) 將資料轉換成字元的格式存入檔案 存放的東西都是肉眼可視的英文字母或數字符號等 二元檔案格式(binary file) 將數值的內容原封不動使用它的二進位方式直接存入檔案中
檔案格式 2 int a=100000; 用途 若用文字檔來存,存下來的會是”100000”這個字串,佔7個byte 若用二進位檔來存,存下來的是0x186A0的的二進位值,固定佔4個byte,因為int型態就是占4個byte 用途 文字檔格式通常用來列印報表,或是讀入人為製作的檔案 二元檔案處理速度快、佔的空間小
檔案處理流程
開啟檔案與關閉檔案 fopen 開啟檔案 fclose 關閉檔案
fopen 程式中叫用的方法如: 第一個參數是字串,指出檔案名稱 第二個參數是模式,也是一個字串 模式有r、w、a三種: fp = fopen(name, mode); 第一個參數是字串,指出檔案名稱 第二個參數是模式,也是一個字串 模式有r、w、a三種: r :唯讀模式(read) w :寫入模式(write) a :增加模式(append),從檔案最後面繼續寫入 如果希望同時擁有讀寫檔案的權利,可以在模式字串加+ r+ :以主模式r開啟檔案 w+ :以主模式w開啟檔案 a+ :以主模式a開啟檔案
fopen 2 希望以二元模式開啟時,可以在模式字串加b 打開一個不存在的檔案來寫入或附加在檔案尾端 rb:代表以唯讀模式即二元檔案格式開啟 打開一個不存在的檔案來寫入或附加在檔案尾端 檔案必須儘可能先被建立 打開一個存在的檔案寫入時,舊的檔案內容會被刪除 若是增加模式(a)就會保留它們,並寫入到檔案尾端 嘗試讀一個不存在的檔案會造成錯誤,讀取一個不被允許讀取的檔案也會產生錯誤 假如有錯誤產生 fopen 會傳回NULL
fclose fclose(FILE *fp); 在檔案不用時,關閉該檔案 關閉檔案時會強迫仍在電腦緩衝區的所有資料才真正輸出到檔案裡頭
範例練習 自己製作一個test.txt檔案,並利用fopen開啟該檔案 若成功開啟則不會有錯誤訊息,反之會有錯誤訊息
讀/寫檔案 fprintf(FILE *p, ...) 除了前面加個檔案指標外,其餘與printf()一樣 範例練習:開啟test.txt檔案,並嘗試寫入一些訊息
課堂練習 讓使用者可以輸入多個學生姓名和成績後,輸出到檔案student.txt 使用者可以按0離開成績輸入系統或按其他鍵繼續輸入 提示:while(1) 配合break;
fscanf() fscanf(FILE *p, ...) 除了前面加個檔案指標外,其餘與scanf()一樣 注意:通常fprintf()和fscanf()都是用來處理文字格式檔案
fread() fread(pointer to variable, item size, item number, FILE *fp) 從fp所指到的檔案讀一個整數(4 bytes)到num所指的記憶體 int num; fread(&num, sizeof(int), 1, fp); 從fp所指到的檔案讀一個字串(10 bytes)到str所指的記憶體 char str[10]; fread(str, sizeof(str), 1, fp);
fwrite() fwrite(pointer to variable, item size, item number, FILE *fp) 從num所指的位址寫一個整數(4 bytes)到fp所指的檔案之中 fwrite(&num, sizeof(int), 1, fp); 注意 通常fread()和fwrite()都是用來處理二元格式檔案
get v.s. put fgetc(FILE *fp) fputc(int c, FILE *fp) printf("We read a character %c from the file.\n",fgetc(fp)); fputc(int c, FILE *fp) 將字元c寫入fp所指的檔案。 scanf("%c",&ch); fputc(ch, fp); fgets(char *buffer, int max_char_num, FILE *fp) 從fp所指到的檔案讀入一個字串到buffer,最多只允許max_char_num-1個字元 與gets()不同的是,fgets()函式會保留換行字元 fputs(const char *str, FILE *fp) 將str這個字串的內容寫到fp所指的檔案裡面 與puts()不同的是,fputs()不會自動加上換行字元
其他檔案處理函式 feof(FILE *fp) 用來判斷檔案游標是否已經到了檔案的結尾 if(feof(fp)) printf("We reach the end-of-file.\n"); 課堂練習:用文字編輯器編好一個資料檔,接著撰寫一個程式將資料檔的內容印出。(fscanf())
補充 1 2 3 J A C EOF 1 2 3 J A C \n EOF 寫法一 fscanf(fin,”%s”,line); while(!feof(fin)){ fscanf(fin,”%s”,line); printf(“%s\n”,line); } 適用情況(結尾沒空白or換行) 不適用(結尾有空白or換行) ↓ ↓ 1 2 3 J A C EOF ↓ ↓ ↓ 1 2 3 J A C \n EOF
補充 1 2 3 J A C EOF 1 2 3 J A C \n EOF 寫法二 fscanf(fin,”%s”,line); while(1){ fscanf(fin,”%s”,line); if(feof(fin))break; printf(“%s\n”,line); } 不適用情況(結尾沒空白or換行) 適用(結尾有空白or換行) ↓ ↓ 1 2 3 J A C EOF ↓ ↓ ↓ 1 2 3 J A C \n EOF
其他檔案處理函式 2 ferror(FILE *fp) rewind(FILE *fp) 用來判斷檔案讀寫是否出現問題 if(ferror(fp)) printf("We encounter file access error.\n"); rewind(FILE *fp) 將檔案游標重設到檔案的開頭,並將錯誤旗標(flag)重設
fseek() fseek(FILE *fp, how man bytes to move, where to start) SEEK_SET 表示從檔案開頭起算 SEEK_CUR 表示目前游標位置起算 SEEK_END 表示從檔案結尾起算 how many bytes 正值表示往檔案結尾移動,負值表示往開頭 fseek(fp,0,SEEK_SET); //跟rewind一樣移到檔案開頭 fseek(fp,1,SEEK_CUR); //檔案指標向後移動一個byte
檔案游標移動實例
檔案處理函式原型和回傳值 FILE fopen(const char *,const char *) 成功傳回檔案指標,失敗傳回NULL int fclose(FILE *) 成功傳回0,失敗傳回EOF int fprintf(FILE *, const char *, ...) 傳回寫出字元個數,失敗傳回EOF int fscanf(FILE *, const char *, ...) 傳回讀入字元個數,失敗傳回EOF int fread(void *, size_t, sizet, FILE *) 傳回讀入項目個數 int fwrite(void *, size_t, sizet, FILE *) 傳回寫出項目個數 int fseek(FILE *, int, int) 成功傳回0,失敗傳回非0值 void rewind(FILE *) int feof(FILE *) 已到檔尾傳回非零值,否則傳回0 int ferror(FILE *) 發生錯誤傳回非零值,否則傳回0 void perror(const char *)
exit() 被叫用時,程式終止執行 參數由程式自行設定 exit會對每個打開的輸出檔案叫用 fclose,強迫清光任何一個緩衝區 if( (fp=fopen(fname,"r")) == NULL ) { printf("The file doesn't exist.\n"); exit(0); } 參數由程式自行設定 一般來說傳入的值是 0 則通知執行成功 非零則表示有不正常的情況 exit會對每個打開的輸出檔案叫用 fclose,強迫清光任何一個緩衝區
綜合練習 綜合練習1 請將toUpper.txt檔案內容讀入,將其轉為大寫,並輸出到檔案UpResult.txt 綜合練習2: (47.14) score.txt檔案是全班50位同學的的考試成績,試著讀入它,並算出全班的平均成績輸出在螢幕上 綜合練習3: (53.74) score2.txt是另一種格式的檔案,同樣是50位同學的成績,試者讀入它,並算出全班同學的平均成績輸出在螢幕上
考前複習 給一個陣列 函式+指標的使用 結構 字串的處理 如何找出最大值 如何排序 =>氣泡排序 如何搜尋裡面的資料 => 二元搜尋 函式+指標的使用 如何傳陣列進去 結構 如何定義自己的資料型態 => struct 字串的處理 如何複製一個字串 如何將字串轉為大寫or小寫 如何比較字串大小or是否相等
考前複習 檔案 亂數 其他 如何開檔或寫檔 =>fprintf,fopen,fscanf,fclose,feof 如何產生一特定範圍的亂數 (rand()%(最大-最小+1)+最小 其他 如何判斷是否被整除 scanf何時要加& 如何輸入有空白的字串 …