【C语言重点难点精讲】C语言文件
文章目錄
- 一:文件相關(guān)概念
- (1)什么是文件
- (2)文件名
- (3)文件類型
- 二:文件指針
- 三:文件的打開和關(guān)閉
- 四:文件的順序讀寫
- (1)寫
- (2)讀
- 五:文件的隨機(jī)讀取
- (1)fseek
- (2)ftell
- (3)rewind
- 六:文件結(jié)束條件判定
- 七:其它注意點(diǎn)
一:文件相關(guān)概念
(1)什么是文件
我們在磁盤上所見到的都是文件,在程序設(shè)計(jì)中,所談到文件主要有兩種:
- 一種是程序文件:包括源程序文件(后綴為.c),目標(biāo)文件(windows環(huán)境后綴為.obj),可執(zhí)行程序(windows環(huán)境后綴為.exe);
- 另一種是數(shù)據(jù)文件:文件的內(nèi)容不一定是程序,也可以是程序運(yùn)行時(shí)讀寫的數(shù)據(jù),比如程序運(yùn)行需要從中讀取數(shù)據(jù)的文件,或者輸出內(nèi)容的文件
本節(jié)主要討論的是數(shù)據(jù)文件
(2)文件名
一個(gè)文件有“文件路徑+文件主干+文件后綴”三部分組成,為了方便起見,文件表示也被稱為文件名
(3)文件類型
數(shù)據(jù)文件可以被分為文本文件和二進(jìn)制文件
- 舉個(gè)例子,程序里有個(gè)變量是10000,如果要把它放到磁盤里,你想要讓用戶讀懂那么你肯定要用字符表示,也就是1對應(yīng)的ASCII碼,2對應(yīng)的ASCII碼,這樣去轉(zhuǎn)換,那么這種就是文本。如果不經(jīng)過任何轉(zhuǎn)換,就是二進(jìn)制文件(使用記事本方式打開exe文件時(shí)的亂碼)
如下程序代碼表示將數(shù)字10000用存儲為二進(jìn)制文件
int main() {int a = 10000;FILE* pf = fopen("test.txt", "wb");fwrite(&a, 4, 1, pf);//二進(jìn)制寫fclose(pf);pf = NULL;return 0; }雖然顯示的是txt文件,但是其本質(zhì)是二進(jìn)制文件,所以用記事本打開是亂碼
要去看到到底是什么,可以用VS,使用二進(jìn)制編輯器打開
二:文件指針
每一個(gè)使用的文件,在內(nèi)存中都會(huì)開辟一個(gè)文件信息區(qū),這個(gè)文件信息區(qū)存放的是文件的名字,文件的狀態(tài)等等,所有的這些信息存放在一個(gè)結(jié)構(gòu)體變量中,將其取名為FILE
既然它是結(jié)構(gòu)體變量,那么我們就可以創(chuàng)建一個(gè)指針去操作它,這個(gè)指針也就被稱為文件指針
pf是一個(gè)指向FILE類型的數(shù)據(jù)變量,可以使pf指向某個(gè)文件的文件信息區(qū)(是一個(gè)結(jié)構(gòu)體變量)。通過該文件信息區(qū)中的信息就可以訪問該文件
三:文件的打開和關(guān)閉
文件讀寫時(shí)先打開文件,再關(guān)閉文件
在打開文件的時(shí)候,會(huì)返回一個(gè)File*的指針,C語言規(guī)定使用fopen打開文件,fclose關(guān)閉文件
mode選項(xiàng)有如下幾種
int main() { FILE* pf = fopen("test.txt", "r"); if (pf == NULL) {printf("%s\n", strerror(errno));return 0; } fclose(pf); pf == NULL; return 0; }四:文件的順序讀寫
讀寫函數(shù)如下
注意標(biāo)準(zhǔn)輸入流和標(biāo)準(zhǔn)輸入流
int main() {char arr[1024] = { 0 };fgets(arr, 1024, stdin);//鍵盤就是標(biāo)準(zhǔn)輸入流fputs(arr, stdout);//屏幕是標(biāo)準(zhǔn)輸出流 }注意這幾組函數(shù)
- scanf和printf是針對標(biāo)準(zhǔn)輸入/輸出流的格式化輸入/輸出語句
- fscanf和fprintf是針對所有輸入/輸出流的格式化輸入/輸出語句
- sscanf是從字符串中讀取格式化的數(shù)據(jù)
- sprintf是把格式化數(shù)據(jù)輸出到字符串
(1)寫
1:字符輸出
int main() {FILE* pfwrite = fopen("test.txt", "w");if (pfwrite == NULL) {printf("%s\n", strerror(errno);return 0;}fputc('L', pfwrite);fputc('o', pfwrite);fputc('v', pfwrite);fputc('E', pfwrite);fclose(pfwrite);pfwrite = NULL;return 0; }2:文本行輸出,其中換行需要手動(dòng)加入
int main() {FILE* pfwrite = fopen("test.txt", "w");if (pfwrite == NULL) {printf("%s\n", strerror(errno));return 0;}fputs("I\n", pfwrite);fputs("LOVE\n", pfwrite);fputs("YOU", pfwrite);return 0; }3:格式化輸出
struct S {int n;float score;char arr[10]; };int main() {struct S s = { 100,3.14f,"love" };FILE* pfwrite = fopen("test.txt", "w");if (pfwrite == NULL) {printf("%s\n", strerror(errno));return 0;}fprintf(pfwrite, "%d-%f-%s", s.n, s.score, s.arr);//格式化輸出return 0; }4:二進(jìn)制輸出
struct S {char arr[10];int age; };int main() {struct S s = { "Bob",19};FILE* pfwrite = fopen("test.txt", "wb");//二進(jìn)制if (pfwrite == NULL) {printf("%s\n", strerror(errno));return 0;}fwrite(&s, sizeof(struct S), 1, pfwrite);return 0; }(2)讀
1:字符讀入
int main() {FILE* pfread = fopen("test.txt", "r");if (pfread == NULL) {printf("%s\n", strerror(errno));return 0;}printf("%c", fgetc(pfread));printf("%c", fgetc(pfread));printf("%c", fgetc(pfread));printf("%c", fgetc(pfread));printf("%c", fgetc(pfread));return 0; }2:文本行輸入,可以獲得換行符
int main() {FILE* pfread = fopen("test.txt", "r");if (pfread == NULL) {printf("%s\n", strerror(errno));return 0;}char a[20];fgets(a, 6, pfread);//讀一行6個(gè)字符printf("%s\n", a);return 0; }3:格式化輸入
struct S {int n;float score;char arr[10]; };int main() {struct S s = { 0 };FILE* pfread = fopen("test.txt", "r");if (pfread == NULL) {printf("%s\n", strerror(errno));return 0;}fscanf(pfread, "%d%f%s", &(s.n), &(s.score), &(s.arr));printf("%d-%f-%s", s.n, s.score, s.arr);return 0; }4:二進(jìn)制輸入
int main() {struct S s = { 0 };FILE* pfread = fopen("test.txt", "rb");//二進(jìn)制if (pfread == NULL) {printf("%s\n", strerror(errno));return 0;}fread(&s, sizeof(struct S), 1, pfread);printf("%d-%f-%s", s.n, s.score, s.arr);return 0; }五:文件的隨機(jī)讀取
(1)fseek
文件指針開始會(huì)指向文件內(nèi)容的開頭,順序讀取時(shí)想要讀取某個(gè)特定字符時(shí),必須先讀其前面的字符,而使用隨機(jī)讀取,可以直接偏移文件指針,直接讀取
需要注意,在讀取完成后文件指針會(huì)自動(dòng)向后偏移
- SEEL_CUR:以文件指針的當(dāng)前位置偏移
- SEEK_END:以文件的末尾位置偏移
- SEEK_SET:以文件的起始位置開始
(2)ftell
返回當(dāng)前文件指針相對于起始位置的偏移量
int main() {FILE* pfread = fopen("test.txt", "r");if (pfread == NULL) {printf("%s\n", strerror(errno));return 0;}fgetc(pfread);//讀取一個(gè)跳過一個(gè)int pos = ftell(pfread);printf("%d\n", pos);fclose(fread);return 0; }(3)rewind
讓文件指針回到起始位置
int main() {FILE* pfread = fopen("test.txt", "r");if (pfread == NULL) {printf("%s\n", strerror(errno));return 0;}fgetc(pfread);//讀取一個(gè)跳過一個(gè)int pos1 = ftell(pfread);rewind(pfread);//回到其實(shí)位置int pos2 = ftell(pfread);printf("%d\n", pos2);//結(jié)果仍然是0fclose(fread);return 0; }六:文件結(jié)束條件判定
對于fgetc,如果其返回值為EOF;對于fgets,如果其返回值為NULL,就代表文件讀到末尾
需要特別注意的一點(diǎn)是千萬不要用feof判斷文件結(jié)束
下面是讀到文件末尾的標(biāo)準(zhǔn)寫法
while ((c = fgetc(fp)) != EOF) {//操作 }七:其它注意點(diǎn)
1:flcose函數(shù)在文件成功關(guān)閉時(shí)返回0,關(guān)閉失敗時(shí)返回EOF
2:當(dāng)文件到達(dá)末尾時(shí),feof返回的是非0,沒有到達(dá)則返回0
3:使用getchar()輸入字符時(shí),是先將所有字符送入緩沖區(qū),直到鍵入回車換行符才從緩沖區(qū)逐個(gè)讀出并賦值給變量
4:fgets從fp所指的文件中讀取字符串并在字符串末尾添加’\0’,然后存入s,最多讀n-1個(gè)字符
5:fgets在出錯(cuò)和到達(dá)文件末尾返回都是NULL,所以應(yīng)該用ferror來確定它返NULL的原因是什么
- 函數(shù)ferror用來檢測是否出現(xiàn)文件錯(cuò)誤,如果出現(xiàn),函數(shù)返回非0值,沒有錯(cuò)誤,返回0值
6:fputs出現(xiàn)寫入錯(cuò)誤,返回EOF,成功返回一個(gè)非負(fù)數(shù)
7:與gets()不同的是,fgets()從指定的流讀字符串,讀到換行符時(shí)將換行符也作為字符串的一部分讀到字符串。同理,與puts()不同的是,fputs()不會(huì)在寫入文件的字符串末尾自動(dòng)加上換行符
8:函數(shù)fseek調(diào)用成功,返回0,否則返回非0
9:fopen發(fā)生錯(cuò)誤時(shí),返回0
總結(jié)
以上是生活随笔為你收集整理的【C语言重点难点精讲】C语言文件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【BZOJ-1458】士兵占领 最
- 下一篇: SCU3033 Destroying a