目录
1、读写文件中的字符:
例题1:从键盘键入一串字符,然后把它们转存到磁盘文件上。
例题2:将0-127之间的ASCII字符写到文件中,然后从文件中读出并显示到屏幕上。
例题3:修改例题2判断读出的字符是否为可打印字符,若是则直接将该字符显示到屏幕上,否则将该字符的十进制ASCII码显示到屏幕上。
2、读写文件中的字符串
例题4:用函数fgets(),从键盘键入一串字符,然后把它们添加到文本文件demo.txt的末尾。假设文本文件demo.txt中已有内容为:I am a student.
ANSI C提供了丰富的文件读写函数。包含按字符读写、按数据块读写、按格式读写等。
1、读写文件中的字符:
函数fgetc()用于从一个以只读或读写方式打开的文件上读字符。其函数原型为:
int fgetc(FILE *fp);
其中,fp是由函数fopen()返回的文件指针,该函数的功能是从fp所指定的文件中读取一个字符,并将位置指针指向下一个字符。若读取成功,则返回该字符,若读到文件末尾,则返回EOF,(EOF是一个字符常量,在stdio.h中定义为-1)。
函数fputc()用于将一个字符写到一个文件上。fputc()的函数原型为:
int fputc(int c,FILE *fp);
其中,fp是由函数fopen()返回的文件指针,c是要输入的字符(尽管c定义为int型,但值写入低字节)。该函数的功能是将字符c写到文件指针fp所指的文件中。若写入错误,则返回EOF,否则返回字符c。
例题1:从键盘键入一串字符,然后把它们转存到磁盘文件上。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
char ch;
if((fp = fopen("demo.txt","w"))==NULL)
{
printf("Filure to open demo.txt!\n");
exit(0);
}
ch = getchar();
while(ch!='\n')
{
fputc(ch,fp);
ch= getchar();
}
fclose(fp);
return 0;
}
他会自动生成一个文件叫做demo.txt并自动输入我在exe中输入的字符串。
例题2:将0-127之间的ASCII字符写到文件中,然后从文件中读出并显示到屏幕上。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
char ch;
int i;
if((fp = fopen("demo.bin","wb"))==NULL)
{
printf("Failure to open demo.bin!\n");
exit(0);
}
for(i=0;i<128;i++)
{
fputc(i,fp);
}
fclose(fp);
if((fp = fopen("demo.bin","rb"))==NULL)
{
printf("Failure to open demo.bin!\n");
exit(0);
}
while((ch=fgetc(fp))!=EOF)
{
putchar(ch);
}
fclose(fp);
return 0;
}
运行该程序显示的结果在不同的机器上可能显示的乱码有所不同,用记事本或写字板打开的文件看到的也是乱码,而且与屏幕显示的结果可能并不完全一致。
这是为什么呢?
这是因为在Windows文本编辑器中打开文件时,显示的那些拐来拐去、方块箭头等符号都是不可打印字符。使用不同的文本编辑软件会有不同的处理,而且还会配合字符集等进行转码,甚至换用不同的字体是会有不同的显示结果。
程序第23~26行通过检查fgetc()的返回值是否为EOF来判断是否读到了文件的末尾,若读到文件末尾,则返回EOF,即-1。除此方法之外,还可以使用函数feof()来判断是否读到文件末尾。
因此程序第23~26行还可用下面的语句替换:
ch = fgetc(fp);
while(!feof(fp))
{
putchar(ch);
ch = fgetc(fp);
}
这里,函数feof()用于检查是否到达文件末尾,当文件位置指针指向文件结束符(End-of-file Indicator)时,返回非0值,否则返回0值。其函数原型为:
int feof(FILE *fp);
例题3:修改例题2判断读出的字符是否为可打印字符,若是则直接将该字符显示到屏幕上,否则将该字符的十进制ASCII码显示到屏幕上。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
FILE *fp;
char ch;
int i;
if((fp = fopen("demo.bin","wb"))==NULL)
{
printf("Failure to open demo.bin!\n");
exit(0);
}
for(i=0;i<128;i++)
{
fputc(i,fp);
}
fclose(fp);
if((fp= fopen("demo.bin","rb"))==NULL)
{
printf("Failure to open demo.bin!\n");
exit(0);
}
while((ch= fgetc(fp))!=EOF) //从文件中读取字符直到文件末尾
{
if(isprint(ch)) //判断字符是否可打印
printf("%c\t",ch); //若是可打印字符,则显示该字符
else
printf("%d\t",ch); //若是非可打印字符,则显示该字符的ASCII码值
}
fclose(fp);
return 0;
}
除本例使用的方法外,还可使用函数feof()来判断是否读到文件末尾,即将原程序第24~30行换成如下语句:
while(!feop(fp))
{
ch = fgetc(fp);
if(isprint(ch))
printf("%c\t",ch);
else
printf("%d\t",ch);
}
此时程序运行显示结果后会显示一个-1,这是因为使用函数feof()时,仅当读到文件结束符时,才能判断出到达文件尾,而文件末尾的文件结束符又是一个值为-1、不可打印的非控制字符,因此按上面程序的流程,就将其十进制ASCII码值(即-1)输出到屏幕上。
如何解决这个问题呢?
其实很简单就是将上面第27行用函数isprint()判断是否时可打印字符的语句修改为用函数iscntrl()判断是否是控制字符即可,即修改为 if(!iscntrl(ch))
若为非控制字符,则直接将其显示到屏幕上,否则将其十进制ASCII码值显示到屏幕上。
修改方法2:将第 26行语句复制到第30行和第31行之间作为while循环的最后一条语句,同时复制到第24行while语句之前,然后删除第26行。之所以这样修改,是因为函数feof()总是在读完文件所有内容后在执行一次读文件操作(将文件结束符读走,但不显示)才能返回真(非0)值。
2、读写文件中的字符串
从文件中读取字符串可使用函数fgets(),其函数原型为:
char * fgets(char * s,int n, FILE *fp);
该函数从fp所指的文件中读取字符串并在字符末尾添加'\0',然后存入s,最多读n-1个字符。当读到回车换行符、到达文件尾或读满n-1个字符时,函数返回该字符串的首地址,即指针s的值;读取失败时返回空指针(NULL)。因出错和到达文件尾时都返回NULL,因此应使用feof()或ferror()确定函数fgets()返回NULL的实际原因是什么。
例题4:用函数fgets(),从键盘键入一串字符,然后把它们添加到文本文件demo.txt的末尾。假设文本文件demo.txt中已有内容为:I am a student.
#include <stdio.h>
#include <stdlib.h>
#define N 80
int main(void)
{
FILE *fp;
char str[N];
if((fp= fopen("demo.txt","a"))==NULL)
{
printf("Failure to open demo.txt!\n");
exit(0);
}
gets(str);
fputs(str,fp);
fclose(fp);
if((fp = fopen("demo.txt","r"))==NULL)
{
printf("Failure to open demo.txt!\n");
exit(0);
}
fgets(str,N,fp);
puts(str);
fclose(fp);
return 0;
}
与gets()不同的是,fgets()从指定的流读字符串,读到换行符时将换行符也作为字符串的一部分读到字符串中来。同理,与puts不同的是,fputs()不会再写入文件的字符串末尾添加换行符。