当前位置: 首页 > article >正文

75.【C语言】文件操作(3)

目录

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以示结束


http://www.kler.cn/news/342984.html

相关文章:

  • 第 3 章:使用 Vue 脚手架
  • 【JVM】实战篇
  • 【寻找one piece的算法之路】滑动窗口
  • 【代码笔记】
  • SpringBoot3.3 优雅启停定时任务
  • Java对请求参数进行校验
  • 用Python编写一个Web爬虫:自动获取感兴趣的新闻
  • JavaWeb——Vue组件库Element(5/6):案例:组件实现(概述、Form表单、Table表格、Pagination 分页、效果展示、完整代码)
  • uni-app如何搭建项目(一步一步教程)
  • 云渲染农场可以用哪些CG软件!
  • 【安卓逆向之内存读写
  • C++ 基于SDL库的 Visual Studio 2022 环境配置
  • 在培训考试小程序页面弹出半屏的弹窗交互实践
  • 使用Spring Security+jwt+redis实现登录注册逻辑
  • 请解释一下数据库的分区和分片?请解释一下数据库的日志和日志的重要性?
  • 【Python】使用优先级队列管理任务顺序
  • 设置 Notepad++ 制表符(Tab 缩进)宽度为2个空格大小
  • Bit-map按位存储--轻松应对面试被问到从10亿个数字中查找指定数是否存在
  • Oracle 12201非PDBS模式单机部署(静默安装)
  • 洗衣店订单管理:Spring Boot技术突破