目录
6.文件的顺序读写
1.几个顺序读写函数
1.fgetc函数
代码示例
代码改进
2.fputc函数
3.fputs函数
如果需要换行,应该写入换行符(\n)
4.fgets函数
1.读取单行字符串
2.读取多行字符串
6.文件的顺序读写
1.几个顺序读写函数
分组:(fgetc,fputc),(fgets,fputs),(fscanf,fprintf),(fread,fwrite)
1.fgetc函数
声明:int fgetc ( FILE * stream );
格式:fgetc(指针);
作用:从流中取得字符
如果读取成功,返回字符(提升为int型,因此建议用int类型的变量来接收返回值),当读到文件末尾时,返回EOF
如果读取失败,返回EOF
代码示例
如果abc.txt内的字符个数充足的话,这是读取abc.txt的前5个字符
#include <stdio.h>
int main()
{
FILE* p = fopen("abc.txt", "r");
if (p == NULL)
{
perror("fopen");
return 1;//错误返回
}
int ch = 0;
ch = fgetc(p);
printf("%c", ch);
ch = fgetc(p);
printf("%c", ch);
ch = fgetc(p);
printf("%c", ch);
ch = fgetc(p);
printf("%c", ch);
fclose(p);
p = NULL;//将野指针置空
return 0;
}
x86+debug环境,用VS调试, 打开内存窗口,输入p
执行完int ch = fgetc(p);后
执行完第一个ch = fgetc(p);后
执行完第二个ch = fgetc(p);后
执行完第三个ch = fgetc(p);后
执行完第四个ch = fgetc(p);后
......
会发现,每执行一次fgetc函数时,0x01458F48处的数据(即指针p的数据)+1,0x1469F50处的数据-1
代码改进
如果想一直读取字符到结尾,可以这样改进
int ch = 0;//ch为返回值接收变量
while ((ch=fgetc(p))!=EOF)
printf("%c", ch);
注意到fgetc函数支持所有的输出流, 因此使用以下代码可以从标准输入流中打印字符至屏幕
while ((ch=fgetc(stdin))!=EOF)
printf("%c", ch);
图中实际上输入了"abcdefg\n"和"csdn\n"
如果不按Ctrl+Z(向显存写入EOF),光标会一直处于等待状态
备注:Windwos下,EOF为<stdio.h>定义的一个常量 #define EOF (-1)
具体细节参见32.【C语言】详解scanf
2.fputc函数
声明:int fputs ( const char * str, FILE * stream );
格式:fputs(' ',指针);
作用:向文件中写入一个字符
#include <stdio.h>
int main()
{
FILE* p = fopen("abc.txt", "w");
if (p == NULL)
{
perror("fopen");
return 1;//错误返回
}
fputc('a', p);
fclose(p);
p = NULL;//将野指针置空
return 0;
}
向abc.txt写入字符a
注意到fputc函数支持所有的输出流,因此使用fputc('a', stdout);可以将字符a显示到屏幕上
3.fputs函数
声明:int fputs ( const char * str, FILE * stream );
格式:fputs("字符串", 指针);
作用:向文件中写入一串字符
#include <stdio.h>
int main()
{
FILE* p = fopen("abc.txt", "w");
if (p == NULL)
{
perror("fopen");
return 1;//错误返回
}
fputs("abcdefgh", p);
fclose(p);
p = NULL;//将野指针置空
return 0;
}
如果再添加一行,再次运行
fputs("Hello World!", p);
并没有放在两行
如果需要换行,应该写入换行符(\n)
fputs("\nHello World!", p);
4.fgets函数
声明:char * fgets ( char * str, int num, FILE * stream );
格式:fgets(接收指针, 读取当前行的字符个数, 文件指针);
作用:读取字符串
细节之"0D 0A"
先向abc.txt写入,再用HxD.exe查看
发现每行字符串间隔了0D 0A,这为fgets打印多行字符串提供了帮助
查ASCII码表可知
CR(0DH)为回车(转义字符\r),LF(0A)为换行(转义字符\n)
具体为什么这样设计的原因有两点
1.早期的打字机在写一行结束的时候,要做两个动作才能从下一行开始打印
回车(打字头归位)-->换行(打字机上卷一行),Windows的记事本保留了这一特点
2.取决于操作系统,可参见此网站Introducing extended line endings support in Notepad
下面是关键信息的截图
在Windows中,采用CR+LF(0D 0A)的形式;在Unix或Linux中,采用LF(0A)的形式;在麦金塔中,采用CR(0D)的形式............(详见下图)
下图为https://www.sttmedia.com/newline提供的更详细的信息
1.读取单行字符串
#include <stdio.h>
int main()
{
FILE* p = fopen("abc.txt", "r");
if (p == NULL)
{
perror("fopen");
return 1;//错误返回
}
char arr[100];//arr用来接收读取到的字符串
fgets(arr, 100, p);//第2个参数写入100,为的是能够最大化读取当前行的字符串
printf("%s", arr);
fclose(p);
p = NULL;//将野指针置空
return 0;
}
2.读取多行字符串
如果要读取多行,可以多次写
fgets(arr, 100, p);
printf("%s", arr);
也可以写循环
while (fgets(arr, 100, p) != NULL)
{
printf("%s", arr);
}
注意:此次调用fgets函数会覆盖掉上一次读取的内容
如将上方部分代码改成
fgets(arr, 100, p);
fgets(arr, 100, p);
fgets(arr, 100, p);
VS调试,打开监视窗口
除此之外,fgets会在读取完当前行后,在arr数组中写入\0以示结束