? ? ? ? 之前,我講解了文件的基本情況與讀寫模式,看到這篇博客的小伙伴們先參考這篇博客:
?C語言——文件操作詳解(1)_
? ? ? ? 接下來,我會(huì)繼續(xù)講解文件操作的第二大步:文件讀/寫操作。
目錄
????????A.文件的順序讀寫
????????一.字符輸入輸出函數(shù)?
????????1.fputc字符輸出函數(shù)
????????2.代碼實(shí)踐:
?????????3.字符輸入函數(shù) fgetc
????????4.代碼實(shí)踐:
? ? ? ?二.字符串輸入輸出函數(shù)
????????1.文本行輸出函數(shù) fputs—— 將一個(gè)字符串寫入流中
????????2.代碼實(shí)踐:
????????3.文本行輸入函數(shù) fgets——從流中讀取一個(gè)字符串?
????????4.代碼實(shí)踐:?
????????5.文件打開模式:"a"寫文件(追加)
???????三.格式化輸入輸出函數(shù)
????????1.格式化輸出函數(shù) fprintf
?????????2.代碼實(shí)踐:
????????3.格式化輸入函數(shù) fscanf?——從文件中讀取格式化數(shù)據(jù)
????????4.代碼實(shí)踐:
??????四.二進(jìn)制輸入輸出函數(shù)?
?????????1.二進(jìn)制輸出 fwrite——將數(shù)據(jù)塊寫入流中
?????????2.代碼實(shí)踐:
? ? ? ? ?3.二進(jìn)制輸入 fread——從流中讀取數(shù)據(jù)
?????????4.代碼實(shí)踐:
? ??五.sscanf函數(shù)與sprintf函數(shù)
????????sprintf?
????????2.代碼實(shí)踐:
????六.printf與scanf同類型函數(shù)對(duì)比
? ? 七.流?
A.文件的順序讀寫
首先,先來看幾個(gè)常用的讀寫函數(shù):
一.字符輸入輸出函數(shù)?
1.fputc字符輸出函數(shù)
int fputc ( int character, FILE * stream );參數(shù)介紹:
? ? ? ? int character:表示填寫要輸入文件的字符
????????FILE * stream(流):指向標(biāo)識(shí)輸出流的?FILE?對(duì)象的指針。
成功后,將返回寫入的字符,并且文件指針指向下一個(gè)位置等待寫入。
如果發(fā)生寫入錯(cuò)誤,則返回?EOF?并設(shè)置錯(cuò)誤指示器(ferror)。
2.代碼實(shí)踐:
int main() {
FILE* pf = fopen("test.txt", "w");
//判斷文件是否正常打開
if (pf == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
//字符輸入函數(shù)——fputc()
char ch = 0;
fputc('a', pf);
fputc(';', pf);
//關(guān)閉文件
fclose(pf);
pf = NULL;
return 0;
}
? ? ? ? 注:每次使用fputc函數(shù)都只能往文件中輸入一個(gè)字符?。
通過代碼調(diào)試后,打開test.txt文件,里面會(huì)顯示剛才輸入的兩個(gè)字符,如下:
#include><stdio.h>
int main() {
FILE* pf = fopen("test.txt", "w");
if (pf == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
//字符輸入函數(shù)——fputc()——一次寫入一個(gè)字符
char ch = 0;
fputc('a', pf);//往test.txt文件中輸入一個(gè)字符
fputc(';', pf);//往文件中輸入一個(gè);號(hào)字符
for (ch = 'b'; ch <= 'z'; ch++) {
fputc(ch, pf);
}
//關(guān)閉文件
fclose(pf);
pf = NULL;
return 0;
}
? ? ? ? ?代碼講解:因?yàn)閒putc每使用一次才能往文件中輸入一個(gè)字符,使用循環(huán)可以實(shí)現(xiàn)多次輸入,如上代碼,我循環(huán)了25次,輸入了b~z 25個(gè)字符,經(jīng)代碼調(diào)試后,如下:
?3.字符輸入函數(shù) fgetc
?參數(shù)只有一個(gè),就是文件指針,意為從文件中讀取一個(gè)字符內(nèi)容。返回值為整型
4.代碼實(shí)踐:
int main() {
FILE* pf = fopen("test.txt", "r");
if (pf == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
//字符輸出函數(shù)——fgetc(),一次讀取一個(gè)字符
char ch = 0;
ch=fgetc(pf);//往test.txt文件中讀取一個(gè)字符
printf("%c\n", ch);
ch = fgetc(pf);//往文件中讀取第二個(gè)字符
printf("%c\n", ch);
ch = fgetc(pf);//往文件中讀取第三個(gè)字符
printf("%c\n", ch);
ch = fgetc(pf);//往文件中讀取第四個(gè)字符
printf("%c\n", ch);
fclose(pf);
pf = NULL;
return 0;
}
如上圖代碼,fgetc每使用一次,也就能讀取一個(gè)字符。
? ? ? ? 還是使用循環(huán)法可以讀取文件中的所有內(nèi)容!如下:
#include<stdio.h>
//讀文件——"r"
int main() {
FILE* pf = fopen("test.txt", "r");
if (pf == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
//字符輸出函數(shù)——fgetc(),一次讀取一個(gè)字符
char ch = 0;
//使用循環(huán)方式讀取文件字符,一次讀一個(gè)
while ((ch = fgetc(pf)) != EOF) {
printf("%c ", ch);//可以讀取到文件中所有字符
}
fclose(pf);
pf = NULL;
return 0;
}
?二.字符串輸入輸出函數(shù)
1.文本行輸出函數(shù) fputs—— 將一個(gè)字符串寫入流中(寫入后不會(huì)自動(dòng)換行,需要自己加'\n')
????????????????int fputs ( const char * str, FILE * stream );
函數(shù)參數(shù):
str:? ? ? ? ? ? ? ? ? ? ? ? ? 包含要寫入流的內(nèi)容的字符串。stream(流):????????指向標(biāo)識(shí)輸出流的?FILE?對(duì)象的指針。
函數(shù)作用:
將?str?所指向的?C 字符串寫入流。
該函數(shù)開始從指定的地址 (str) 復(fù)制,直到到達(dá)終止空字符 ('\0')。此終止空字符不會(huì)復(fù)制到流中。
?2.代碼實(shí)踐:
//寫一個(gè)字符串到文件中
//使用函數(shù)fputs_一次寫入一個(gè)字符串的數(shù)據(jù)
int main() {
FILE* pf = fopen("test.txt", "w");
if (pf == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
char ch = 0;
fputs("abcd", pf);
fputs("efghi\n", pf);
fputs("jklmn\n", pf);
//關(guān)閉文件
fclose(pf);
pf = NULL;
return 0;
}
? ? ? ? 代碼講解:第一次執(zhí)行的fputs函數(shù),它不會(huì)換行,需要手動(dòng)添加\n標(biāo)志,否則會(huì)一直在第一行進(jìn)行文件的輸入填寫。代碼調(diào)試后結(jié)果如下:
? ? ? ? 注1:第一次使用的fputs函數(shù),字符串"abcd"沒有加'\n',所以在第二次輸入的字符串會(huì)緊挨第一個(gè)字符串的末尾位置。
? ? ? ? 注2:?每次對(duì)test.txt文件進(jìn)行調(diào)試運(yùn)行時(shí),都會(huì)覆蓋掉上一次的數(shù)據(jù)內(nèi)容。
? ? ? ??例:上一次test.txt中保存的數(shù)據(jù)是 a;bcdef~z共27個(gè)字符,現(xiàn)在換成了abcdefghi (換行)?jklmn等內(nèi)容。
3.文本行輸入函數(shù) fgets——從流中讀取一個(gè)字符串?
char * fgets ( char * str, int num, FILE * stream );str:???????????????????指向在其中復(fù)制字符串讀取的?chars 數(shù)組的指針。
num:????????????????要復(fù)制到?str?中的最大字符數(shù)(包括終止空字符)。
stream(流):??????指向標(biāo)識(shí)輸入流的?FILE?對(duì)象的指針。
函數(shù)作用:
從流中讀取字符并將其作為 C 字符串存儲(chǔ)到?str?中,直到讀取 (num-1) 字符或達(dá)到換行符或文件末尾(以先發(fā)生者為準(zhǔn))。
換行符使?fgets?停止讀取,但它被函數(shù)視為有效字符,并包含在復(fù)制到?str?的字符串中。
終止空字符會(huì)自動(dòng)追加到復(fù)制到?str 的字符之后。
4.代碼實(shí)踐:?
#include<stdio.h>
int main() {
FILE* pf = fopen("test.txt", "r");
if (pf == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
char arr[300];
fgets(arr,5,pf);
printf("%s\n", arr);
fgets(arr, 6, pf);
printf("%s\n", arr);
fgets(arr, 6, pf);
printf("%s\n", arr);
//關(guān)閉文件
fclose(pf);
pf = NULL;
return 0;
}
調(diào)試結(jié)果:?
? ? ? ?
代碼講解:
? ? ? ?1. 打開test.txt文件,在第一個(gè)fgets函數(shù)中,表示從文件指針讀取5個(gè)字符到char arr數(shù)組中去。但從結(jié)果上看,只讀取到abcd4個(gè)字符。
? ? ? ? 原因:fgets功能是讀取一個(gè)字符串,函數(shù)在按要求讀取時(shí),最后一個(gè)讀到的字符一定為'\0'結(jié)束字符,所以輸出abcd。如下圖:
2. 當(dāng)?shù)谝粋€(gè)pgets函數(shù)讀取完字符串后,文件指針默認(rèn)跳轉(zhuǎn)到文件的下一個(gè)內(nèi)容中,所以第二個(gè)fgets函數(shù)讀取到的字符串緊隨其后,輸出字符串"efghi"。
3.為什么第三個(gè)fgets函數(shù)什么也沒有輸出?原因:字符串"jklmn"處于第二行,fgets在第二次的使用中遇到'\0',換行符使?fgets?停止讀取,無論在怎么使用fgets函數(shù)也沒法讀到。所以什么也不輸出。
若想讀到第二行,還是利用循環(huán)法讀取文件所有內(nèi)容。
int main() {
FILE* pf = fopen("test.txt", "r");
if (pf == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
//字符輸出函數(shù)——fgets()——一次讀取一行字符
char arr[300];
while (fgets(arr, 300, pf) != NULL) {
printf("%s\n", arr);
}
//關(guān)閉文件
fclose(pf);
pf = NULL;
return 0;
}
此外,再說一說文件打開模式:"a"追加
5.文件打開模式:"a"寫文件(追加)
int main() {
FILE* pf = fopen("test.txt", "a");
if (pf == NULL) {
printf("%s\n", strerror(errno));
return -1;
}
fputs("hello bit!", pf);
//關(guān)閉文件
fclose(pf);
pf = NULL;
return 0;
}
結(jié)果如下:
?三.格式化輸入輸出函數(shù)
1.格式化輸出函數(shù) fprintf
函數(shù)參數(shù):
stream:????????指向標(biāo)識(shí)輸出流的?FILE?對(duì)象的指針
format:? ? ? ? ?各類型的輸出形式,以%開頭的,如%f,%s,%c,%d等
?2.代碼實(shí)踐:
struct S {
char arr[10];
int age;
double score;
};
int main() {
struct S s = { "zhangsan",20,95.56 };
FILE* pf = fopen("test2.txt", "w");
if (pf == NULL) {
printf("%s\n", strerror(errno));
return -1;
}
//printf("%s %d %lf\n", s.arr, s.age, s.score);
fprintf(pf, "%s %d %lf\n", s.arr, s.age, s.score);
//關(guān)閉文件
fclose(pf);
pf = NULL;
return 0;
}
代碼講解:fprintf的作用:把結(jié)構(gòu)體變量s中的信息寫入到文件test2.txt中.
? ? ? ? ? ? ? ? 而printf與fprintf的區(qū)別在于:fprintf比printf只多了一個(gè)參數(shù)——文件指針。
結(jié)果如下:
3.格式化輸入函數(shù) fscanf?——從文件中讀取格式化數(shù)據(jù)
函數(shù)參數(shù)同上;?
4.代碼實(shí)踐:
struct S {
char arr[10];
int age;
double score;
};
int main() {
struct S s;
FILE* pf = fopen("test2.txt", "r");
if (pf == NULL) {
printf("%s\n", strerror(errno));
return -1;
}
//scanf("%s %d %lf", s.arr, &(s.age), &(s.score));
fscanf(pf, "%s %d %lf", s.arr, &(s.age), &(s.score));
printf("%s %d %lf\n", s.arr, s.age, s.score);//將讀取到的顯示出來
//關(guān)閉文件
fclose(pf);
pf = NULL;
return 0;
}
代碼講解:?fscanf(pf, "%s %d %lf", s.arr, &(s.age), &(s.score));//從文件中讀取出結(jié)構(gòu)體數(shù)據(jù)。
? ? ? ? ? ? ? ? ? ?fscanf比scanf也是只多一個(gè)文件指針參數(shù)。
?四.二進(jìn)制輸入輸出函數(shù)?
1.二進(jìn)制輸出 fwrite——將數(shù)據(jù)塊寫入流中
函數(shù)參數(shù):
ptr:? ? ?指向要寫入的元素?cái)?shù)組的指針,轉(zhuǎn)換為?const void*。
size:? ?要寫入的每個(gè)元素的大小(以字節(jié)為單位)。
count:元素?cái)?shù),每個(gè)元素的大小為字節(jié)大小
stream: 指向指定輸出流的?FILE?對(duì)象的指針。
?2.代碼實(shí)踐:
struct S2 {
char arr[20];
int age;
double score;
};
int main() {
struct S2 s = { "張三",25,93.25 };//創(chuàng)建結(jié)構(gòu)體變量信息
FILE* pf = fopen("test2.txt", "wb");
if (pf == NULL) {
printf("%s\n", strerror(errno));
return -1;
}
fwrite(&s, sizeof(struct S2), 1, pf);//將結(jié)構(gòu)體變量中的信息寫入文件中除了張三,
//其他都是亂碼
//張三以文本形式寫進(jìn)去,以二進(jìn)制形式寫出來是
//一樣的
fclose(pf);
pf = NULL;
return 0;
}
?調(diào)試結(jié)果:
? ?注:有亂碼是因?yàn)椋瑪?shù)據(jù)內(nèi)容是以二進(jìn)制形式寫入文件,有的東西文件無法失敗,出現(xiàn)亂碼。?
3.二進(jìn)制輸入 fread——從流中讀取數(shù)據(jù)
?
?4.代碼實(shí)踐:
struct S2 {
char arr[20];
int age;
double score;
};
int main() {
struct S2 s;
FILE* pf = fopen("test2.txt", "rb");
if (pf == NULL) {
printf("%s\n", strerror(errno));
return -1;
}
fread(&s, sizeof(struct S2), 1, pf);//從文件中讀取內(nèi)容
printf("%s %d %lf\n", s.arr, s.age, s.score);
fclose(pf);
pf = NULL;
return 0;
}
五.sscanf函數(shù)與sprintf函數(shù)
sprintf?
2.代碼實(shí)踐:
struct S3 {
char arr[10];
int age;
double score;
};
int main() {
struct S3 s = { "張三",25,56.30 };
char a[100] = { 0 };
sprintf(a, "%s %d %lf\n", s.arr, s.age, s.score);
printf("字符串輸出:%s\n", a);//數(shù)組a中的內(nèi)容:"張三 25 56.300000"(字符串)
struct S3 tmp = { 0 };
sscanf(a, "%s %d %lf", tmp.arr, &(tmp.age), &(tmp.score));
printf("格式化輸出:%s %d %lf\n", tmp.arr, tmp.age, tmp.score);
return 0;
}
代碼講解://sprintf是將格式化數(shù)據(jù)轉(zhuǎn)換成字符串放入數(shù)組a中
????????????????//sscanf是將數(shù)組a中字符串的內(nèi)容取出,放入為格式化數(shù)據(jù)中?
?
六.printf與scanf同類型函數(shù)對(duì)比
任何一個(gè)C程序,只要運(yùn)行起來,會(huì)默認(rèn)打開三個(gè)流:
stdin? ? ? ? ? ? ? 標(biāo)準(zhǔn)輸入流(鍵盤)——scanf
stdout? ? ? ? ? ?標(biāo)準(zhǔn)輸出流(屏幕)——printf
stderror?? ??? ?標(biāo)準(zhǔn)錯(cuò)誤流(屏幕)
?scanf是針對(duì)標(biāo)準(zhǔn)輸入的格式化輸入語句;??????????????prinf是針對(duì)標(biāo)準(zhǔn)輸出的格式化輸出語句
?fscanf是針對(duì)所有輸入流的格式化輸入語句;? ? ? ? ?fprintf 是針對(duì)所有輸出流的格式化輸出語句.
?sscanf從一個(gè)字符串中轉(zhuǎn)化處一個(gè)格式化的數(shù)據(jù);sprintf是把一個(gè)格式化的數(shù)據(jù)轉(zhuǎn)化成字符串
七.流?
1.剛才很多函數(shù)都提到了流這個(gè)詞,流就是文件指針,下圖就是流的作用圖解:
? ? ? ? 2.打開一個(gè)流,將把該流與一個(gè)文件或設(shè)備連接起來,關(guān)閉流將斷開這種連接,打開一個(gè)文件將返回一個(gè)指向FILE結(jié)構(gòu)體類型的指針,該指針記錄了控制該流的所有必要信息。???????
? ? ? ? 3.拿輸入來說,stdin就是默認(rèn)的輸入流,通常就是鍵盤輸入。啥意思?就是沒有特別說明的話,你的程序就是找鍵盤要那個(gè)需要被復(fù)制的文件。stdin就是一個(gè)指向鍵盤這個(gè)輸入設(shè)備的指針。針對(duì)這個(gè)stdin這個(gè)指針,又有對(duì)應(yīng)的函數(shù)來執(zhí)行相印的操作,如果輸入的是字符,就用getchar,若是文本則用gets,scanf,二進(jìn)制數(shù)據(jù)用fread。 理解了這一個(gè)流,其他也是如出一轍。文章來源:http://www.zghlxwxcb.cn/news/detail-486844.html
好了,關(guān)于文件操作的讀寫函數(shù)就介紹到這,大家覺得有用的話點(diǎn)個(gè)一鍵三連吧,下期見!文章來源地址http://www.zghlxwxcb.cn/news/detail-486844.html
到了這里,關(guān)于C語言——文件操作(2)文件的讀寫操作的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!