C语言读取文件整数仅读取首行的问题排查与解决咨询
C语言tally函数读取文件提前终止循环的问题分析与解决
问题描述
我编写了一个C语言函数tally,用于从指定文件中读取整数值并统计指定整数出现的次数。待读取的.txt文件每行包含一个整数和一个浮点数,但目前函数仅读取首行的数值后就终止循环。
问题代码:
int tally(char fname[], int item) { int totalSales = 0; FILE *input; int intPlaceholder; FILE *write; input = fopen(fname, "r"); if (input != NULL) { for (int i = 0; fscanf(input, "%d", &intPlaceholder) == 1; i++) { if (intPlaceholder == item) { totalSales++; // Adds 1 to total sales after finding a matching item code in the file printf("Has found a match!"); } else { // Does nothing as it hasn't found a matching code } printf("\nLooped once."); } printf("\nStopped looping.\n"); } else { printf("This option is not valid.\n"); return 0; // Could not open the file } fclose(input); return totalSales; }
待读取的文件内容:
0 87.99 1 3.99 2 7.99 3 10.00 4 8.00
实际运行时,代码仅识别到0和87(本不应识别87,但这不是首要问题),仅循环两次,而我预期会循环10次。另有一个读取浮点数的同类函数运行正常,困惑为何仅整数读取出现此问题。
原因分析
fscanf("%d")的读取逻辑:%d格式符会连续读取输入流中的数字字符,直到遇到非数字字符才停止。首行读取0后,流中剩余内容为87.99\n,下一次fscanf("%d")会读取87(.是非数字字符,触发停止),此时流中剩下.99\n。- 循环终止的触发:第三次调用
fscanf("%d")时,流的当前位置是.,无法解析为整数,fscanf返回EOF,循环条件不满足,因此循环仅执行两次就终止。 - 预期偏差:你预期循环10次是误解了文件结构,实际每行是一个整数加一个浮点数,共5行,正确的循环次数应该是5次(每行处理一个目标整数)。
解决方法
核心思路是每次读取整数后,跳过该行剩余的浮点数内容,避免后续读取时遇到无效字符导致解析失败。以下是两种可行方案:
方案1:用fscanf抑制读取浮点数
在读取整数后,用%*f格式符读取并丢弃该行的浮点数(*表示抑制赋值,不存储到变量):
int tally(char fname[], int item) { int totalSales = 0; FILE *input; int intPlaceholder; input = fopen(fname, "r"); if (input != NULL) { // 每次读取整数后,自动读取并丢弃后续的浮点数 while (fscanf(input, "%d%*f", &intPlaceholder) == 1) { if (intPlaceholder == item) { totalSales++; printf("Has found a match!"); } printf("\nLooped once."); } printf("\nStopped looping.\n"); } else { printf("This option is not valid.\n"); return 0; } fclose(input); return totalSales; }
方案2:逐行读取后解析(容错性更强)
使用fgets读取整行内容,再用sscanf从行内解析整数,这种方法不受行内多余字符、换行符的影响,更适合处理结构化文本:
#include <string.h> // 需包含string.h头文件 int tally(char fname[], int item) { int totalSales = 0; FILE *input; int intPlaceholder; char line[100]; // 定义足够大的缓冲区存储每行内容 input = fopen(fname, "r"); if (input != NULL) { // 逐行读取文件,直到文件末尾 while (fgets(line, sizeof(line), input) != NULL) { // 从当前行中解析整数,忽略后续所有内容 if (sscanf(line, "%d", &intPlaceholder) == 1) { if (intPlaceholder == item) { totalSales++; printf("Has found a match!"); } printf("\nLooped once."); } } printf("\nStopped looping.\n"); } else { printf("This option is not valid.\n"); return 0; } fclose(input); return totalSales; }
内容的提问来源于stack exchange,提问作者koyo
相关产品推荐
相关产品推荐

