输入输出
翻译整理自 cppreference - cstdio。
1. 标准流
C 程序启动时自动打开三个标准流:
| 流 | 默认指向 |
|---|---|
stdin |
标准输入(键盘) |
stdout |
标准输出(屏幕) |
stderr |
标准错误(屏幕,无缓冲) |
#include <stdio.h>
fprintf(stdout, "stdout\n");
fprintf(stderr, "stderr\n");2. printf / scanf
int age;
printf("age: ");
scanf("%d", &age);
double pi;
scanf("%lf", &pi);
char name[32];
scanf("%31s", name);scanf 必须传地址。
%s不带宽度是缓冲区溢出高危。
scanf 返回值
int n = scanf("%d %d", &a, &b);
if (n != 2) {
fprintf(stderr, "input invalid\n");
}3. 文件操作
FILE *fp = fopen("data.txt", "r");
if (!fp) {
perror("fopen");
return 1;
}
// 读
int ch;
while ((ch = fgetc(fp)) != EOF) {
putchar(ch);
}
// 或整行读
char line[256];
while (fgets(line, sizeof(line), fp)) {
printf("%s", line);
}
fclose(fp);写文件
FILE *fp = fopen("out.txt", "w");
fprintf(fp, "name=%s\n", "Go");
fputs("another line\n", fp);
fputc('A', fp);
fclose(fp);模式
| 模式 | 含义 |
|---|---|
r |
只读(文件须存在) |
w |
覆盖写(不存在则创建) |
a |
追加 |
r+ |
读写 |
w+ |
读写(覆盖) |
a+ |
读写(追加) |
b |
二进制(可组合:rb、wb) |
4. 二进制 IO
typedef struct { int id; char name[32]; } User;
User u = {1, "Alice"};
FILE *fp = fopen("user.dat", "wb");
fwrite(&u, sizeof(u), 1, fp);
fclose(fp);
User v;
fp = fopen("user.dat", "rb");
fread(&v, sizeof(v), 1, fp);
fclose(fp);注意:结构体含指针时不能直接 fwrite,因为指针不指向文件数据。
5. 随机访问
fseek(fp, 0L, SEEK_SET); // 起始
fseek(fp, 0L, SEEK_END); // 末尾
fseek(fp, 10L, SEEK_CUR); // 相对当前位置
long pos = ftell(fp); // 当前位置
rewind(fp); // 等价 fseek(fp, 0, SEEK_SET)
获取文件大小:
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
rewind(fp);6. 缓冲
stdio 默认带缓冲(行缓冲或全缓冲):
setvbuf(fp, NULL, _IONBF, 0); // 无缓冲
setvbuf(fp, buf, _IOFBF, sizeof(buf)); // 全缓冲
fflush(fp); // 刷新输出
fflush只对输出流有意义,对输入流是未定义。
7. 字符与字符串 IO
int c = getchar(); // 等价 getc(stdin)
putchar('A'); // 等价 putc('A', stdout)
char *s = fgets(buf, n, stdin); // 安全,限制长度
puts("hello"); // 输出 + \n
8. 错误处理
FILE *fp = fopen("x.txt", "r");
if (!fp) {
perror("fopen"); // 输出形如 "fopen: No such file..."
fprintf(stderr, "errno=%d\n", errno);
}<errno.h> 提供 errno、strerror:
#include <errno.h>
#include <string.h>
printf("%s\n", strerror(errno));ferror / feof:
if (ferror(fp)) fprintf(stderr, "io error\n");
if (feof(fp)) printf("end of file\n");9. 命令行参数
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "usage: %s <file>\n", argv[0]);
return 1;
}
FILE *fp = fopen(argv[1], "r");
...
}10. sscanf / sprintf
char buf[64];
sprintf(buf, "%d-%d", 2026, 9);
int y, m;
sscanf("2026-9", "%d-%d", &y, &m);更安全的 snprintf:
snprintf(buf, sizeof(buf), "name=%s", name);小结
C 的 IO 完全围绕 FILE 指针,掌握 fopen/fread/fwrite/scanf/printf 后已能完成绝大多数任务。