上一次课中,我们谈到了计算机中的文件,讲了文件的含义,作用和分类。
最后我们了解了文件的操作,再来看一下文件常用的操作过程:
以上这些处理文件的过程,在计算机语言中,统称为文件操作。
而对于我们关注的信息学竞赛而言,文件操作也是一个必须要学会的内容,为什么这么说?
现在,我们来看一道信息学竞赛的真题。
为什么文件操作很重要?
我们来看一份 2019 年信息学竞赛的试题:
数字游戏 — 2019 CCF CSP-J2 第一题
问题描述小 K 同学向小 P 同学发送了一个长度为 8 的 01 字符串来玩数字游戏,小 P 同学想要知道字符串中究竟有多少个 1。
注意:01 字符串为每一个字符是 0 或者 1 的字符串,如 “101”(不含双引号)为一个长度为 3 的 01 字符串。
输入格式输入文件名为 number.in。输入文件只有一行,一个长度为 8 的 01 字符串 s。
输出格式输出文件名为 number.out输出文件只有一行,包含一个整数,即 01 字符串中字符 1 的个数。
输入输出样例 1number.in | number.out |
---|---|
00010100 | 2 |
见选手目录下的 number/number1.in 和 number/number1.ans
输入输出样例 1 说明该 01 字符串中有 2 个字符 1
输入输出样例 2number.in | number.out |
---|---|
11111111 | 8 |
见选手目录下的 number/number2.in 和 number/number2.ans
输入输出样例 2 说明该 01 字符串中有 8 个字符 1
输入输出样例 3见选手目录下的 number/number3.in 和 number/number3.ans
数据规模与约定对于 20% 的数据,保证输入的字符全部为 0。对于 100% 的数据,输入只可能包含字符 0 和字符 1,字符串长度固定为 8。
这是这场考试中最简单的一道题,就是所谓的送分题。
不难发现,这道题中含有很多的文件操作,所以,对于参加竞赛的同学们,一定要熟练掌握常用的文件操作。
那么,在 C 语言中,怎样对文件进行操作呢?
以下我们逐一介绍 C 语言操作文件的方法,并以最简的代码做示例。
首先,我们在开始进行文件操作时,需要定义一个文件类型的指针。
FILE *fp;
指针,是一个 C 语言的一个进阶话题,大家目前只需要记住这个形式就可以,现在不必深究。
有了这个文件指针的定义,我们就可以开始进行各种文件操作了。
我们按照以下顺序,举例说明 C 语言文件操作的基本方法。
1. 打开文件#include <stdio.h>
int main() {
// 打开文件 number.in,以读取的方式打开
FILE *fp = fopen("../number/number.in", "r");
}
其中,第一个参数是文件名字符串,而第二个参数则是访问文件的模式。
各种模式的含义如下表:
模式 | 描述 |
---|---|
r | 打开一个文本文件,允许读取文件。 |
w | |
a |
打开一个文本文件,允许写入文件。 不存在,则会创建一个新文件。 程序会从文件的开头写入内容。 文件存在,则会重新写入。 |
r+ | 打开一个文本文件,允许读写文件。 |
w+ |
打开一个文本文件,允许读写文件。 已存在,则文件会被截断为零长度。 文件不存在,则会创建一个新文件。 |
a+ |
打开一个文本文件,允许读写文件。 如果文件不存在,则创建一个新文件。 读取从头开始,写入是追加模式。 |
虽然看起来很复杂,其实仔细分析不难发现,最基本的模式只有 r / w / a 三种,它们的含义分别是 read / write / append,就是 读 / 写 / 追加
2. 关闭文件#include <stdio.h>
int main() {
FILE *fp = fopen("../number/number1.in", "r");
// 关闭打开的文件
fclose(fp);
}
3. 写入文件
#include <stdio.h>
int main() {
// 创建文件 number.out,准备写文件
FILE *fp = fopen("../number/number.out", "w");
// 向文件中写入字符 8
fputc('8', fp);
fclose(fp);
}
4. 读取文件
#include <stdio.h>
int main() {
// 打开文件 number.in,准备读文件
// 文件内容:00010100
FILE *fp = fopen("../number/number.in", "r");
// 读取文件的第一个字符
char c = fgetc(fp);
// 输出读取的字符 c
printf("%c", c); // 输出结果:8
fclose(fp);
}
至此,我们就了解了 C 语言关于文件操作最常用的方法。
最后,我们利用今天学到的文件操作的方法,把这道信奥竞赛的试题完成。
通过分析,我们发现这道题解题的步骤是这样的:
现在,我们分步骤解题。
首先,创建文件 number.in:
10010010
代码 1#include <stdio.h>
int main() {
// 以 r 方式打开文件 number.in
FILE *fp = fopen("../number/number.in", "r");
// 关闭文件
fclose(fp);
}
代码 2
#include <stdio.h>
int main() {
FILE *fp = fopen("../number/number.in", "r");
char c;
// 循环读取 number.in 中的每一个字符
while((c = fgetc(fp)) != EOF) {
// 输出当前字符,测试
printf("%c", c); // 输出:10010010
}
fclose(fp);
}
代码 3
#include <stdio.h>
int main() {
FILE *fp = fopen("../number/number.in", "r");
// 定义计数器 sum,赋初始值 0
int sum = 0;
char c;
while((c = fgetc(fp)) != EOF) {
// 判断当前字符是否是 1
if (c == '1') {
sum++; // 计数器加 1
}
}
// 输出 sum,测试
printf("%d", sum); // 输出:3
fclose(fp);
}
代码 4
#include <stdio.h>
int main() {
FILE *fp = fopen("../number/number.in", "r");
int sum = 0;
char c;
while((c = fgetc(fp)) != EOF) {
if (c == '1') {
sum++;
}
}
fclose(fp);
// 以 w 方式创建文件 number.out
fp = fopen("../number/number.out", "w");
// 把计数结果写入文件 number.out
fputc(sum + '0', fp);
fclose(fp);
}
至此,我们就完成了这道信奥试题,不足 20 行代码,如果熟练的话,大概用时 5 分钟。
今天的内容有点多,同学们一定要好好复习一下哦,我们下次课见!