Appearance
C 标准库 - <stdio.h>
概述
<stdio.h> 头文件提供了输入/输出(I/O)功能,包括文件操作、格式化输入/输出、字符输入/输出等。这是 C 语言中最常用的标准库之一。
标准流
stdin
标准输入流(通常是键盘)。
c
#include <stdio.h>
int main() {
int value;
printf("请输入一个整数: ");
scanf("%d", &value);
printf("你输入的值是: %d\n", value);
return 0;
}stdout
标准输出流(通常是屏幕)。
c
#include <stdio.h>
int main() {
printf("Hello, World!\n");
fprintf(stdout, "输出到标准输出\n");
return 0;
}stderr
标准错误流(通常是屏幕)。
c
#include <stdio.h>
int main() {
fprintf(stderr, "这是一个错误消息\n");
return 0;
}文件操作
fopen()
c
FILE *fopen(const char *filename, const char *mode);打开文件。
c
#include <stdio.h>
int main() {
FILE* file = fopen("test.txt", "w");
if (file == NULL) {
perror("打开文件失败");
return 1;
}
fprintf(file, "Hello, File!\n");
fclose(file);
return 0;
}fclose()
c
int fclose(FILE *stream);关闭文件。
c
#include <stdio.h>
int main() {
FILE* file = fopen("test.txt", "w");
if (file == NULL) {
return 1;
}
fprintf(file, "Hello, File!\n");
fclose(file);
return 0;
}fread()
c
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);从文件读取数据。
c
#include <stdio.h>
int main() {
FILE* file = fopen("test.txt", "r");
if (file == NULL) {
return 1;
}
char buffer[100];
size_t bytes_read = fread(buffer, 1, sizeof(buffer), file);
buffer[bytes_read] = '\0';
printf("读取的内容: %s\n", buffer);
fclose(file);
return 0;
}fwrite()
c
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);向文件写入数据。
c
#include <stdio.h>
int main() {
FILE* file = fopen("test.txt", "w");
if (file == NULL) {
return 1;
}
const char* text = "Hello, File!";
size_t bytes_written = fwrite(text, 1, strlen(text), file);
printf("写入了 %zu 字节\n", bytes_written);
fclose(file);
return 0;
}fseek()
c
int fseek(FILE *stream, long offset, int whence);设置文件位置指示器。
c
#include <stdio.h>
int main() {
FILE* file = fopen("test.txt", "w+");
if (file == NULL) {
return 1;
}
fprintf(file, "Hello, World!");
fseek(file, 7, SEEK_SET);
fprintf(file, "C Programming");
rewind(file);
char buffer[100];
fread(buffer, 1, sizeof(buffer), file);
buffer[20] = '\0';
printf("文件内容: %s\n", buffer);
fclose(file);
return 0;
}ftell()
c
long ftell(FILE *stream);获取当前文件位置。
c
#include <stdio.h>
int main() {
FILE* file = fopen("test.txt", "r");
if (file == NULL) {
return 1;
}
fseek(file, 0, SEEK_END);
long size = ftell(file);
printf("文件大小: %ld 字节\n", size);
fclose(file);
return 0;
}rewind()
c
void rewind(FILE *stream);将文件位置指示器重置到文件开头。
c
#include <stdio.h>
int main() {
FILE* file = fopen("test.txt", "w");
if (file == NULL) {
return 1;
}
fprintf(file, "Hello, World!");
rewind(file);
char buffer[100];
fread(buffer, 1, sizeof(buffer), file);
buffer[13] = '\0';
printf("文件内容: %s\n", buffer);
fclose(file);
return 0;
}格式化输出
printf()
c
int printf(const char *format, ...);格式化输出到标准输出。
c
#include <stdio.h>
int main() {
int age = 25;
char name[] = "张三";
double height = 1.75;
printf("姓名: %s\n", name);
printf("年龄: %d\n", age);
printf("身高: %.2f 米\n", height);
return 0;
}fprintf()
c
int fprintf(FILE *stream, const char *format, ...);格式化输出到指定流。
c
#include <stdio.h>
int main() {
FILE* file = fopen("output.txt", "w");
if (file == NULL) {
return 1;
}
fprintf(file, "姓名: %s\n", "张三");
fprintf(file, "年龄: %d\n", 25);
fprintf(file, "身高: %.2f 米\n", 1.75);
fclose(file);
return 0;
}sprintf()
c
int sprintf(char *str, const char *format, ...);格式化输出到字符串。
c
#include <stdio.h>
int main() {
char buffer[100];
int age = 25;
char name[] = "张三";
sprintf(buffer, "%s 今年 %d 岁", name, age);
printf("%s\n", buffer);
return 0;
}snprintf()
c
int snprintf(char *str, size_t size, const char *format, ...);安全的格式化输出到字符串。
c
#include <stdio.h>
int main() {
char buffer[10];
int age = 25;
char name[] = "张三";
snprintf(buffer, sizeof(buffer), "%s 今年 %d 岁", name, age);
printf("%s\n", buffer);
return 0;
}格式化输入
scanf()
c
int scanf(const char *format, ...);从标准输入格式化读取。
c
#include <stdio.h>
int main() {
int age;
char name[50];
printf("请输入姓名: ");
scanf("%s", name);
printf("请输入年龄: ");
scanf("%d", &age);
printf("姓名: %s, 年龄: %d\n", name, age);
return 0;
}fscanf()
c
int fscanf(FILE *stream, const char *format, ...);从文件格式化读取。
c
#include <stdio.h>
int main() {
FILE* file = fopen("data.txt", "w");
if (file == NULL) {
return 1;
}
fprintf(file, "张三 25\n");
fprintf(file, "李四 30\n");
fclose(file);
file = fopen("data.txt", "r");
char name[50];
int age;
while (fscanf(file, "%s %d", name, &age) == 2) {
printf("姓名: %s, 年龄: %d\n", name, age);
}
fclose(file);
return 0;
}sscanf()
c
int sscanf(const char *str, const char *format, ...);从字符串格式化读取。
c
#include <stdio.h>
int main() {
char str[] = "张三 25";
char name[50];
int age;
sscanf(str, "%s %d", name, &age);
printf("姓名: %s, 年龄: %d\n", name, age);
return 0;
}字符输入/输出
getchar()
c
int getchar(void);从标准输入读取一个字符。
c
#include <stdio.h>
int main() {
printf("请输入一个字符: ");
int c = getchar();
printf("你输入的字符是: %c\n", c);
return 0;
}putchar()
c
int putchar(int c);向标准输出写入一个字符。
c
#include <stdio.h>
int main() {
putchar('H');
putchar('e');
putchar('l');
putchar('l');
putchar('o');
putchar('\n');
return 0;
}gets()
c
char *gets(char *s);从标准输入读取一行(已废弃,不推荐使用)。
c
#include <stdio.h>
int main() {
char buffer[100];
printf("请输入一行文本: ");
gets(buffer);
printf("你输入的是: %s\n", buffer);
return 0;
}fgets()
c
char *fgets(char *s, int size, FILE *stream);从流中安全读取一行。
c
#include <stdio.h>
int main() {
char buffer[100];
printf("请输入一行文本: ");
fgets(buffer, sizeof(buffer), stdin);
printf("你输入的是: %s", buffer);
return 0;
}puts()
c
int puts(const char *s);向标准输出写入字符串并添加换行符。
c
#include <stdio.h>
int main() {
puts("Hello, World!");
puts("C Programming");
return 0;
}fputs()
c
int fputs(const char *s, FILE *stream);向流中写入字符串。
c
#include <stdio.h>
int main() {
FILE* file = fopen("output.txt", "w");
if (file == NULL) {
return 1;
}
fputs("Hello, World!\n", file);
fputs("C Programming\n", file);
fclose(file);
return 0;
}文件状态
feof()
c
int feof(FILE *stream);检查是否到达文件末尾。
c
#include <stdio.h>
int main() {
FILE* file = fopen("test.txt", "r");
if (file == NULL) {
return 1;
}
int c;
while ((c = fgetc(file)) != EOF) {
putchar(c);
}
if (feof(file)) {
printf("\n到达文件末尾\n");
}
fclose(file);
return 0;
}ferror()
c
int ferror(FILE *stream);检查文件流是否发生错误。
c
#include <stdio.h>
int main() {
FILE* file = fopen("test.txt", "r");
if (file == NULL) {
return 1;
}
char buffer[100];
fread(buffer, 1, sizeof(buffer), file);
if (ferror(file)) {
printf("读取文件时发生错误\n");
} else {
printf("文件读取成功\n");
}
fclose(file);
return 0;
}clearerr()
c
void clearerr(FILE *stream);清除文件流的错误和文件结束标志。
c
#include <stdio.h>
int main() {
FILE* file = fopen("test.txt", "r");
if (file == NULL) {
return 1;
}
char buffer[100];
fread(buffer, 1, sizeof(buffer), file);
if (ferror(file)) {
printf("读取文件时发生错误\n");
clearerr(file);
}
fclose(file);
return 0;
}文件定位
fseek()
c
int fseek(FILE *stream, long offset, int whence);设置文件位置指示器。
c
#include <stdio.h>
int main() {
FILE* file = fopen("test.txt", "w");
if (file == NULL) {
return 1;
}
fprintf(file, "Hello, World!");
fseek(file, 7, SEEK_SET);
fprintf(file, "C Programming");
fclose(file);
return 0;
}ftell()
c
long ftell(FILE *stream);获取当前文件位置。
c
#include <stdio.h>
int main() {
FILE* file = fopen("test.txt", "r");
if (file == NULL) {
return 1;
}
fseek(file, 0, SEEK_END);
long size = ftell(file);
printf("文件大小: %ld 字节\n", size);
fclose(file);
return 0;
}rewind()
c
void rewind(FILE *stream);将文件位置指示器重置到文件开头。
c
#include <stdio.h>
int main() {
FILE* file = fopen("test.txt", "w");
if (file == NULL) {
return 1;
}
fprintf(file, "Hello, World!");
rewind(file);
char buffer[100];
fread(buffer, 1, sizeof(buffer), file);
buffer[13] = '\0';
printf("文件内容: %s\n", buffer);
fclose(file);
return 0;
}实际应用示例
1. 文件复制
c
#include <stdio.h>
void copy_file(const char* src, const char* dest) {
FILE* src_file = fopen(src, "rb");
if (src_file == NULL) {
perror("无法打开源文件");
return;
}
FILE* dest_file = fopen(dest, "wb");
if (dest_file == NULL) {
perror("无法打开目标文件");
fclose(src_file);
return;
}
char buffer[4096];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), src_file)) > 0) {
fwrite(buffer, 1, bytes_read, dest_file);
}
fclose(src_file);
fclose(dest_file);
printf("文件复制完成\n");
}
int main() {
copy_file("source.txt", "destination.txt");
return 0;
}2. 读取配置文件
c
#include <stdio.h>
#include <string.h>
#define MAX_LINE 256
void read_config(const char* filename) {
FILE* file = fopen(filename, "r");
if (file == NULL) {
perror("无法打开配置文件");
return;
}
char line[MAX_LINE];
while (fgets(line, sizeof(line), file) != NULL) {
if (line[0] == '#' || line[0] == '\n') {
continue;
}
char key[100], value[100];
if (sscanf(line, "%99[^=]=%99s", key, value) == 2) {
printf("配置项: %s = %s\n", key, value);
}
}
fclose(file);
}
int main() {
read_config("config.txt");
return 0;
}3. 日志系统
c
#include <stdio.h>
#include <time.h>
void log_message(const char* level, const char* message) {
time_t now = time(NULL);
struct tm* tm = localtime(&now);
FILE* log_file = fopen("app.log", "a");
if (log_file != NULL) {
fprintf(log_file, "[%04d-%02d-%02d %02d:%02d:%02d] [%s] %s\n",
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
level, message);
fclose(log_file);
}
printf("[%s] %s\n", level, message);
}
int main() {
log_message("INFO", "程序启动");
log_message("DEBUG", "处理数据中...");
log_message("ERROR", "连接失败");
log_message("INFO", "程序结束");
return 0;
}4. 文件统计
c
#include <stdio.h>
typedef struct {
long lines;
long words;
long chars;
} FileStats;
FileStats count_file(const char* filename) {
FileStats stats = {0, 0, 0};
FILE* file = fopen(filename, "r");
if (file == NULL) {
perror("无法打开文件");
return stats;
}
int c;
int in_word = 0;
while ((c = fgetc(file)) != EOF) {
stats.chars++;
if (c == '\n') {
stats.lines++;
}
if (c == ' ' || c == '\t' || c == '\n') {
in_word = 0;
} else if (!in_word) {
in_word = 1;
stats.words++;
}
}
fclose(file);
return stats;
}
int main() {
FileStats stats = count_file("test.txt");
printf("行数: %ld\n", stats.lines);
printf("单词数: %ld\n", stats.words);
printf("字符数: %ld\n", stats.chars);
return 0;
}5. 二进制文件处理
c
#include <stdio.h>
typedef struct {
int id;
char name[50];
double score;
} Student;
void write_student(const char* filename, Student* student) {
FILE* file = fopen(filename, "ab");
if (file == NULL) {
perror("无法打开文件");
return;
}
fwrite(student, sizeof(Student), 1, file);
fclose(file);
}
void read_students(const char* filename) {
FILE* file = fopen(filename, "rb");
if (file == NULL) {
perror("无法打开文件");
return;
}
Student student;
printf("学生信息:\n");
while (fread(&student, sizeof(Student), 1, file) == 1) {
printf("ID: %d, 姓名: %s, 分数: %.2f\n",
student.id, student.name, student.score);
}
fclose(file);
}
int main() {
Student s1 = {1, "张三", 95.5};
Student s2 = {2, "李四", 88.0};
Student s3 = {3, "王五", 92.5};
write_student("students.dat", &s1);
write_student("students.dat", &s2);
write_student("students.dat", &s3);
read_students("students.dat");
return 0;
}6. 交互式菜单
c
#include <stdio.h>
void show_menu() {
printf("\n=== 主菜单 ===\n");
printf("1. 添加记录\n");
printf("2. 查看记录\n");
printf("3. 删除记录\n");
printf("4. 退出\n");
printf("请选择: ");
}
int main() {
int choice;
do {
show_menu();
scanf("%d", &choice);
switch (choice) {
case 1:
printf("添加记录\n");
break;
case 2:
printf("查看记录\n");
break;
case 3:
printf("删除记录\n");
break;
case 4:
printf("退出程序\n");
break;
default:
printf("无效的选择\n");
}
} while (choice != 4);
return 0;
}7. 文件搜索
c
#include <stdio.h>
#include <string.h>
void search_in_file(const char* filename, const char* keyword) {
FILE* file = fopen(filename, "r");
if (file == NULL) {
perror("无法打开文件");
return;
}
char line[1024];
int line_number = 0;
int found = 0;
while (fgets(line, sizeof(line), file) != NULL) {
line_number++;
if (strstr(line, keyword) != NULL) {
printf("第 %d 行: %s", line_number, line);
found = 1;
}
}
fclose(file);
if (!found) {
printf("未找到关键词: %s\n", keyword);
} else {
printf("找到 %d 处匹配\n", found);
}
}
int main() {
search_in_file("test.txt", "Hello");
return 0;
}注意事项
1. 检查文件打开是否成功
c
#include <stdio.h>
void good_practice() {
FILE* file = fopen("test.txt", "r");
if (file == NULL) {
perror("打开文件失败");
return;
}
fclose(file);
}
void bad_practice() {
FILE* file = fopen("test.txt", "r");
fclose(file);
}2. 关闭文件
c
#include <stdio.h>
void good_practice() {
FILE* file = fopen("test.txt", "w");
if (file != NULL) {
fprintf(file, "Hello, World!");
fclose(file);
}
}
void bad_practice() {
FILE* file = fopen("test.txt", "w");
if (file != NULL) {
fprintf(file, "Hello, World!");
}
}3. 使用安全的函数
c
#include <stdio.h>
void good_practice() {
char buffer[100];
fgets(buffer, sizeof(buffer), stdin);
}
void bad_practice() {
char buffer[100];
gets(buffer);
}4. 检查返回值
c
#include <stdio.h>
void good_practice() {
int result = printf("Hello, World!\n");
if (result < 0) {
printf("输出失败\n");
}
}
void bad_practice() {
printf("Hello, World!\n");
}总结
<stdio.h> 提供的输入/输出功能是 C 语言编程的基础:
- 功能全面 - 涵盖文件操作、格式化 I/O、字符 I/O 等
- 易于使用 - 提供了简单直观的接口
- 广泛应用 - 几乎所有 C 程序都会使用
记住:
- 始终检查文件操作是否成功
- 记得关闭打开的文件
- 使用安全的函数(如 fgets 而不是 gets)
- 检查函数的返回值