在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()函数避免多读最后一行:

 Node* readTxt(){
FILE* fp = NULL;
Node* head = NULL;
fp = fopen("file.txt","r");
if(fp == NULL){
cout<<"Error(fopen):fp == NULL"<<endl;
return NULL;
}
while (!feof(fp))
{
Data data;
int res = fscanf(fp,"%d %s %lf\n",&data.num,data.str,&data.dou);
cout<<"res == "<<res<<endl;
14 if(res == -1){
15 break;
16 }
insert(head,&data);
}
fclose(fp);
return head;
}

  2.2 fread()函数避免多读取最后一行:

 Node* readBit(){
FILE* fp = NULL;
Node* head = NULL;
fp = fopen("fileBit.txt","r");
if(fp == NULL){
cout<<"Error(fopen):fp == NULL"<<endl;
return NULL;
}
while (!feof(fp))
{
Data data;
int res = fread(&data,sizeof(Data),,fp);
cout<<"res == "<<res<<endl;
14 if(res == 0){
15 break;
16 }
insert(head,&data);
}
fclose(fp);
return head;
}

完整测试代码:

 #include<iostream>
#include<stdlib.h>
using namespace std; typedef struct{
int num;
char str[];
double dou;
}Data; typedef struct node{
Data data;
struct node* next;
}Node; Data* input();
void insert(Node*& head,Data* data);
void enterData(Node*& head);
void listData(Node* head,void visit(Data* item));
void visit(Data* item);
void saveTxt(Node* head);
Node* readTxt();
void saveBit(Node* head);
Node* readBit(); Data* input(){
Data* data = (Data*)calloc(,sizeof(Data));
cout<<"An Int:";
cin>>data->num;
cout<<"a string:";
cin>>data->str;
cout<<"a double:";
cin>>data->dou;
return data;
} void insert(Node*& head,Data* data){
if(data == NULL){
cout<<"Error:data == NULL\n";
return;
}
if(head == NULL){
head = (Node*)calloc(,sizeof(Node));
head->data = *data;
head->next = NULL;
}else{
Node* node = (Node*)calloc(,sizeof(Node));
node->data = *data;
node->next = head->next;
head->next = node;
}
} void enterData(Node*& head){
char c;
do
{
Data* p = input();
insert(head,p);
cout<<"continue?[y/n]:";
cin>>c;
} while (c=='y'||c=='Y');
} void visit(Data* item){
if(item == NULL){
cout<<"Error(visit):item == NULL"<<endl;
}
cout<<"Int="<<item->num<<" str="<<item->str<<" double="<<item->dou<<endl;
}
void listData(Node* head,void visit(Data* item)){
if(head == NULL){
cout<<"Error(listData):head == NULL"<<endl;
}
Node* p = head;
while (p!=NULL)
{
visit(&(p->data));
p = p->next;
}
} void saveTxt(Node* head){
int inres = ;
FILE* fp = NULL;
if(head == NULL){
cout<<"Error(saveTxt):head == NULL"<<endl;
return;
}
fp = fopen("file.txt","w");
if(fp == NULL){
cout<<"Error(fopen):fp == NULL"<<endl;
return;
}
Node* p = head;
while (p!=NULL)
{
inres = fprintf(fp,"%d %s %lf\n",p->data.num,p->data.str,p->data.dou);
cout<<"inres == "<<inres<<endl;
p = p->next;
}
fclose(fp);
} Node* readTxt(){
FILE* fp = NULL;
Node* head = NULL;
fp = fopen("file.txt","r");
if(fp == NULL){
cout<<"Error(fopen):fp == NULL"<<endl;
return NULL;
}
while (!feof(fp))
{
Data data;
int res = fscanf(fp,"%d %s %lf\n",&data.num,data.str,&data.dou);
cout<<"res == "<<res<<endl;
if(res == -){
break;
}
insert(head,&data);
}
fclose(fp);
return head;
} void saveBit(Node* head){
FILE* fp = NULL;
if(head == NULL){
cout<<"Error(saveBit):head == NULL"<<endl;
return;
}
fp = fopen("fileBit.txt","w");
if(fp == NULL){
cout<<"Error(fopen):fp == NULL"<<endl;
return;
}
Node* p = head;
while (p!=NULL)
{
fwrite(&(p->data),sizeof(Data),,fp);
p = p->next;
}
fclose(fp);
} Node* readBit(){
FILE* fp = NULL;
Node* head = NULL;
fp = fopen("fileBit.txt","r");
if(fp == NULL){
cout<<"Error(fopen):fp == NULL"<<endl;
return NULL;
}
while (!feof(fp))
{
Data data;
int res = fread(&data,sizeof(Data),,fp);
cout<<"res == "<<res<<endl;
if(res == ){
break;
}
insert(head,&data);
}
fclose(fp);
return head;
} int main(){
Node* head = NULL,*headBit = NULL;
cout<<"sizeof(Data)=="<<sizeof(Data)<<endl;
//enterData(head);
//saveTxt(head);
head = readTxt();
saveBit(head);
cout<<"bit---------------\n";
headBit = readBit();
listData(headBit,visit);
cout<<"txt---------------\n";
listData(head,visit);
saveTxt(head);
return ;
}

