首页 > 代码库 > fprintf与fwrite函数用法与差异
fprintf与fwrite函数用法与差异
在C语言中有两个常见的保存文件的函数:fprintf 与 fwrite。其主要用法与差异归纳如下:
一、fprintf函数。
1.以文本的形式保存文件。函数原型为 int fprintf(FILE* stream,const char* format,[argument]),用法类似于printf函数,返回值是输出的字符数,发生错误时返回一个负值。
2.对应的读取函数为fscanf()。函数原型为int fscanf(FILE* stream,const char* format,[argument...]),用法类似于scanf函数,返回值为成功读入参数的个数,当读到文件末尾EOF时,返回-1。
二、fwrite函数。
1.以二进制形式保存文件。函数原型为size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream),参数依次为数据地址,数据元素大小,数据元素个数,文件指针。返回值为实际写入的数据的项数。
2.对应的读取函数为fread。函数原型为size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ,参数依次为数据地址,数据元素大小,数据元素个数,文件指针。返回值为实际读取的数据项数,当读到文件末尾的EOF时,返回0。
三、疑难点:
1.由于fprintf以文本形式保存文件,所以当保存多组数据的时候,每组数据之间必须有分隔符,可以是空格,换行符或者特殊字符,否则在读取文件的时候会出错。
2.无论哪种读取文件的方式,都可以用while(!feof(fp))来判断文件是否读到末尾,但feof()函数在读到EOF时仍然返回0,到下一个位置时才返回1,这就容易导致最后一组数据容易读取两次,或多读取一组空数据。(经试验fprint函数以空格和换行符作为数据分隔符的时候不会出现此情况)利用两个读取函数的返回值,我们可以避免这种情况。
2.1 fscanf()函数避免多读最后一行:
1 Node* readTxt(){ 2 FILE* fp = NULL; 3 Node* head = NULL; 4 fp = fopen("file.txt","r"); 5 if(fp == NULL){ 6 cout<<"Error(fopen):fp == NULL"<<endl; 7 return NULL; 8 } 9 while (!feof(fp))10 {11 Data data;12 int res = fscanf(fp,"%d %s %lf\n",&data.num,data.str,&data.dou);13 cout<<"res == "<<res<<endl;14 if(res == -1){15 break;16 }17 insert(head,&data);18 }19 fclose(fp);20 return head;21 }
2.2 fread()函数避免多读取最后一行:
1 Node* readBit(){ 2 FILE* fp = NULL; 3 Node* head = NULL; 4 fp = fopen("fileBit.txt","r"); 5 if(fp == NULL){ 6 cout<<"Error(fopen):fp == NULL"<<endl; 7 return NULL; 8 } 9 while (!feof(fp))10 {11 Data data;12 int res = fread(&data,sizeof(Data),1,fp);13 cout<<"res == "<<res<<endl;14 if(res == 0){15 break;16 }17 insert(head,&data);18 }19 fclose(fp);20 return head;21 }
完整测试代码:
1 #include<iostream> 2 #include<stdlib.h> 3 using namespace std; 4 5 typedef struct{ 6 int num; 7 char str[20]; 8 double dou; 9 }Data; 10 11 typedef struct node{ 12 Data data; 13 struct node* next; 14 }Node; 15 16 Data* input(); 17 void insert(Node*& head,Data* data); 18 void enterData(Node*& head); 19 void listData(Node* head,void visit(Data* item)); 20 void visit(Data* item); 21 void saveTxt(Node* head); 22 Node* readTxt(); 23 void saveBit(Node* head); 24 Node* readBit(); 25 26 Data* input(){ 27 Data* data = http://www.mamicode.com/(Data*)calloc(1,sizeof(Data)); 28 cout<<"An Int:"; 29 cin>>data->num; 30 cout<<"a string:"; 31 cin>>data->str; 32 cout<<"a double:"; 33 cin>>data->dou; 34 return data; 35 } 36 37 void insert(Node*& head,Data* data){ 38 if(data =http://www.mamicode.com/= NULL){ 39 cout<<"Error:data =http://www.mamicode.com/= NULL/n"; 40 return; 41 } 42 if(head == NULL){ 43 head = (Node*)calloc(1,sizeof(Node)); 44 head->data = http://www.mamicode.com/*data; 45 head->next = NULL; 46 }else{ 47 Node* node = (Node*)calloc(1,sizeof(Node)); 48 node->data = http://www.mamicode.com/*data; 49 node->next = head->next; 50 head->next = node; 51 } 52 } 53 54 void enterData(Node*& head){ 55 char c; 56 do 57 { 58 Data* p = input(); 59 insert(head,p); 60 cout<<"continue?[y/n]:"; 61 cin>>c; 62 } while (c==‘y‘||c==‘Y‘); 63 } 64 65 void visit(Data* item){ 66 if(item == NULL){ 67 cout<<"Error(visit):item == NULL"<<endl; 68 } 69 cout<<"Int="<<item->num<<" str="<<item->str<<" double="<<item->dou<<endl; 70 } 71 void listData(Node* head,void visit(Data* item)){ 72 if(head == NULL){ 73 cout<<"Error(listData):head == NULL"<<endl; 74 } 75 Node* p = head; 76 while (p!=NULL) 77 { 78 visit(&(p->data)); 79 p = p->next; 80 } 81 } 82 83 void saveTxt(Node* head){ 84 int inres = 0; 85 FILE* fp = NULL; 86 if(head == NULL){ 87 cout<<"Error(saveTxt):head == NULL"<<endl; 88 return; 89 } 90 fp = fopen("file.txt","w"); 91 if(fp == NULL){ 92 cout<<"Error(fopen):fp == NULL"<<endl; 93 return; 94 } 95 Node* p = head; 96 while (p!=NULL) 97 { 98 inres = fprintf(fp,"%d %s %lf\n",p->data.num,p->data.str,p->data.dou); 99 cout<<"inres == "<<inres<<endl;100 p = p->next;101 }102 fclose(fp);103 }104 105 Node* readTxt(){106 FILE* fp = NULL;107 Node* head = NULL;108 fp = fopen("file.txt","r");109 if(fp == NULL){110 cout<<"Error(fopen):fp == NULL"<<endl;111 return NULL;112 }113 while (!feof(fp))114 {115 Data data;116 int res = fscanf(fp,"%d %s %lf\n",&data.num,data.str,&data.dou);117 cout<<"res == "<<res<<endl;118 if(res == -1){119 break;120 }121 insert(head,&data);122 }123 fclose(fp);124 return head;125 }126 127 void saveBit(Node* head){128 FILE* fp = NULL;129 if(head == NULL){130 cout<<"Error(saveBit):head == NULL"<<endl;131 return;132 }133 fp = fopen("fileBit.txt","w");134 if(fp == NULL){135 cout<<"Error(fopen):fp == NULL"<<endl;136 return;137 }138 Node* p = head;139 while (p!=NULL)140 {141 fwrite(&(p->data),sizeof(Data),1,fp);142 p = p->next;143 }144 fclose(fp);145 }146 147 Node* readBit(){148 FILE* fp = NULL;149 Node* head = NULL;150 fp = fopen("fileBit.txt","r");151 if(fp == NULL){152 cout<<"Error(fopen):fp == NULL"<<endl;153 return NULL;154 }155 while (!feof(fp))156 {157 Data data;158 int res = fread(&data,sizeof(Data),1,fp);159 cout<<"res == "<<res<<endl;160 if(res == 0){161 break;162 }163 insert(head,&data);164 }165 fclose(fp);166 return head;167 }168 169 int main(){170 Node* head = NULL,*headBit = NULL;171 cout<<"sizeof(Data)=="<<sizeof(Data)<<endl;172 //enterData(head);173 //saveTxt(head);174 head = readTxt();175 saveBit(head);176 cout<<"bit---------------\n";177 headBit = readBit();178 listData(headBit,visit);179 cout<<"txt---------------\n";180 listData(head,visit);181 saveTxt(head);182 return 0;183 }
fprintf与fwrite函数用法与差异