在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. 空函数有参函数调用参数的注意事项Swift 1.1语言

    空函数有参函数调用参数的注意事项Swift 1.1语言 7.2.3  空函数 空函数有参函数调用参数的注意事项Swift 1.1语言空函数是函数中最简单的形式.在空函数中,函数只有一个空壳,里面是没有 ...

  2. PDA移动POS开单扫描打票收银系统-带来零售批发 新的技术 新的手段!!

    手持POS终端高清彩屏,清晰.美观.大方,适用于仓库.超市.服装.食品.批发零售.手机电脑等企业管理.可与管理软件灵活对接.1:员工记不住价格,产品名称,只要有PDA扫描,价格,库存,直接开销售单,打 ...

  3. 1143 多少个Fibonacci数

    时间限制:500MS  内存限制:65536K提交次数:270 通过次数:16 题型: 编程题   语言: C++;C Description 给你如下Fibonacci 数的定义: F1 = 1 F ...

  4. 前端JSON使用总结

    JSON: JavaScript Object Notation(JavaScript 对象表示法)的简称. 1. 什么是 JSON ? JSON 指的是 JavaScript 对象表示法(JavaS ...

  5. html表单应用

    <!DOCTYPE html> <html> <head> <meta name="generator" content="HT ...

  6. HDU1796 How many integers can you find(容斥原理)

    题目给一个数字集合,问有多少个小于n的正整数能被集合里至少一个元素整除. 当然是容斥原理来计数了,计算1个元素组合的有几个减去2个元素组合的LCM有几个加上3个元素组合的LCM有几个.注意是LCM. ...

  7. CodeForces Round 199 Div2

    完了,这次做扯了,做的时候有点发烧,居然只做出来一道题,差点被绿. My submissions     # When Who Problem Lang Verdict Time Memory 443 ...

  8. !cocos2d 重复添加action事件

    当点击的时候,如果不是按照开始点击计算的,那么持续点击会导致不会变大. void Piece::setActived(bool active) { _actived = active; CCActio ...

  9. BZOJ3682 : Phorni

    后缀平衡树+线段树. $O(1)$比较大小的标号法真是强大. #include<cstdio> #include<cmath> #define N 300010 #define ...

  10. 【wikioi】1026 逃跑的拉尔夫

    题目链接 算法:BFS 14.01.02 PS: 本人再次脑残,BFS又是写得那么脓肿,突然发现我原来什么搜索都是不会的呀.. //2014-02-05已更新 ******************** ...