C语言文件操作:如何提取每行数字并进行比较?
提取每行末尾的浮点数并完成统计计算
你不需要用strtok,用fgets配合sscanf就能满足需求——因为你的文件每行最后一个元素是浮点数,前面的名称即使包含空格也不影响。下面是完整的示例代码,包含读取文件、提取分数、计算最大值、最小值、平均值的逻辑:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> int main() { // 若要读取本地文件,将stdin替换为文件名,比如 "scores.txt" FILE *fp = stdin; if (!fp) { perror("Failed to open file"); return 1; } char line[1000]; float total = 0.0f; int valid_count = 0; float max_score = -INFINITY; float min_score = INFINITY; // 逐行读取直到文件末尾 while (fgets(line, sizeof(line), fp) != NULL) { // 移除换行符,避免干扰后续解析 size_t line_len = strlen(line); if (line_len > 0 && line[line_len - 1] == '\n') { line[line_len - 1] = '\0'; } float score; // 核心逻辑:跳过所有非浮点数起始字符,读取最后一个浮点数 // %*[^0123456789.-] 表示跳过所有不是数字、负号、小数点的内容 if (sscanf(line, "%*[^0123456789.-]%f", &score) == 1) { total += score; valid_count++; if (score > max_score) max_score = score; if (score < min_score) min_score = score; printf("提取到分数:%.2f\n", score); } else { printf("该行无有效分数:%s\n", line); } } fclose(fp); // 输出统计结果 if (valid_count > 0) { printf("\n=== 统计结果 ===\n"); printf("有效行数:%d\n", valid_count); printf("最高分:%.2f\n", max_score); printf("最低分:%.2f\n", min_score); printf("平均分:%.2f\n", total / valid_count); } else { printf("未找到任何有效分数\n"); } return 0; }
关键细节说明
- 文件读取逻辑:用
while (fgets(...) != NULL)替代你的do-while,这是判断文件读取完毕的标准写法,避免遗漏行或提前终止。 - 分数提取逻辑:
sscanf的扫描集%*[^0123456789.-]会跳过所有不构成浮点数开头的字符,直到遇到数字、负号或小数点,然后用%f读取浮点数。- 如果你的名称可能包含小数点/负号(比如名称是
test-1),上面的方法会出错,这时可以改用从字符串末尾向前查找的方式:// 从后往前定位第一个数字相关字符 int idx = strlen(line) - 1; while (idx >= 0 && !((line[idx] >= '0' && line[idx] <= '9') || line[idx] == '.' || line[idx] == '-')) { idx--; } if (idx >= 0) { char *endptr; float score = strtof(&line[idx], &endptr); // 验证转换是否成功 if (endptr != &line[idx]) { // 这里处理score的统计逻辑 } }
- 统计变量:直接在读取过程中计算总和、最大值、最小值,无需额外存储所有分数(如果文件很大,这种方式更节省内存)。
你的原始代码问题修正
lines++后面缺少分号;- 循环条件
line[0] != '\n'错误,无法正确判断文件结束; - 尽量避免使用全局变量,将变量放在
main函数内作为局部变量更规范。
内容的提问来源于stack exchange,提问作者Throwaway
相关产品推荐
相关产品推荐

