fputs函数,fgets函数,典型问题分析(一次读写一行字符-----文本操作)【文件】(46)

C_old 专栏收录该内容
51 篇文章 0 订阅

这里给出很多例子,读者自行写代码验证印象会更加深刻

fputs函数

fputs函数说明

我们给出使用的测试代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

#define F_PRINTF_ERR(e)\
do\
{\
	if (e == NULL)\
	{\
		printf("open error\n");\
		exit(0);\
	}\
} while (0)\

int main()
{
	FILE* pf = fopen("lines.txt","w");
	F_PRINTF_ERR(pf);
	fputs("aaaaaaaaaaaaaaa\n", pf);
	fputs("bbbbbbbbbbbbbbb\n", pf);
	fputs("ccccccccccccccc\n", pf);
	fclose(pf);
	return 0;
}

执行结果为:
fputs函数执行结果

我们可以看到三行数据已经写入。
当然我们也可以给字符串中加入控制字符:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define F_PRINTF_ERR(e)\
do\
{\
	if (e == NULL)\
	{\
		printf("open error\n");\
		exit(0);\
	}\
} while (0)\

int main()
{
	FILE* pf = fopen("lines.txt","w");
	F_PRINTF_ERR(pf);
	fputs("aaa\naaaaaaaaaaaa\n", pf);
	fputs("bbbbbbbbbbbbbbb\n", pf);
	fputs("ccccc\0cccccccccc\n", pf);
	fclose(pf);
	return 0;
}

执行结果如下:
执行结果

\n表示换行,\0代表字符串结束,所以控制字符在代码中也得以体现。

fgets函数

fgets函数说明

我们通过代码进行测试:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define F_PRINTF_ERR(e)\
do\
{\
	if (e == NULL)\
	{\
		printf("open error\n");\
		exit(0);\
	}\
} while (0)\

int main()
{
	FILE* pf = fopen("lines.txt", "r+");
	F_PRINTF_ERR(pf);
	char buf[1024];
	fgets(buf,1024,pf);
	printf("buf = %s",buf);
	fclose(pf);
	return 0;
}

执行结果为:

写入文本文件

这里只读取到了 aaa\n
这里就是我们要说明的第一种情况:
fgets函数 读取 n-1 个字符前遇到\n,正常读取 \n 然后在读取数据的后面加上 \0 结束。

接下来我们修改代码,这次我们就值读取2个字节:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define F_PRINTF_ERR(e)\
do\
{\
	if (e == NULL)\
	{\
		printf("open error\n");\
		exit(0);\
	}\
} while (0)\

int main()
{
	FILE* pf = fopen("lines.txt", "r+");
	F_PRINTF_ERR(pf);
	char buf[1024];
	fgets(buf,2,pf);
	printf("buf = %s",buf);
	fclose(pf);
	return 0;
}

执行结果为:
执行结果

只读取到了一个字符,这里我们说明第二种情况:
读取 n-1 个字符前没有遇到\n,读取 n-1 个字符前也没有遇到 EOF,读到 n-1 个字符然后后面加上 \0 ,读取结束。

所以上面代码读取两个的时候只读取到1个,因为最后一个字符用与添加\0表示字符串结束。

那么这一次我们把所有的\n都去掉:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define F_PRINTF_ERR(e)\
do\
{\
	if (e == NULL)\
	{\
		printf("open error\n");\
		exit(0);\
	}\
} while (0)\

int main()
{
	FILE* pf = fopen("lines.txt", "r+");
	F_PRINTF_ERR(pf);
	fputs("aaaaaaaaaaaaaaa", pf);
	fputs("bbbbbbbbbbbbbbb", pf);
	fputs("ccccccccccccccc", pf);
	return 0;
}

执行结果为:
写入文本操作

接下来我们进行读取:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define F_PRINTF_ERR(e)\
do\
{\
	if (e == NULL)\
	{\
		printf("open error\n");\
		exit(0);\
	}\
} while (0)\

int main()
{
	FILE* pf = fopen("lines.txt", "r+");
	F_PRINTF_ERR(pf);


	char buf[1024];
	fgets(buf,1024,pf);
	printf("buf = %s",buf);
	fclose(pf);
	return 0;
}

执行结果为:
执行结果

这是我们的第三种情况:
这次读取没有遇到\n,需要读取数据的大小小于开辟出来存放读取到数据的大小,如果遇到EOF那么此时读取到的就是 EOF + \0 结束。

这里在读取所有字母之后遇到了EOF,所以只读取了30个字符并且在后面添加了\0。

典型问题分析

如果读取以下文件:
1234567890abcdefg
1234567890
abcdefg\n

使用

fgets(buf,10,fp);

读取数据需要读取多少次?
我们在这里直接进行说明,然后通过编译器验证:

①123456789 \0
②0abcdefg \n\0
③123456789 \0
④0 \n\0
⑤abcdefg \n\0
⑥需要再进行一次来判断是文件结束EOF

总共需要6次
我们通过代码来验证:
首先我们先把数据写入文件:
文本文件内容

接下来我们进行验证:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define F_PRINTF_ERR(e)\
do\
{\
	if (e == NULL)\
	{\
		printf("open error\n");\
		exit(0);\
	}\
} while (0)\

int main()
{
	FILE* pf = fopen("lines.txt", "r+");
	F_PRINTF_ERR(pf);
	char buf[1024];
	int count = 0;
	while (fgets(buf, 10, pf))
	{
		count++;
		printf("第%d次读取%s\n",count,buf);
	}
	return 0;
}

执行结果为:

执行结果

如果我们把最后的一行的回车去掉(只留下多一个空行):
文本文件

执行结果为:
执行结果

如果我们不要所有的空行:
文本文件

执行结果为:
执行结果

结果也是只需要读取5次,读者可以根据前面的行规则细细体会其中的不同。

小结

#include <stdio.h>
#include <stdlib.h>
#define N 1024
int main()
{
    FILE* pf = fopen("xx.txt", "w+");
    if (pf == NULL)
        exit(-1);
    fputs("abcd\n1234567", pf);
    // fputs("abcd1234567",pf);
    rewind(pf);
    char buf[N];
    //遇到\n EOF 的时候返回非空,在 EOF 以后,再去读,返回为NULL
    printf("%p\n", fgets(buf, N - 1, pf));
    printf("%p\n", fgets(buf, N - 1, pf));
    printf("%p\n", fgets(buf, N - 1, pf));
    puts(buf);
    fclose(pf);
    return 0;
}

执行结果为:
执行结果

分析说明

遇到\n 或者EOF 的时候返回非空,在 EOF 以后,再去读取,返回为NULL。

  • 0
    点赞
  • 0
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值