在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. BZOJ1099 : [POI2007]树Drz

    首先1与i交换,n与i交换,i与i+1交换的可以$O(n)$算出. 然后只需要考虑i与x交换(1<i,x<n且|i-x|>1). 设 a[i]=h[i-1] b[i]=h[i+1] ...

  2. linux eclipse cdt make error 127

    不知道为啥,copy原来的eclipse环境到新的地方后,编译总是出错: make:*** error 127 解决方案是:属性Properties---C++编译 c++build---build ...

  3. objective-c "performSelector may cause a leak because its selector is unknown".

    #define SuppressPerformSelectorLeakWarning(Stuff) \ do { \ _Pragma("clang diagnostic push" ...

  4. 【BZOJ】3196: Tyvj 1730 二逼平衡树(区间第k小+树套树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3196 Treap+树状数组 1WA1A,好伤心,本来是可以直接1A的,这次开始我并没有看题解,就写出 ...

  5. mysql中INSTR函数的用法

    mysql中INSTR函数的用法 INSTR(字段名, 字符串) 这个函数返回字符串在某一个字段的内容中的位置, 没有找到字符串返回0,否则返回位置(从1开始) SELECT * FROM tblTo ...

  6. C#获取机器码(转)

    /// <summary>    /// 机器码    /// </summary>   public class MachineCode    {        ///   ...

  7. oracle函数listagg的使用说明(分组后连接字段)

    关于oracle函数listagg的使用说明 工作中经常遇到客户提出这样的需求,希望在汇总合并中,能够把日期逐个枚举出来. 如图,原始数据是这样的: 客户希望能够实现这样的汇总合并: 那么通常我会使用 ...

  8. PHP5 session 详解【经典】 -- 转帖

    PHP5 session 详解[经典] http协议是WEB服务器与客户端(浏览器)相互通信的协议,它是一种无状态协议.所谓无状态,指的是不会维护http请求数据,http请求是独立的,非持久的.而越 ...

  9. PHP文件漏桐可以通过对服务器进行设置和配置来达到防范目的

    对脚本执行漏洞的防范 黑客利用脚本执行漏洞进行攻击的手段是多种多样的,而且是灵活多变的,对此,必须要采用多种防范方法综合的手段,才能有效防止黑客对脚本执行漏洞进行攻击.这里常用的方法方法有以下四种.一 ...

  10. Lucene搜索方法总结

    转自:summerbell http://www.iteye.com/topic/569358 1.多字段搜索 使用 multifieldqueryparser 可以指定多个搜索字段. query q ...