当前位置: 首页 > news >正文

C语言 标准I/O函数全面指南

C标准I/O函数全面指南

本指南详细介绍了C语言中用于文件操作的标准输入/输出函数,包括单字符I/O、字符串I/O、格式化I/O、块I/O以及文件光标操作。每个部分包含函数定义、使用说明和实用示例,适合学习、复习以及博客发布。内容采用清晰的Markdown格式,代码规范,包含详细注释和最佳实践(如错误处理),以提升可读性和实用性。


1. 单字符读写:fputcfgetc

函数定义

  • fgetc

    #include <stdio.h>
    int fgetc(FILE *stream);
    
    • 功能:从指定文件中读取一个字符,并以无符号整数形式返回。
    • 参数stream - 文件指针。
    • 返回值
      • 成功:返回读取的字符(无符号整数形式)。
      • 失败:返回EOF并设置错误码。
  • fputc

    #include <stdio.h>
    int fputc(int c, FILE *stream);
    
    • 功能:将指定字符c写入到文件指针stream指向的文件中。
    • 参数
      • c:要写入的字符(以无符号整数形式传递)。
      • stream:文件指针。
    • 返回值
      • 成功:返回写入的字符(无符号整数形式)。
      • 失败:返回EOF并设置错误码。

示例代码

以下示例展示如何使用fputc写入字符到文件,并用fgetc读取文件内容。

#include <stdio.h>int main() {// 定义文件指针FILE *fp = NULL;// 以只写模式打开文件if ((fp = fopen("file.txt", "w")) == NULL) {perror("fopen error");return -1;}// 写入字符串 "Hello",每次写入一个字符fputc('H', fp);fputc('e', fp);fputc('l', fp);fputc('l', fp);fputc('o', fp);fclose(fp); // 关闭文件// 以只读模式重新打开文件if ((fp = fopen("file.txt", "r")) == NULL) {perror("fopen error");return -1;}// 逐字符读取并打印char ch;while ((ch = fgetc(fp)) != EOF) {printf("%c ", ch);}fclose(fp); // 关闭文件return 0;
}

说明

  • 写入fputc每次写入一个字符,文件光标自动向后移动。
  • 读取fgetc每次读取一个字符,遇到文件末尾返回EOF
  • 注意:写入后光标位于文件末尾,直接读取会失败,因此需重新打开文件或使用rewind重置光标。

2. 字符串读写:fgetsfputs

函数定义

  • fputs

    #include <stdio.h>
    int fputs(const char *s, FILE *stream);
    
    • 功能:将字符串s写入到文件指针stream指向的文件中(不包含字符串结束符\0)。
    • 参数
      • s:要写入的字符串。
      • stream:文件指针。
    • 返回值
      • 成功:返回写入的字符数(非负数)。
      • 失败:返回EOF
  • fgets

    #include <stdio.h>
    char *fgets(char *s, int size, FILE *stream);
    
    • 功能:从文件指针stream指向的文件中读取最多size-1个字符到数组s,遇到换行符或文件末尾停止,并在末尾自动添加\0
    • 参数
      • s:存储读取数据的字符数组。
      • size:最多读取的字符数(包含末尾\0)。
      • stream:文件指针。
    • 返回值
      • 成功:返回s(字符数组起始地址)。
      • 失败或文件末尾:返回NULL

示例代码

以下示例展示如何从终端输入字符串并写入文件,再从文件中读取并显示。

#include <stdio.h>
#include <string.h>int main() {// 定义文件指针FILE *fp = NULL;// 以只写模式打开文件if ((fp = fopen("file.txt", "w")) == NULL) {perror("fopen error");return -1;}// 从终端输入字符串并写入文件char wbuf[128];while (1) {printf("请输入字符串(输入quit退出):");fgets(wbuf, sizeof(wbuf), stdin); // 从标准输入读取wbuf[strcspn(wbuf, "\n")] = '\0'; // 移除换行符if (strcmp(wbuf, "quit") == 0) {break;}fputs(wbuf, fp); // 写入字符串fputc('\n', fp); // 添加换行符}fclose(fp);// 以只读模式打开文件if ((fp = fopen("file.txt", "r")) == NULL) {perror("fopen error");return -1;}// 逐行读取并打印char rbuf[128];while (fgets(rbuf, sizeof(rbuf), fp) != NULL) {printf("读取到:%s", rbuf);}fclose(fp);return 0;
}

