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()函数避免多读最后一行:
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函数用法与差异的更多相关文章
- php写入文件fwrite() 函数用法
在php中,php fwrite() 函数是用于写入文件(可安全用于二进制文件).说的简单点,就是在一个文件中,添加新的内容,本篇文章收集总结了几篇关于php写入文件fwrite() 函数用法的总结, ...
- C++:fread、fwrite函数用法
主要内容: fread.fwrite函数的用法 1.函数功能 用来读写一个数据块. 2.一般调用形式 fread(buffer,size,count,fp); fwrite(buffer,size,c ...
- fread 和 fwrite 函数用法示例以及注意事项
1.函数功能 用来读写一个数据块. 2.一般调用形式 fread(buffer,size,count,fp); fwrite(buffer,size,count,fp); 3.说明 ( ...
- 【转】fread函数和fwrite函数
1.函数功能 用来读写一个数据块. 2.一般调用形式 fread(buffer,size,count,fp); fwrite(buffer,size,count,fp); 3.说明 ( ...
- select()函数用法二
Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如 connect.accept.recv或recvfrom这样的阻塞程序 ...
- C语言对文件的操作函数用法详解1
在ANSIC中,对文件的操作分为两种方式,即: 流式文件操作 I/O文件操作 一.流式文件操作 这种方式的文件操作有一个重要的结构FILE,FILE在stdio.h中定义如下: typedef str ...
- fread函数和fwrite函数
1.函数功能 用来读写一个数据块. 2.一般调用形式 fread(buffer,size,count,fp); fwrite(buffer,size,count,fp); 3.说明 ( ...
- fopen函数和fread函数、fwrite函数
fopen(打开文件) 相关函数 open,fclose 表头文件 #include<stdio.h> 定义函数 FILE * fopen(const char * path,const ...
- 关于 pgsql 数据库json几个函数用法的效率测试
关于 pgsql 数据库json几个函数用法的效率测试 关于pgsql 几个操作符的效率测试比较1. json::->> 和 ->> 测试方法:单次运行100次,运行10个单次 ...
随机推荐
- AngularJS学习笔记一:简单入门
阿里云网站的前端是AngularJS实现的. 先下载AngularJS的开发工具包,我下载的angular-1.4.0. 在合适位置引入js文件: <script src="angul ...
- 数学 ACdream 1196 KIDx's Triangle
题目传送门 /* 这道题花了好长时间AC,思路有,但是表达式少写了括号一直乱码,囧! 注意:a==0时要特判:) */ #include <cstdio> #include <alg ...
- xml文件读写
创建xml文件,对xml文件进行添加新节点.删除节点.更新节点.创建的如下的xml文件. <?xml version="1.0" encoding="UTF-8&q ...
- BZOJ3577 : 玩手机
很明显网络流. S到每个发射站连边,容量为该站限制 每个接收站到T连边,容量为该站限制 矩阵每个点拆成两个点i和i',i向i'连边,容量为该位置手机数 每个发射站向该正方形内所有点i连边,容量为无穷大 ...
- Java集合的线程安全用法
线程安全的集合包含2个问题 1.多线程并发修改一 个 集合 怎么办? 2.如果迭代的过程中 集合 被修改了怎么办? a.一个线程在迭代,另一个线程在修改 b.在同一个线程内用同一个迭代器对象进行迭代. ...
- TYVJ P1031 热浪 Label:dijkstra 最短路
背景 USACO OCT09 9TH 描述 德克萨斯纯朴的民眾们这个夏天正在遭受巨大的热浪!!!他们的德克萨斯长角牛吃起来不错,可是他们并不是很擅长生產富含奶油的乳製品.Farmer John此时以先 ...
- fireBug使用指南
据说,对于网页开发人员来说,Firebug是Firefox浏览器中最好的插件之一. 我最近就在学习怎么使用Firebug,网上找到一篇针对初学者的教程,感觉比较有用,就翻译了出来. ========= ...
- C#引用Interop.SQLDMO.dll后的注意事项(转)
C#引用sqldmo.dll的方法 找到 sqldmo.dll这个文件C:\Program Files\Microsoft SQL Server\80\Tools\Binn\sqldmo.dll用.N ...
- 用LinqPad查看Nhibernate生成的sql语句
使用Nhibernate开发一般都要对Nhibernate生成的sql语句进行查看及分析,查看Nhibernate生成的sql语句,可以使用NHProfiler和log4net.但NHProfiler ...
- Swift Internal Parameter and External Parameter 外部参数和内部参数
今天跟大神又学习了些关于IOS开发Swift语言的外部参数和内部参数 func doSomething(num1: Int, num2: Int) -> Int { return num1 + ...