Skip to content

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 语言编程的基础:

  1. 功能全面 - 涵盖文件操作、格式化 I/O、字符 I/O 等
  2. 易于使用 - 提供了简单直观的接口
  3. 广泛应用 - 几乎所有 C 程序都会使用

记住:

  • 始终检查文件操作是否成功
  • 记得关闭打开的文件
  • 使用安全的函数(如 fgets 而不是 gets)
  • 检查函数的返回值