说明

  • 写入fputs写入字符串,不包括\0,需手动添加换行符以分隔行。
  • 读取fgets读取一行(包含换行符),自动添加\0,适合逐行处理文本文件。
  • 注意fgets会保留输入的换行符,需用strcspn或类似方法移除。

3. 格式化读写:fprintffscanf

函数定义

  • fprintf

    #include <stdio.h>
    int fprintf(FILE *stream, const char *format, ...);
    
    • 功能:按指定格式将数据写入文件。
    • 参数
      • stream:文件指针(可为stdoutstderr)。
      • format:格式化字符串,包含格式控制符(如%d%s%f%lf)。
      • ...:可变参数,数量由格式控制符决定。
    • 返回值
      • 成功:返回写入的字符数。
      • 失败:返回负数。
  • fscanf

    #include <stdio.h>
    int fscanf(FILE *stream, const char *format, ...);
    
    • 功能:按指定格式从文件中读取数据到变量中。
    • 参数
      • stream:文件指针(可为stdin)。
      • format:格式化字符串,包含格式控制符。
      • ...:变量地址列表,数量由格式控制符决定。
    • 返回值
      • 成功:返回成功读取的项数。
      • 失败或文件末尾:返回EOF并设置错误码。

示例代码

以下示例展示格式化读写到标准输出/输入和外部文件。

#include <stdio.h>int main() {// 向标准输出写入格式化数据fprintf(stdout, "整数: %d, 小数: %.2f, 字符串: %s\n", 520, 3.14, "I Love C");// 从标准输入读取整数int num;printf("请输入一个整数:");if (fscanf(stdin, "%d", &num) == 1) {printf("读取到:%d\n", num);} else {printf("读取失败\n");}// 写入格式化数据到文件FILE *fp = NULL;if ((fp = fopen("usr.txt", "w")) == NULL) {perror("fopen error");return -1;}fprintf(fp, "%s %d", "admin", 123456); // 写入用户名和密码fclose(fp);// 从文件中读取格式化数据if ((fp = fopen("usr.txt", "r")) == NULL) {perror("fopen error");return -1;}char usrName[20];int pwd;if (fscanf(fp, "%s %d", usrName, &pwd) == 2) {printf("用户名: %s, 密码: %d\n", usrName, pwd);} else {printf("读取失败\n");}fclose(fp);return 0;
}

说明

  • 格式化fprintffscanf支持多种数据类型(如整数、浮点数、字符串),灵活性高。
  • 标准I/O:使用stdoutstdin可直接操作终端输入输出。
  • 注意fscanf读取时需确保变量地址正确,格式匹配,否则可能导致错误。

4. 格式串转字符串:sprintfsnprintf

函数定义

  • sprintf

    #include <stdio.h>
    int sprintf(char *str, const char *format, ...);
    
    • 功能:将格式化数据转换为字符串,存储到字符数组str中。
    • 参数
      • str:目标字符数组。
      • format:格式化字符串。
      • ...:可变参数。
    • 返回值
      • 成功:返回转换的字符数(不含\0)。
      • 失败:返回EOF
  • snprintf

    #include <stdio.h>
    int snprintf(char *str, size_t size, const char *format, ...);
    
    • 功能:将格式化数据转换为字符串,最多存储size-1个字符到str,并添加\0
    • 参数
      • str:目标字符数组。
      • size:最大存储字符数(含\0)。
      • format:格式化字符串。
      • ...:可变参数。
    • 返回值
      • 成功:返回应写入的字符数(不含\0)。
      • 如果超出size:返回应写入的字符数(但只写入size-1个字符)。
      • 失败:返回EOF

示例代码

以下示例展示如何将多种数据类型组合成字符串。

#include <stdio.h>int main() {char buf[20];// 使用 sprintf(不安全,可能溢出)sprintf(buf, "%d %s %.1f", 1001, "zhangsan", 99.5);printf("sprintf结果: %s\n", buf);// 使用 snprintf(安全,限制长度)snprintf(buf, sizeof(buf), "%d %s %.1f", 1001, "zhangsan", 99.5);printf("snprintf结果: %s\n", buf);return 0;
}

说明

  • 安全性sprintf可能导致缓冲区溢出,推荐使用snprintf以限制写入长度。
  • 用途:常用于将多种数据类型组合成字符串,便于后续处理或输出。
  • 注意:确保buf大小足够容纳格式化结果,snprintf更适合现代编程。

