C||读写文件输入输出

对接之前的文章:英语单词学习软件【动态分配空间】

题引:

输入一些整数,求出它们的最小值、最大值、平均值(保留三位小数)。输入保证这些数都是不超过1000的整数。
样例输入:

2 8 3 5 1 7 3 6

样例输出:

1 8 4.375

题解:

不难发现,要输入的整数个数是不确定的。

法一:

#include
int main()
{
	int x, n = 0, min = 1000, max = 0, s = 0;
	while (scanf("%d", &x) == 1)
	{
		s += x;
		if (x < min)min = x;
		if (x > max)max = x;
		n++;
	}
	printf("%d %d %.3f", min, max, (double)s / n);
	return 0;
}

解析此码:whie循环中“scanf("%d", &x) == 1”是条件,scanf函数有返回值?对,scanf函数返回的是成功输入的变量个数,当输入结束时,scanf函数无法再次读取x,将返回0。
下面进行测试。输入“2 8 3 5 1 7 3 6”,按ENTER,但未显示结果。难道程序速度太慢?其实程序正在等待输入。还记得scanf的输入格式吗?空格、TAB、回车符都是无关紧要的,所以按ENTER并不意味着输入的结束。那该怎么结束输入呢?
答,在Windows下,输入完毕后先按ENTER,再按Ctrl+Z,最后再按ENTER,即可结束输入。在Linux下,输入完毕后按Ctrl+D即可。
值得注意的是,在循环之前,我们需要先对min、max赋值,否则变量在赋值前的值是不确定的

法二:

倘使读者懒一点,那么法一就不是很方便了:每次测试都要手动输入许多数。
一个好的方法是用文件——把输入数据保存在文件中,输出数据保存在文件中。这样,只要事先把输入数据保存在文件中,就不必每次重新输入了。
使用文件最简单的方法是使用输入输出重定向,只需在main函数的入口处加入以下两条语句:

freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);

上述语句将使得scanf从文件input.txt读入,printf写入文件output.txt。

#include
int main()
{
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
	int x, n = 0, min = 1000, max = 0, s = 0;
	while (scanf("%d", &x) == 1)
	{
		s += x;
		if (x < min)min = x;
		if (x > max)max = x;
		n++;
	}
	printf("%d %d %.3f", min, max, (double)s / n);
	return 0;
}

法三:

当然除了重定向的方式,还可以fopen

#include
int main()
{
	FILE *fin, *fout;
	fin = fopen("input.txt", "r");
	fout = fopen("output.txt", "w");
	int x, n = 0, min = 1000, max = 0, s = 0;
	while (fscanf(fin, "%d", &x) == 1)
	{
		s += x;
		if (x < min)min = x;
		if (x > max)max = x;
		n++;
	}
	fprintf(fout, "%d %d %.3f", min, max, (double)s / n);
	fclose(fin);
	fclose(fout);
	return 0;
}

先声明变量fin、fout,把scanf改成fscanf,第一个参数为fin;把printf改成fprintf,第一个参数为fout,最后执行fclose,关闭两个文件。
顺便一提,如果想把fopen版的程序改写成读写标准输入输出,只需赋值“fin=stdin; fout=stdout;”即可。

比较法二法三:

重定向和fopen两种方法各有优劣。重定向的方法写起来简单、自然,但不能同时读写文件和标准输入输出;fopen的写法稍显繁琐,但是灵活性比较大(比如,可以反复打开并读写文件,即我们的实操:英语单词学习软件)。

注释:

“r”:以只读的形式打开文本文件(不存在则出错)
“w”:以只写的形式打开文本文件(若不存在则新建,反之,则从文件起始位置写,覆盖原内容)

“a”:以追加的形式打开文本文件(若不存在,则新建;反之,在原文件后追加)
“r+”:以读写的形式打开文本文件(读时,从头开始;写时,新数据只覆盖所占的空间)
“wb”:以只写的形式打开二进制文件
“rb”:以只读的形式打开二进制文件
“ab”:以追加的形式打开一个二进制文件
“rb+”:以读写的形式打开二进制文件。
“w+”:首先建立一个新文件,进行写操作,然后从头开始读(若文件存在,原内容将全部消失)
“a+”:功能与”a”相同。只是在文件尾部追加数据后,可以从头开始读
“wb+”:功能与”w+”相同。只是在读写时,可以由位置函数设置读和写的起始位置
“ab+”:功能与”a+”相同。只是在文件尾部追加数据之后,可以由位置函数设置开始读的起始位置

题目进阶

输入一些整数,求出它们的最小值、最大值、平均值(保留三位小数)。输入保证这些数都是不超过1000的整数。
输入包含多组数据,每组数据第一行是整数个数n,第二行是n个整数。n=0为输入结束标记,程序应当忽略这组数据。
样例输入:

8
2 8 3 5 1 7 3 6
4
-4 6 10 0
0

样例输出:

Case 1: 1 8 4.375
Case 2: -4 10 3.000

比较常见的方法就不过多解释了。

#include
int main()
{
	int x, n = 0, kase = 0;
	while (scanf("%d", &n) == 1 && n)
	{
		int min = 1000, max = 0, s = 0;
		for (int i = 0; i < n; i++)
		{
			(void)scanf("%d", &x);
			s += x;
			if (x < min)min = x;
			if (x > max)max = x;
		}
		printf("Case %d: %d %d %.3f\n", ++kase, min, max, (double)s / n);
	}
	return 0;
}

值得注意的是min和max要定义在while循环中,此过程为重置min、max,否则将影响下组数据的求解。
当嵌套的两个代码块中有同名变量时,内层的变量会屏蔽外层变量,有时会发起十分隐蔽的错误

你可能感兴趣的:(算法,c语言)