fprintf与fwrite函数用法与差异的更多相关文章

  1. php写入文件fwrite() 函数用法

    在php中,php fwrite() 函数是用于写入文件(可安全用于二进制文件).说的简单点,就是在一个文件中,添加新的内容,本篇文章收集总结了几篇关于php写入文件fwrite() 函数用法的总结, ...

  2. C++:fread、fwrite函数用法

    主要内容: fread.fwrite函数的用法 1.函数功能 用来读写一个数据块. 2.一般调用形式 fread(buffer,size,count,fp); fwrite(buffer,size,c ...

  3. fread 和 fwrite 函数用法示例以及注意事项

    1.函数功能   用来读写一个数据块. 2.一般调用形式   fread(buffer,size,count,fp);   fwrite(buffer,size,count,fp); 3.说明   ( ...

  4. 【转】fread函数和fwrite函数

    1.函数功能   用来读写一个数据块. 2.一般调用形式   fread(buffer,size,count,fp);   fwrite(buffer,size,count,fp); 3.说明   ( ...

  5. select()函数用法二

    Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如 connect.accept.recv或recvfrom这样的阻塞程序 ...

  6. C语言对文件的操作函数用法详解1

    在ANSIC中,对文件的操作分为两种方式,即: 流式文件操作 I/O文件操作 一.流式文件操作 这种方式的文件操作有一个重要的结构FILE,FILE在stdio.h中定义如下: typedef str ...

  7. fread函数和fwrite函数

    1.函数功能   用来读写一个数据块. 2.一般调用形式   fread(buffer,size,count,fp);   fwrite(buffer,size,count,fp); 3.说明   ( ...

  8. fopen函数和fread函数、fwrite函数

    fopen(打开文件) 相关函数 open,fclose 表头文件 #include<stdio.h> 定义函数 FILE * fopen(const char * path,const ...

  9. 关于 pgsql 数据库json几个函数用法的效率测试

    关于 pgsql 数据库json几个函数用法的效率测试 关于pgsql 几个操作符的效率测试比较1. json::->> 和 ->> 测试方法:单次运行100次,运行10个单次 ...

随机推荐

  1. Xamarin Android提示找不到资源属性定义

    Xamarin Android提示找不到资源属性定义 错误信息:”Resource.Attribute”未包含”actonBarSize”的定义Xamarin Android经常会出现找不到资源属性的 ...

  2. Win7系统删除微软拼音

    微软拼音会在使用Office时偷偷的安装,都找不到删除的地方.在网上找了很多方法都不灵光,最后用下面的方法成功删除.   在语言设置窗口里,重新添加一次这个输入法,确定保存,然后再删除,就行了. 这个 ...

  3. BZOJ2725 : [Violet 6]故乡的梦

    如果S==T,那么答案为0. 如果S与T不连通,那么答案为inf. 否则,S到T的最短路径上至少有一条边. 求出以S为源点的最短路图,是个DAG,随便抓一条S到T的最短路,记为P. 设dpS[x]表示 ...

  4. BZOJ3024 : [Balkan2012]balls

    问题1: ans=max(sum[n]-(sum[i]-sum[j-1])+a[i]*(i-j+1)) =max(sum[n]-sum[i]+sum[j-1]+a[i]*(i+1)-a[i]*j) = ...

  5. HDU 2255 & KM模板

    题意: 一张完备二分图求最优完备匹配. SOL: 这题就不讲什么sol了...毕竟是裸的KM,不会的话可以看老人家的大白鼠,一些问题看代码注释.讲讲经历(悲惨的经历) 刚打完,自信地交上去发现MLE. ...

  6. python zip enumerate函数

    zip是一个内置函数, 接受两个或多个序列,并将他们拉到一起,成为一个元组列表.每个元组包含各个序列中的一个元素. s = 'abc' t = [0,1,2] zip(s,t) >>> ...

  7. 使用jQuery操作Cookies的实现代码

    Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是 ...

  8. 【BZOJ】1191: [HNOI2006]超级英雄Hero(二分图匹配)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1191 一眼题,笑嘻嘻地写了匈牙利,提交..WA了?不科学!!!!!数组小了??不思考了,改大提交,. ...

  9. CMYK印刷色

    一,介绍 CMYK也称作印刷色彩模式,顾名思义就是用来印刷的. 它和RGB相比有一个很大的不同:RGB模式是一种发光的色彩模式,CMYK是一种依靠反光的色彩模式. CMYK——即青.洋红(品红).黄. ...

  10. asp.net 微信企业号办公系统-流程设计--保存与发布

    如果流程未设计完时可以先保存,以后再打开接着设计.点击工具栏上的保存按钮即可保存当前流程设计: 如果下次要接着设计,则可以打开该流程继续设计: 如果流程设计完成,可以点击安装按钮来发布流程,流程安装成 ...