# File I/O [toc] ## 開啟檔案 ```c= FILE *fptr; fptr = fopen("filename.txt" , "mode"); ``` ### **FILE \*fptr** - 宣告一個變數,名稱為fptr,類型為FILE - \* (pointer) 代表fptr指向檔案存取的位址 ### **filename.txt** - 第一個參數代表我們要開啟的檔案, - 預設路徑為cpp source code存放位址 - 回傳值為該檔案的位址 ### **mode** - 代表我們想要對該檔案執行的動作類型 - 常見類型: | mode | meaning | |:-------- |:--------| | "r" | **read:** 開啟檔案作為輸入來源 | | "w" | **write:** 建立一個新檔案儲存輸出資訊,如果同樣檔名的檔案已經存在,則該檔案內容會被捨棄並被視為一個empty file | | "a" | **append:** 開啟一個檔案做為輸出並在該檔案的最後一行新增輸出資訊。如果該檔案不在則會新增一個檔案 | ## 處理檔案 ### 讀取檔案中的字 跟`scanf()`類似,只不過需要多一個參數:file pointer - fscanf( ) - ``fscanf(file pointer, “datatype”, data variable)`` - 從檔案中讀取資料並存在指定類型的變數中 - fgetc( ) - ``variable = fgetc(filepointer)`` - 讀取目前filepointer所在位址的一個字元,並回傳該字元 - fgets( ) - ``fgets(string, num, file pointer)`` - 讀取目前filepointer所在位址的一串字元,直到讀取了``num-1``個字元為止,並將其作為string儲存 **Example**: ```c= int main() { FILE *fptr; fptr = fopen("input.txt","r"); int num1 = 0, num2 = 0; char c1, c2; char str[5]; // check whether the file is open if(fptr != NULL) { fscanf(fptr, "%d %d", &num1, &num2); printf("%d %d\n", num1, num2); c1 = fgetc(fptr); c2 = fgetc(fptr); printf("%c %c\n", c1, c2); fgets(str, 5 , fptr); printf("%s\n", str); } else { printf("fail to open 'input.txt'."); } fclose(fptr); } ``` ### 在檔案上寫字 跟`printf()`類似,只不過需要多一個參數:file pointer - fprintf() - `fprintf(file pointer, “datatype”, data variable)` - 在檔案上pointer的位址輸出標準字串 - fputc() - `fputc(char, file pointer)` - 在檔案上pointer的位址輸出一個字元 - fputs() - `fputs(string, file pointer)` - 在檔案上pointer的位址輸出一個字串 **Example**: ```c= int main() { FILE *fptr; fptr = fopen("output.txt","w"); int num 25; // check whether the file is open if(fptr != NULL) { fprintf(fptr,"Below are your message:\n%d\n",num); fputc('~',fptr); fputs("I want to sleep all day.",fptr); } else { printf("fail to open 'output.txt'."); } fclose(fptr); } ``` ### 重新設置字串位置指標 - fseek() - `fseek(file pointer, offset, reference position)` - 根據參考位址以及數值,重新設定file pointer位址 | reference position | meaning | |:------------------- |:-------- | | SEEK_SET | 檔案的開頭 | | SEEK_CUR | 檔案目前的位址 | | SEEK_END | 檔案目前的尾端 | **Example**: - 檔案: <img style="margin:20px auto;padding:1px;border:1px #eee;width:20%;" src="https://i.imgur.com/lvJv3Nk.png" /> - 未使用fseek() ```c= int main() { FILE *fptr; fptr = fopen("input.txt","r"); char c1; // check whether the file is open if(fptr != NULL) { while(c1 = fgetc(fptr) != EOF) { c1 = fgetc(fptr); printf("%c", c1); } } } ``` - 使用fseek() ```c= int main() { FILE *fptr; fptr = fopen("input.txt","r"); char c1; // check whether the file is open if(fptr != NULL) { while(c1 = fgetc(fptr) != EOF) { fseek(fptr,-1,SEEK_CUR); c1 = fgetc(fptr); printf("%c", c1); } } } ``` - 輸出:左:未使用`fseek( )`;右:使用`fseek( )` <img style="margin:28px auto;padding:1px;border:5px #eee;width:40%;" src="https://i.imgur.com/xr6p7ab.png" /> <img style="margin:28px auto;padding:1px;border:5px #eee;width:36%;" src="https://i.imgur.com/BDD8cvX.png" /> ## 關閉檔案 ### fclose(fptr) - 關閉檔案 - 釋出記憶體空間 - 不把檔案關閉的話可能會造成fprintf()的異常 :::info :bulb: 同時開的檔案數量有限,因此我們需要關閉不必要的檔案以節省記憶體空間 ::: :::success ## :bulb:Exercise 1. ```c= #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int main() { FILE* fptr; fptr = fopen("input.txt", "r"); int n=0, m=0; char arr[50][50]; if (fptr != NULL) { fscanf(fptr, "%d %d", &n, &m); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { arr[i][j] = 'H'; } } int k; fscanf(fptr, "%d", &k); int r, c; for (int i = 0; i < k; i++) { fscanf(fptr, "%d %d", &c, &r); arr[c][r] = ' '; } } else { printf("fail to open 'input.txt'."); } FILE* fptr2; fptr2 = fopen("output.txt", "w"); if (fptr2 != NULL) { for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { fprintf(fptr2, "%c", arr[i][j]); } fputc('\n', fptr2); } } else { printf("fail to open 'output.txt'."); } fclose(fptr2); } ``` ::: :::info ## :bulb:Homework 1. ```c= #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { FILE* fptr; FILE* fptr2; fptr = fopen("input.txt", "r"); fptr2 = fopen("output.txt", "w"); int num; char spec[15][15],input; scanf("%d", &num); for (int i = 0; i < num; i++) { scanf("%s", spec[i]); } int result = 1; bool bo = 0; if (fptr != NULL && fptr2 != NULL) { char c; while (fgetc(fptr) != EOF) { char str[15]; fseek(fptr, -1, SEEK_CUR); for(int j=0 ; j<15 ; j++) { c = fgetc(fptr); if (((int)c >= 65 && (int)c <= 90) || ((int)c >= 97 && (int)c <= 122)) { str[j] = c; } else { str[j] = '\0'; if (j == 0) { fputc(c,fptr2); break; } for (int k = 0; k < num; k++) { result = strcmp(str, spec[k]); if (result == 0) { break; } } if (result == 0) fprintf(fptr2, "***%c", c); else fprintf(fptr2, "%s%c", str, c); break; } } } } else { printf("Failed to open 'input.txt' or 'output.txt'."); } fclose(fptr); fclose(fptr2); } ``` :::