C语言读取格式化文件至指定标记异常,求原因及解决方案
C语言文件读取循环失效问题排查与解决
我在C语言文件操作上卡壳了:代码里的while循环本该读到"ARCS POST"就停止,但死活识别不到,而且循环里的fseek定位完全没用。先贴我的代码和目标文件内容:
我的代码
int main(int argc, char *argv[]) { FILE* f = fopen("/Users/[...].txt","r+"); int input1=0; int input2=0; int input3=0; fscanf(f,"sommets : %d\n",&input1); printf("%d\n",input1); fscanf(f,"transitions : %d\n",&input1); printf("%d\n",input1); printf("%ld\n",ftell(f)); fscanf(f,"ARCS PRE\n"); printf("%ld\n",ftell(f)); long int point = ftell(f); char word[10]="ARCS POST"; char data[100]; while((strcmp(word, fgets(data,100,f)))!=0){ fseek(f,point-ftell(f), (int) ftell(f)); //to reposition the cursor after strcmp fscanf(f, "%d->%d,%d\n", &input1, &input2, &input3); printf("%d->%d,%d\n",input1, input2, input3); point =ftell(f); } fclose(f); return 0; }
目标文件内容
sommets : 69 transitions : 9 ARCS PRE 1->2,5 1->3,7 ARCS POST 1->7,1 1->9,4 END
问题根源
- 字符串比较不匹配:
fgets会把文件里的换行符\n也读进data缓冲区,而你定义的word是"ARCS POST"(不带换行),所以strcmp永远返回非0,循环根本停不下来。 - fseek用法完全错误:
fseek的第三个参数必须是SEEK_SET(文件开头)、SEEK_CUR(当前位置)或SEEK_END(文件末尾),你把ftell(f)的数值传进去是非法的,直接导致定位失效。 - 混合fscanf和fgets的缓冲区混乱:
fscanf读取后会把换行符留在输入缓冲区,后续fgets可能读到空行,进一步打乱文件指针位置。
替代解决方案(更稳健写法)
直接用fgets逐行读取,避免混合输入函数的问题,同时处理换行符确保字符串比较准确:
#include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { FILE* f = fopen("/Users/[...].txt","r"); // 只读模式足够,无需r+ if (!f) { // 必须检查文件是否打开成功 perror("文件打开失败"); return 1; } int input1=0, input2=0, input3=0; char line[100]; // 读取节点数 fscanf(f,"sommets : %d\n",&input1); printf("%d\n",input1); // 读取转换数 fscanf(f,"transitions : %d\n",&input1); printf("%d\n",input1); // 跳过"ARCS PRE"行 fgets(line, sizeof(line), f); // 循环读取直到遇到"ARCS POST" while (fgets(line, sizeof(line), f)) { // 去掉末尾的换行符(兼容不同系统的换行) line[strcspn(line, "\n\r")] = '\0'; // 检测停止标记 if (strcmp(line, "ARCS POST") == 0) { break; } // 解析弧的内容,检查解析是否成功 if (sscanf(line, "%d->%d,%d", &input1, &input2, &input3) == 3) { printf("%d->%d,%d\n", input1, input2, input3); } } fclose(f); return 0; }
方案优势
- 全程用
fgets逐行读取,彻底避免混合输入函数的缓冲区问题。 - 用
strcspn去掉换行符(同时处理\n和\r),确保字符串比较完全匹配。 - 增加文件打开失败的错误处理,避免空指针操作。
- 检查
sscanf返回值,防止无效行导致的变量乱码。
内容的提问来源于stack exchange,提问作者Romanion
相关产品推荐
相关产品推荐

