You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何两次调用fgets()可正常运行,单次调用却不行?

为什么两次调用fgets()正常,单次却不行?

嘿,我来帮你捋清楚这个问题~ 先从你的代码和场景入手分析:

核心原因:数据文件格式和fgets调用次数不匹配

从你两次调用fgets的代码逻辑来看,大概率你的数据文件file__dat的格式是每一条设备信息(Name+MAC)对应两行内容——比如第一行是有效数据(Name,MAC格式),第二行是空行/换行符;或者第一行存Name,第二行存MAC。

两次fgets的逻辑刚好适配了这个格式:

  1. 第一次fgets读取有效行,用strtok分割出Name和MAC,存入结构体;
  2. 第二次fgets读取那行不需要的内容(空行/第二字段行),相当于跳过它,让下一次循环的fgets能读到下一组有效数据。

而单次调用fgets时,循环会把所有行都当成有效数据处理:

  • 如果遇到空行,strtok分割不到任何内容,返回NULL,这时用strcpy把NULL拷贝到结构体里,会触发未定义行为(程序崩溃、乱码等);
  • 如果是一行存Name一行存MAC的格式,单次调用会把Name当成第一组的Name,下一行的MAC当成第二组的Name,直接导致数据完全错位。

验证方法:打印每次fgets的内容

你可以在代码里加打印,看看两次fgets分别读到了什么,就能一目了然:

for (i = 0; i < num; i++) {
    fgets(buff, 22, dat);
    printf("第一次fgets读到: |%s|\n", buff); // 用|包裹方便看空行/换行
    printf("%s\n", buff);
    file = strtok(buff, ",");
    strcpy(aparell[i].Name, file);
    file = strtok(NULL, ",");
    strcpy(aparell[i].MAC, file);
    
    fgets(buff, 22, dat);
    printf("第二次fgets读到: |%s|\n", buff);
}

如果第二次打印的是空行(||或者|\n|),那就是我说的情况了。

优化建议(给新手的小提醒)

  1. 必须检查文件打开是否成功:你现在直接fopen后就用,万一文件不存在/权限不够,dat会是NULL,后续调用fgets直接崩:
    dat = fopen(file__dat, "r");
    if (dat == NULL) {
        perror("打开文件失败"); // 打印具体错误原因
        return 1; // 或者做其他错误处理
    }
    
  2. 加strtok的空指针判断:防止读到无效行时程序崩溃:
    file = strtok(buff, ",");
    if (file == NULL) {
        printf("第%d行数据格式错误,跳过\n", i+1);
        continue;
    }
    strcpy(aparell[i].Name, file);
    
    file = strtok(NULL, ",");
    if (file == NULL) {
        printf("第%d行缺少MAC字段,跳过\n", i+1);
        continue;
    }
    strcpy(aparell[i].MAC, file);
    
  3. 用strncpy代替strcpy更安全:避免缓冲区溢出(比如Name字段太长超过结构体数组的长度):
    // 假设aparell[i].Name的长度是20,就这么写:
    strncpy(aparell[i].Name, file, sizeof(aparell[i].Name)-1);
    aparell[i].Name[sizeof(aparell[i].Name)-1] = '\0'; // 手动加字符串结束符
    

内容的提问来源于stack exchange,提问作者Agapito Gallart Bernat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:22:58