前言
本文为业余学习《明解C语言入门篇》的记录,包含代码清单和练习题。
开始学习时间:2022年8月21日
+++++++++++++++++++++++++++++++
第1章 初识C语言
第2章 运算和数据类型
第3章 分支结构程序
第4章 程序的循环控制
第5章 数组
第6章 函数
第7章 基本数据类型
第8章 动手编写各种程序吧
第9章 字符串的基本知识
第10章 指针
第11章 字符串和指针
第12章 结构体
第13章 文件处理
+++++++++++++++++++++++++++++++
第13章 文件处理
13-1 文件与流
代码清单 13-1
//打开与关闭文件
#include <stdio.h>
int main()
{
FILE *fp;
fp=fopen("abc","r");
if(fp == NULL)
{
printf("\a无法打开文件\"abc\"。\n");
}
else
{
printf("\a成功打开了文件\"abc\"。\n");
fclose(fp);
}
return 0;
}
练习 13-1
//修改代码清单13-1,自定义打开的文件名
#include <stdio.h>
int main()
{
FILE *fp;
char fn[128];
printf("请输入文件名:");
scanf("%s",fn);
fp=fopen(fn,"r");
if(fp != NULL)
{
printf("该文件存在。\n");
fclose(fp);
}
else
{
printf("该文件不存在。\n");
}
return 0;
}
练习 13-2
//编写程序,从键盘输入文件名,消去文件内容
#include <stdio.h>
int main()
{
FILE *fp;
char fn[128];
printf("请输入文件名:");
scanf("%s",fn);
if(fp=fopen(fn,"r")==NULL)
{
printf("该文件不存在,已创建新文件。\n");
}
else
{
printf("已清空文件内容。\n");
}
fp=fopen(fn,"w");
fclose(fp);
return 0;
}
代码清单 13-2
//读入身高和体重,计算并显示它们的平均值
#include <stdio.h>
int main()
{
FILE *fp;
int ninzu=0;
char name[100];
double height,weight;
double hsum=0.0;
double wsum=0.0;
char fn[128];
printf("请输入文件名:");
scanf("%s",fn);
puts("\n数据如下:");
if((fp=fopen(fn,"r"))==NULL)
{
printf("\a文件打开失败。\n");
}
else
{
while(fscanf(fp,"%s%lf%lf",name,&height,&weight)==3)
{
printf("%-10s %5.1f %5.1f\n",name,height,weight);
ninzu++;
hsum+=height;
wsum+=weight;
}
printf("----------------------\n");
printf("平均 %5.1f %5.1f\n",hsum/ninzu,wsum/ninzu);
fclose(fp);
}
return 0;
}
练习 13-3
//改写代码清单13-2,将从文件读入的个人信息按身高排序后显示
#include <stdio.h>
typedef struct
{
char name[128];
double height;
double weight;
}human;
void swap(human *p1,human *p2);
int main()
{
FILE *fp;
int ninzu=0;
human per[100]={0};
double hsum=0.0;
double wsum=0.0;
char fn[128];
int i,j;
printf("请输入文件名:");
scanf("%s",fn);
puts("\n按身高升序排列后:");
if((fp=fopen(fn,"r"))==NULL)
{
printf("\a文件打开失败。\n");
}
else
{
while(fscanf(fp,"%s%lf%lf",per[ninzu].name,&per[ninzu].height,&per[ninzu].weight)==3)
{
hsum+=per[ninzu].height;
wsum+=per[ninzu].weight;
ninzu++;
}
for(i=0;i<ninzu-1;i++)
{
for(j=ninzu-1;j>i;j--)
{
if(per[j-1].height>per[j].height)
{
swap(&per[j-1],&per[j]);
}
}
}
for(i=0;i<ninzu;i++)
{
printf("%-10s %5.1lf %5.1lf\n",per[i].name,per[i].height,per[i].weight);
}
printf("----------------------\n");
printf("平均 %5.1f %5.1f\n",hsum/ninzu,wsum/ninzu);
fclose(fp);
}
return 0;
}
void swap(human *p1,human *p2)
{
human temp=*p1;
*p1=*p2;
*p2=temp;
}
代码清单 13-3
//向文件写入程序运行时的日期和时间
#include <stdio.h>
#include <time.h>
int main()
{
FILE *fp;
time_t current=time(NULL);
struct tm *timer=localtime(¤t);
if((fp=fopen("dt_dat1.txt","w"))==NULL)
{
printf("\a文件打开失败。\n");
}
else
{
printf("写入当前日期和时间。\n");
fprintf(fp,"%d %d %d %d %d %d\n",
timer->tm_year + 1900,timer->tm_mon + 1,timer->tm_mday,
timer->tm_hour,timer->tm_min,timer->tm_sec);
fclose(fp);
}
return 0;
}
练习 13-4
//采用代码清单13-2的文件写入形式,编写从键盘读取姓名、身高和体重,并写入文件的程序
#include <stdio.h>
int main()
{
FILE *fp;
char name[128];
double height;
double weight;
if((fp=fopen("hw.dat","a"))==NULL)
{
printf("文件打开失败。\n");
}
else
{
printf("请输入姓名:"); scanf("%s",name); fprintf(fp,"%-10s",name);
printf("请输入身高:"); scanf("%lf",&height); fprintf(fp,"%7.1f",height);
printf("请输入体重:"); scanf("%lf",&weight); fprintf(fp,"%7.1f\n",weight);
fclose(fp);
}
return 0;
}
代码清单 13C-1
//显示当前日期和时间
#include <stdio.h>
#include <time.h>
int main()
{
time_t current=time(NULL);
struct tm *timer=localtime(¤t);
char *wday_name[]={"日","一","二","三","四","五","六"};
printf("当前日期和时间为%d年%d月%d日(%s)%d时%d分%d秒。\n",
timer->tm_year+1900,
timer->tm_mon+1,
timer->tm_mday,
wday_name[timer->tm_wday],
timer->tm_hour,
timer->tm_min,
timer->tm_sec
);
return 0;
}
代码清单 13-4
//显示程序上一次运行时的日期和时间
#include <stdio.h>
#include <time.h>
char data_file[]="datetime.dat";
void get_data();
void put_data();
int main()
{
get_data();
put_data();
return 0;
}
void get_data()
{
FILE *fp;
if((fp=fopen(data_file,"r"))==NULL)
{
printf("本程序第一次运行。\n");
}
else
{
int year,month,day,h,m,s;
fscanf(fp,"%d%d%d%d%d%d",&year,&month,&day,&h,&m,&s);
printf("上一次运行是在%d年%d月%d日%d时%d分%d秒。\n",year,month,day,h,m,s);
fclose(fp);
}
}
void put_data()
{
FILE *fp;
time_t current=time(NULL);
struct tm *timer=localtime(¤t);
if((fp = fopen(data_file,"w")) == NULL)
{
printf("文件打开失败。\n");
}
else
{
fprintf(fp,"%d %d %d %d %d %d\n",
timer->tm_year+1900,
timer->tm_mon+1,
timer->tm_mday,
timer->tm_hour,
timer->tm_min,
timer->tm_sec
);
fclose(fp);
}
}
练习 13-5
//显示程序上一次运行的时间和当时的心情
#include <stdio.h>
#include <time.h>
char data_file[]="datetime.dat";
void get_data();
void put_data();
int main()
{
get_data();
put_data();
return 0;
}
void get_data()
{
FILE *fp;
if((fp=fopen(data_file,"r"))==NULL)
{
printf("本程序第一次运行。\n");
}
else
{
int year,month,day,h,m,s;
char mood[160];
fscanf(fp,"%d%d%d%d%d%d%s",&year,&month,&day,&h,&m,&s,&mood);
printf("上一次运行是在%d年%d月%d日%d时%d分%d秒,%s!\n",year,month,day,h,m,s,mood);
fclose(fp);
}
}
void put_data()
{
FILE *fp;
time_t current=time(NULL);
struct tm *timer=localtime(¤t);
char mood[160];
printf("当前的心情:");
scanf("%s",&mood);
if((fp=fopen(data_file,"w"))==NULL)
{
printf("文件打开失败。\n");
}
else
{
fprintf(fp,"%d %d %d %d %d %d\n",
timer->tm_year+1900,
timer->tm_mon+1,
timer->tm_mday,
timer->tm_hour,
timer->tm_min,
timer->tm_sec
);
fprintf(fp,"%s\n",mood);
fclose(fp);
}
}
代码清单 13-5
//将标准输入的数据复制到标准输出
#include <stdio.h>
int main()
{
int ch;
while((ch=getchar()) != EOF)
{
putchar(ch);
}
return 0;
}
代码清单 13-6
//显示文件内容
#include <stdio.h>
int main()
{
int ch;
FILE *fp;
char fn[FILENAME_MAX];
printf("文件名:");
scanf("%s",fn);
if((fp=fopen(fn,"r"))==NULL)
{
printf("文件打开失败。\n");
}
else
{
while((ch=fgetc(fp)) != EOF)
{
putchar(ch);
}
fclose(fp);
}
return 0;
}
练习 13-6
//编写编程实现从键盘计入文件名,计算文件行数并显示
#include <stdio.h>
int main()
{
FILE *fp;
char fn[FILENAME_MAX];
int ch;
printf("文件名:");
scanf("%s",fn);
if((fp=fopen(fn,"r"))==NULL)
{
printf("文件打开失败。\n");
}
else
{
int LineNum=0;
while((ch=fgetc(fp)) != EOF)
{
if(ch=='\n')
{
LineNum++;
}
}
printf("文件总共有%d行。\n",LineNum);
fclose(fp);
}
}
练习 13-7
//编写编程实现从键盘计入文件名,计算文件的字符数并显示
#include <stdio.h>
int main()
{
FILE *fp;
char fn[FILENAME_MAX];
int ch;
printf("文件名:");
scanf("%s",fn);
if((fp=fopen(fn,"r"))==NULL)
{
printf("文件打开失败。\n");
}
else
{
long CS=0;
while((ch=fgetc(fp)) != EOF)
{
CS++;
}
printf("文件总共有%ld个字符。\n",CS);
fclose(fp);
}
}
代码清单 13-7
//复制文件
#include <stdio.h>
int main()
{
FILE *sfp;
FILE *dfp;
char sfn[FILENAME_MAX];
char dfn[FILENAME_MAX];
int ch;
printf("打开原文件:"); scanf("%s",sfn);
printf("打开目标文件:"); scanf("%s",dfn);
if((sfp=fopen(sfn,"r"))==NULL)
{
printf("原文件打开失败。\n");
}
else
{
if((dfp=fopen(dfn,"w"))==NULL)
{
printf("目标文件打开失败。\n");
}
else
{
while((ch=fgetc(sfp)) != EOF)
{
fputc(ch,dfp);
}
printf("文件已复制。\n");
fclose(dfp);
}
fclose(sfp);
}
return 0;
}
练习 13-8
//修改代码清单13-7,复制文件同时在屏幕上显示文件内容
#include <stdio.h>
int main()
{
FILE *sfp;
FILE *dfp;
char sfn[FILENAME_MAX];
char dfn[FILENAME_MAX];
int ch;
printf("打开原文件:"); scanf("%s",sfn);
printf("打开目标文件:"); scanf("%s",dfn);
if((sfp=fopen(sfn,"r"))==NULL)
{
printf("原文件打开失败。\n");
}
else
{
if((dfp=fopen(dfn,"w"))==NULL)
{
printf("目标文件打开失败。\n");
}
else
{
while((ch=fgetc(sfp)) != EOF)
{
putchar(ch);
fputc(ch,dfp);
}
printf("文件已复制。\n");
fclose(dfp);
}
fclose(sfp);
}
return 0;
}
练习 13-9
//修改代码清单13-7,将文件内的小写字母转换成大写字母并复制文件
#include <stdio.h>
#include <ctype.h>
int main()
{
FILE *sfp;
FILE *dfp;
char sfn[FILENAME_MAX];
char dfn[FILENAME_MAX];
int ch;
printf("打开原文件:"); scanf("%s",sfn);
printf("打开目标文件:"); scanf("%s",dfn);
if((sfp=fopen(sfn,"r"))==NULL)
{
printf("原文件打开失败。\n");
}
else
{
if((dfp=fopen(dfn,"w"))==NULL)
{
printf("目标文件打开失败。\n");
}
else
{
while((ch=fgetc(sfp)) != EOF)
{
fputc(toupper(ch),dfp);
}
printf("文件已复制。\n");
fclose(dfp);
}
fclose(sfp);
}
return 0;
}
练习 13-10
//修改代码清单13-7,将文件内的大写字母转换成小写字母并复制文件
#include <stdio.h>
#include <ctype.h>
int main()
{
FILE *sfp;
FILE *dfp;
char sfn[FILENAME_MAX];
char dfn[FILENAME_MAX];
int ch;
printf("打开原文件:"); scanf("%s",sfn);
printf("打开目标文件:"); scanf("%s",dfn);
if((sfp=fopen(sfn,"r"))==NULL)
{
printf("原文件打开失败。\n");
}
else
{
if((dfp=fopen(dfn,"w"))==NULL)
{
printf("目标文件打开失败。\n");
}
else
{
while((ch=fgetc(sfp)) != EOF)
{
fputc(tolower(ch),dfp);
}
printf("文件已复制。\n");
fclose(dfp);
}
fclose(sfp);
}
return 0;
}
13-2 文本和二进制
代码清单 13-8
//将圆周率的值写入文本文件,再进行读取
#include <stdio.h>
int main()
{
FILE *fp;
double pi=3.14159265358979323846;
printf("从变量pi得到的圆周率为%23.21f。\n",pi);
if((fp=fopen("PI.txt","w"))==NULL)
{
printf("文件打开失败。\n");
}
else
{
fprintf(fp,"%f",pi);
fclose(fp);
}
if((fp=fopen("PI.txt","r"))==NULL)
{
printf("文件打开失败。\n");
}
else
{
fscanf(fp,"%lf",&pi);
printf("从文件读取的圆周率为%23.21f。\n",pi);
fclose(fp);
}
return 0;
}
代码清单 13-9
//将圆周率的值写入二进制文件再进行读写
#include <stdio.h>
int main()
{
FILE *fp;
double pi=3.14159265358979323846;
printf("从变量pi得到的圆周率为%23.21f。\n",pi);
if((fp=fopen("PI.bin","wb"))==NULL)
{
printf("打开文件失败。\n");
}
else
{
fwrite(&pi,sizeof(double),1,fp);
fclose(fp);
}
if((fp=fopen("PI.bin","rb"))==NULL)
{
printf("打开文件失败。\n");
}
else
{
fread(&pi,sizeof(double),1,fp);
printf("从文件读取的圆周率为%23.21f。\n",pi);
fclose(fp);
}
return 0;
}
练习 13-11
//编写一个程序,读取含有10个double型元素的数组的所有元素值
#include <stdio.h>
int main()
{
FILE *fp;
double d[10];
int i;
if((fp=fopen("DoubleArray.bin","wb"))==NULL)
{
printf("文件打开失败。\n");
}
else
{
for(i=0;i<10;i++)
{
printf("d[%d]:",i+1);
scanf("%lf",&d[i]);
}
fwrite(d,sizeof(double),10,fp);
fclose(fp);
}
if((fp=fopen("DoubleArray.bin","rb"))==NULL)
{
printf("文件打开失败。\n");
}
else
{
fread(d,sizeof(double),10,fp);
for(i=0;i<10;i++)
{
printf("d[%d]:%23.21f\n",i+1,d[i]);
}
fclose(fp);
}
return 0;
}
练习 13-12
//改写代码清单13-4,将日期和时间作为struct tm型的值直接向二进制文件进行读写操作
#include <stdio.h>
#include <time.h>
char data_file[]="datetime.bin";
void put_data();
void get_data();
int main()
{
get_data();
put_data();
return 0;
}
void get_data()
{
FILE *fp;
struct tm GetTime;
if((fp=fopen(data_file,"rb"))==NULL)
{
printf("本程序第一次运行。\n");
}
else
{
fread(&GetTime,sizeof(struct tm),1,fp);
printf("上一次运行是在%d年%d月%d日%d时%d分%d秒。\n",
GetTime.tm_year+1900,
GetTime.tm_mon+1,
GetTime.tm_mday,
GetTime.tm_hour,
GetTime.tm_min,
GetTime.tm_sec
);
fclose(fp);
}
}
void put_data()
{
FILE *fp;
time_t current=time(NULL);
struct tm *PutTime=localtime(¤t);
if((fp=fopen(data_file,"wb"))==NULL)
{
printf("文件打开失败。\n");
}
else
{
fwrite(PutTime,sizeof(struct tm),1,fp); //因此处PutTime本身为指针变量,所以不用加&
fclose(fp);
}
}
代码清单 13-10
//用字符和字符编码显示文件内容
#include <stdio.h>
#include <ctype.h>
int main()
{
int n;
unsigned long count=0;
unsigned char buf[16];
FILE *fp;
char fn[FILENAME_MAX];
printf("文件名:");
scanf("%s",fn);
if((fp=fopen(fn,"rb"))==NULL)
{
printf("文件打开失败。\n");
}
else
{
while((n=fread(buf,1,16,fp))>0)
{
int i;
printf("%08lX ",count);
for(i=0;i<n;i++)
{
printf("%02X ",(unsigned)buf[i]);
}
if(n<16)
{
for(i=n;i<16;i++)
{
printf(" ");
}
}
for(i=0;i<n;i++)
{
putchar(isprint(buf[i])?buf[i]:'.');
}
putchar('\n');
count+=16;
}
fclose(fp);
}
return 0;
}
练习 13-13
//复制文件(二进制方式)
#include <stdio.h>
int main()
{
FILE *sfp;
FILE *dfp;
char sfn[FILENAME_MAX];
char dfn[FILENAME_MAX];
int ch;
printf("打开原文件:"); scanf("%s",sfn);
printf("打开目标文件:"); scanf("%s",dfn);
if((sfp=fopen(sfn,"rb"))==NULL)
{
printf("原文件打开失败。\n");
}
else
{
if((dfp=fopen(dfn,"wb"))==NULL)
{
printf("目标文件打开失败。\n");
}
else
{
while((fread(&ch,1,1,sfp)) > 0)
{
fwrite(&ch,1,1,dfp);
}
printf("文件已复制。\n");
fclose(dfp);
}
fclose(sfp);
}
return 0;
}
总结
summary
//将标准输入的数据写入文件
#include <stdio.h>\
int main()
{
int ch;
FILE *fp;
char fn[FILENAME_MAX];
printf("文件名:");
scanf("%s",fn);
if((fp=fopen(fn,"w"))==NULL)
{
printf("文件打开失败。\n");
}
else
{
while((ch=fgetc(stdin)) != EOF)
{
fputc(ch,fp);
}
fclose(fp);
}
return 0;
}