5. 模块化读写:freadfwrite

函数定义

  • fread

    #include <stdio.h>
    size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    
    • 功能:从文件读取nmemb项数据,每项大小为size字节,存储到ptr指向的内存。
    • 参数
      • ptr:存储数据的内存地址(支持任意类型)。
      • size:每项数据的大小(字节)。
      • nmemb:读取的项数。
      • stream:文件指针。
    • 返回值
      • 成功:返回实际读取的项数。
      • 失败或文件末尾:返回小于nmemb的值或0。
  • fwrite

    #include <stdio.h>
    size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
    
    • 功能:将ptr指向的nmemb项数据(每项size字节)写入文件。
    • 参数
      • ptr:要写入的数据地址。
      • size:每项数据的大小(字节)。
      • nmemb:写入的项数。
      • stream:文件指针。
    • 返回值
      • 成功:返回实际写入的项数。
      • 失败:返回小于nmemb的值或0。

示例代码

字符串读写
#include <stdio.h>
#include <string.h>int main() {FILE *fp = NULL;// 以只写模式打开文件if ((fp = fopen("test.txt", "w")) == NULL) {perror("fopen error");return -1;}// 循环输入字符串并写入char wbuf[128];while (1) {printf("请输入字符串(输入quit退出):");fgets(wbuf, sizeof(wbuf), stdin);wbuf[strcspn(wbuf, "\n")] = '\0';if (strcmp(wbuf, "quit") == 0) {break;}fwrite(wbuf, strlen(wbuf), 1, fp); // 写入字符串fwrite("\n", 1, 1, fp); // 添加换行fflush(fp); // 刷新缓冲区}fclose(fp);// 以只读模式打开文件if ((fp = fopen("test.txt", "r")) == NULL) {perror("fopen error");return -1;}// 读取并输出char rbuf[10];size_t res;while ((res = fread(rbuf, 1, sizeof(rbuf) - 1, fp)) > 0) {rbuf[res] = '\0'; // 添加结束符fwrite(rbuf, 1, res, stdout); // 输出到终端}fclose(fp);return 0;
}
整数读写
#include <stdio.h>int main() {FILE *fp = NULL;// 以只写模式打开文件if ((fp = fopen("test.txt", "w")) == NULL) {perror("fopen error");return -1;}// 写入整数int num = 16;fwrite(&num, sizeof(int), 1, fp);fclose(fp);// 以只读模式打开文件if ((fp = fopen("test.txt", "r")) == NULL) {perror("fopen error");return -1;}// 读取整数int key;if (fread(&key, sizeof(int), 1, fp) == 1) {printf("读取到: %d\n", key);} else {printf("读取失败\n");}fclose(fp);return 0;
}
结构体读写
#include <stdio.h>
#include <string.h>typedef struct {char name[20];int age;double score;
} Stu;int main() {FILE *fp = NULL;// 以只写模式打开文件if ((fp = fopen("test.txt", "w")) == NULL) {perror("fopen error");return -1;}// 定义并写入学生数据Stu students[] = {{"张三", 18, 98.0},{"李四", 20, 88.0},{"王五", 16, 95.0}};fwrite(students, sizeof(Stu), 3, fp);fclose(fp);// 以只读模式打开文件if ((fp = fopen("test.txt", "r")) == NULL) {perror("fopen error");return -1;}// 读取并显示一个学生信息Stu temp;if (fread(&temp, sizeof(Stu), 1, fp) == 1) {printf("姓名: %s, 年龄: %d, 成绩: %.2f\n", temp.name, temp.age, temp.score);}fclose(fp);return 0;
}

说明

  • 灵活性freadfwrite支持任意数据类型(如字符串、整数、结构体),适合二进制文件操作。
  • 注意:二进制读写需确保数据结构对齐一致,跨平台时需考虑字节序。

6. 文件光标操作:fseek, ftell, rewind

