除了使用格式字符串的 printf/fprintf 和 scanf/fscanf,C 还提供按字符与按行传输文本的流函数。stdin 和 stdout 也是 FILE * 流,所以控制台函数与文件函数遵循同一套流模型。
getchar 与 putchar
getchar() 等价于从 stdin 调用 fgetc;putchar(ch) 把一个字符写到 stdout。两者都使用 int,以便同时表示所有 unsigned char 值和特殊值 EOF。
#include <stdio.h>
int main(void) {
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) {
putchar(ch);
}
putchar('\n');
return 0;
}fgetc 与 fputc
fgetc(fp) 从指定流读取下一个字节,返回提升后的字符值或 EOF。fputc(ch, fp) 向指定流写一个字符,失败时返回 EOF。
示例会使用 file-io-sample.txt。请复制下面的文本,在程序的工作目录中自行创建该文件:
Leaflet file I/O sample
The second line is ready to read.#include <stdio.h>
int main(void) {
FILE *source = fopen("file-io-sample.txt", "r");
FILE *target = fopen("first-character.txt", "w");
if (source == NULL || target == NULL) {
if (source != NULL) {
fclose(source);
}
if (target != NULL) {
fclose(target);
}
return 1;
}
int ch = fgetc(source);
if (ch != EOF) {
if (fputc(ch, target) == EOF) {
fclose(source);
fclose(target);
return 1;
}
}
fclose(source);
fclose(target);
return 0;
}gets 与 puts
gets 无法获知缓冲区容量,会造成越界写入,已从 C11 标准中删除。下面只展示旧代码曾经怎样调用它;不要编译或使用。puts 仍然安全可用,它输出字符串并自动追加换行。
/* Historical example — never use this pattern.
char text[16];
gets(text);
puts(text);
*/如果只需要输出固定文本,puts 可以单独使用:
#include <stdio.h>
int main(void) {
puts("File processing complete.");
return 0;
}fgets 与 fputs
fgets(buffer, size, stream) 最多读取 size−1 个字符并写入 \0;如果换行符在容量范围内,它也会保留换行符。fputs(text, stream) 写字符串,但不会自动增加换行。
#include <stdio.h>
int main(void) {
char line[80];
fputs("Enter a line: ", stdout);
if (fgets(line, sizeof line, stdin) == NULL) {
return 1;
}
fputs("You entered: ", stdout);
fputs(line, stdout);
return 0;
}读取函数返回 EOF 或 NULL 时,可能是正常到达文件末尾,也可能是发生错误。需要区分时,可在读取后使用 feof 和 ferror。
知识测验
知识测验
知识测验
知识测验
安全读取并标记一行
声明 80 字节数组,用 fgets 从 stdin 读取一行。成功时先用 fputs 输出 received: ,再原样输出该行;失败时返回 1。不得使用 gets、scanf 或 printf。
- 准备固定容量字符数组并调用 fgets。
- 读取失败时不要继续使用缓冲区。
- 使用 fputs 输出标签与原始行,并检查返回值。
逐字符复制文本文件
复制本节给出的文本并自行创建 file-io-sample.txt,然后打开它读取,并创建 character-copy.txt 写入。用 fgetc/fputc 逐字符复制,检查写入失败和源流的 ferror,最后关闭两个文件。
- 分别以读取和写入模式打开两个文件,并检查返回值。
- 用 int 保存 fgetc 结果,循环到 EOF。
- 检查 fputc 与 fclose 的结果,确保所有已打开文件都被关闭。