2.C语言文件操作(一):fgetc(),fgets(),fread的区别

三个函数的返回值类型和含义完全不同,这是使用时最容易混淆的地方。下面详细说明:


📌 返回值对比总结

函数 返回值类型 成功时返回值 失败/结束时返回值 主要用途
fgetc() int 读取的字符(0~255) EOF(通常是 -1) 判断是否读到文件末尾
fgets() char* 指向缓冲区的指针(即传入的 str NULL 判断是否读取成功
fread() size_t 成功读取的元素个数 小于请求的元素个数(包括0) 判断实际读取了多少数据

1. fgetc() ------ 返回 字符值EOF

复制代码
int fgetc(FILE *stream);
  • 成功 :返回读取的字符(转换为 unsigned char 再转为 int
    • 范围:0 ~ 255(ASCII字符)
  • 失败/EOF :返回 EOF(通常是 -1)

正确用法:

复制代码
int ch;  // 必须用 int,不能用 char!
while ((ch = fgetc(fp)) != EOF) {
    putchar(ch);  // ch 是实际字符
}

⚠️ 重要 :必须用 int 类型接收,因为 char 可能无法区分 EOF(-1)和字符 0xFF

或者

复制代码
int ch;  // 必须用 int,不能用 char!
while ((ch = fgetc(fp)) != -1) {
    putchar(ch);  // ch 是实际字符
}

2. fgets() ------ 返回 指针NULL

复制代码
char *fgets(char *str, int size, FILE *stream);
  • 成功 :返回传入的缓冲区指针(即 str
  • 失败/EOF :返回 NULL

正确用法:

复制代码
char buf[100];
while (fgets(buf, sizeof(buf), fp) != NULL) {
    printf("%s", buf);  // buf 包含读取的内容
}

💡 即使只读到一个换行符 \n,也算成功,返回非 NULL


3. fread() ------ 返回 元素个数(不是字节数!)

复制代码
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
  • 完全成功 :返回 nmemb(请求的元素个数)
  • ⚠️ 部分成功/EOF :返回实际读取的元素个数 (0 到 nmemb-1
  • 完全失败:返回 0

正确用法:

复制代码
int arr[10];
size_t count = fread(arr, sizeof(int), 10, fp);

if (count == 10) {
    printf("完整读取10个整数\n");
} else if (count > 0) {
    printf("部分读取,只读了 %zu 个整数\n", count);
} else {
    printf("读取失败或文件为空\n");
}

🔑 关键点 :返回的是元素个数 ,不是字节数!

例如:fread(buf, 4, 5, fp) 最多返回 5(表示5个4字节的元素)


🧪 实际例子对比

假设文件内容:"ABC"(3字节)

复制代码
// fgetc()
int ch;
while ((ch = fgetc(fp)) != EOF) {  // 循环3次,ch分别是 'A','B','C'
    // 处理字符
}

// fgets()
char buf[10];
if (fgets(buf, 10, fp) != NULL) {  // 返回 buf 的地址(非NULL)
    // buf = "ABC\0"
}

// fread()
char data[10];
size_t n = fread(data, 1, 10, fp);  // 返回 3(读取了3个1字节的元素)

✅ 使用要点总结

  • fgetc() :用 int 接收,与 EOF 比较
  • fgets() :与 NULL 比较,成功时直接使用缓冲区
  • fread() :检查返回的元素个数,判断是否完整读取

理解这三个函数返回值的区别,是正确使用它们的关键!

相关推荐
白狐_7984 小时前
408数据结构第8章:排序②——性质对比秒杀、场景选择与外部排序
java·数据结构·算法
zander2585 小时前
LeetCode 84:柱状图中的最大矩形——单调栈如何确定左右边界
java·数据结构·算法
Shell运维手记5 小时前
Linux 常用基础命令学习笔记
linux·运维·笔记·学习·算法·github
qq_448011165 小时前
C语言中的动态内存分配
c语言·开发语言·php
杨航 AI5 小时前
O(n log n):线性对数原理拆解 这个是排序算法的黄金复杂度之一。
算法·排序算法
船厂电气自动化ai大模型6 小时前
AI大模型与数学 第32课 函数凹凸性与二阶导数:拐点求解、凹凸区间计算(10道二阶导数计算题)
数据结构·人工智能·python·深度学习·算法
动词ing6 小时前
【学习笔记】C语言(数组指针与指针数组+字符数组+函数+参数传递+字符串作为形参+递归函数+指针函数+回调函数+结构体嵌套+内存动态分配函数)
c语言·笔记·学习
旖旎夜光6 小时前
LeetCode 3:无重复字符的最长子串(滑动窗口) —— 题解
数据结构·c++·算法·leetcode·滑动窗口
汉字萌萌哒6 小时前
2024CSP-J入门级C++真题详解
开发语言·c++
arbboter6 小时前
【网络工具】NetProxy网络代理用户手册
开发语言·网络·c#·网络代理·网络异常·代理工具