函数定义

  • fseek

    #include <stdio.h>
    int fseek(FILE *stream, long offset, int whence);
    
    • 功能:移动文件光标到指定位置。
    • 参数
      • stream:文件指针。
      • offset:偏移量(正:向后,负:向前,0:不动)。
      • whence:起始位置(SEEK_SET:文件开头,SEEK_CUR:当前位置,SEEK_END:文件末尾)。
    • 返回值
      • 成功:返回0。
      • 失败:返回-1并设置错误码。
  • ftell

    #include <stdio.h>
    long ftell(FILE *stream);
    
    • 功能:获取文件光标的当前偏移量(相对于文件开头)。
    • 参数stream - 文件指针。
    • 返回值
      • 成功:返回当前偏移量(字节)。
      • 失败:返回-1并设置错误码。
  • rewind

    #include <stdio.h>
    void rewind(FILE *stream);
    
    • 功能:将文件光标重置到文件开头(等效于fseek(stream, 0, SEEK_SET))。
    • 参数stream - 文件指针。
    • 返回值:无。

示例代码

以下示例展示如何操作文件光标并读取特定位置的数据。

#include <stdio.h>
#include <string.h>typedef struct {char name[20];int age;double score;
} Stu;int main() {FILE *fp = NULL;// 以读写模式打开文件if ((fp = fopen("test.txt", "w+")) == NULL) {perror("fopen error");return -1;}// 写入三个学生数据Stu students[] = {{"张三", 18, 98.0},{"李四", 20, 88.0},{"王五", 16, 95.0}};fwrite(students, sizeof(Stu), 3, fp);// 获取文件大小fseek(fp, 0, SEEK_END);printf("文件大小: %ld 字节\n", ftell(fp));// 移动光标到第二个学生fseek(fp, sizeof(Stu), SEEK_SET);// 读取并显示第二个学生信息Stu temp;if (fread(&temp, sizeof(Stu), 1, fp) == 1) {printf("姓名: %s, 年龄: %d, 成绩: %.2f\n", temp.name, temp.age, temp.score);}fclose(fp);return 0;
}

说明

  • 光标操作fseek灵活控制文件读取位置,ftell可用于计算文件大小。
  • 重置光标rewind适合在同一文件流中从头重新读取。
  • 注意:二进制文件操作时,偏移量需与数据结构大小对齐。

总结与注意事项

  • 文件操作流程:始终检查fopen返回值,确保文件打开成功;操作完成后使用fclose关闭文件。
  • 错误处理:使用perror或检查返回值捕获错误,确保程序健壮性。
  • 缓冲区管理:写入数据后可用fflush刷新缓冲区,确保数据及时写入。
  • 安全性:优先使用snprintf而非sprintf,避免缓冲区溢出。
  • 跨平台注意:二进制文件读写需考虑字节序和结构体对齐问题。
http://www.xdnf.cn/news/895087.html

相关文章:

  • Form开发指南-第二弹:基本配置与开发流程
  • 用ApiFox MCP一键生成接口文档,做接口测试
  • C++ 重载和模板
  • 离散数学_数理逻辑(三):一阶逻辑概念及一阶逻辑命题符号化
  • 蒙特卡罗模拟: 高级应用的思路和实例
  • minimatch 详解:功能、语法与应用场景
  • ResolverActivity 优先级
  • 竞品分析六大步骤
  • 如何防止看板任务长期停滞不前
  • 【xshell】已经安装对应版本xftp,xshell中点击xftp快捷按钮,提示“使用此功能需要Xftp。单击下载按钮,转到Xftp下载页”
  • 如何在运动中保护好半月板?
  • 插入排序,二分查找,字符数组 day8
  • linux C语言中的动态库 静态库说明
  • 智慧停车设备选型指南:何时应优先考虑免布线视频桩方案?
  • QT中使用libcurl库实现到ftp服务器的上传和下载
  • Debugger encountered an exception:Exception at 0x7ff809232bdc
  • 【6.2-6.9学习周报】
  • [免费]SpringBoot+Vue鲜花销售商城系统【论文+源码+SQL脚本】
  • Spring Boot统一功能处理深度解析
  • 如何设置合适的缓存过期时间(TTL)?是否有必要实现缓存预热?
  • 【PmHub面试篇】PmHub集成Redission分布式锁保障流程状态更新面试专题解析
  • 【inode使用 100%,导致项目异常】
  • 【学习分享】shell基础-参数传递
  • 使用反射对任意对象进行二进制序列化的程序
  • 行内样式:深入解析与应用指南
  • Vue.js应用结合Redis数据库:实践与优化
  • 更改安卓虚拟机屏幕大小
  • ICLR文章如何寻找页码
  • 【高频面试题】快慢指针及相关应用
  • 客户体验数据使用的三种视角——场景视角