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

咨询:std::ifstream读取std::string为何导致C++程序死循环

C++读取文件时死循环重复输出的原因解析

尽管担心显得笨拙,我仍想咨询为何以下C++程序运行时会进入死循环:

程序代码

#include <iostream>
#include <fstream>

int main(int argc, char * argv[]) {

  std::ifstream fitData("./fitData.txt");

  int line=1;
  while (true) {
    std::string compType;
    bool isRS;
    int dRecMode;
    double mass;
    fitData >> compType >> isRS >> dRecMode >> mass;
    if ( fitData.eof() ) break;
    std::cout << "at line: " << line << ":" << compType << " " << isRS << " " << dRecMode << " " << mass << std::endl;

    line++;

    if ( line > 20 ) break;
  }

  std::cout << line << std::endl;
}

待读取的fitData.txt文件内容

TT: 1 7 2.26455
TT: 1 7 2.45204
TT: 1 1 2.05438
TT: 1 -5 2.36097
TT: 1 -5 2.34911
TT: 1 7 2.43344
TT: 1 3 2.5
TT: 1 1 2.34866
TT: 1 2 2.24831
TT: 1 -3 2.31099
LC: 0 99 2.27828
LC: 1 99 2.29757
LC: 2 99 2.27512
LC: 3 99 2.31149
LC: 4 99 2.31205
LC: 5 99 2.31091

程序输出

at line: 1:TT: 1 7 2.26455
at line: 2:TT: 1 7 2.45204
at line: 3:TT: 1 1 2.05438
at line: 4:TT: 1 -5 2.36097
at line: 5:TT: 1 -5 2.34911
at line: 6:TT: 1 7 2.43344
at line: 7:TT: 1 3 2.5
at line: 8:TT: 1 1 2.34866
at line: 9:TT: 1 2 2.24831
at line: 10:TT: 1 -3 2.31099
at line: 11:LC: 0 99 2.27828
at line: 12:LC: 1 99 2.29757
at line: 13:LC: 1 99 2.29757
at line: 14: 1 99 2.29757
at line: 15: 1 99 2.29757
at line: 16: 1 99 2.29757
at line: 17: 1 99 2.29757
at line: 18: 1 99 2.29757
at line: 19: 1 99 2.29757
at line: 20: 1 99 2.29757
21

该问题在WSL2(Win10 64位)、Cygwin(Win7 32位)、Xubuntu(64位)等所有测试系统中均会出现,从第13次循环开始std::string变量compType为空,后续重复输出相同内容。


技术解析

核心原因

  1. 输入格式不匹配触发流错误状态
    当程序读取第13行的LC: 2 99 2.27512时,尝试将2读取到bool isRS变量。C++标准中,bool类型的输入仅接受true/false或0/1,2属于非法输入值,这会导致fitData流触发failbit(失败位),进入不可用状态。此时流的所有后续输入操作都会直接失败,但eof()仅在文件指针到达末尾时返回true,因此if (fitData.eof()) break;永远不会触发,循环持续执行。

  2. 输入失败后变量保留旧值
    流进入失败状态后,fitData >> compType >> isRS >> dRecMode >> mass;不会修改任何变量的值。因此后续循环中,isRS、dRecMode、mass始终保留上一次成功读取的内容(第12行的1、99、2.29757),而compType因读取失败被置为空,最终导致重复输出相同内容。

  3. 循环终止条件存在缺陷
    代码中的if (line > 20) break;只是临时限制了循环次数,并未解决根本问题;若文件行数超过20,死循环会持续到触发该条件。

解决方法

  • 正确检查输入状态
    将输入操作与循环条件合并,利用>>运算符返回流对象的特性,直接判断输入是否成功:

    int line = 1;
    std::string compType;
    int isRS_int; // 改用int存储原bool字段的值
    int dRecMode;
    double mass;
    while (fitData >> compType >> isRS_int >> dRecMode >> mass) {
        bool isRS = isRS_int != 0; // 手动转换为bool
        std::cout << "at line: " << line << ":" << compType << " " << isRS << " " << dRecMode << " " << mass << std::endl;
        line++;
    }
    

    这种方式会在输入失败(包括EOF或格式错误)时直接终止循环,无需单独检查eof()。

  • 修复bool类型输入问题
    由于文件中isRS字段存在非0/1的值,不能直接用bool类型读取。建议改用int类型接收该字段,再根据业务需求手动转换为bool(比如非0值视为true)。

  • 可选:重置流状态(如需继续操作流)
    如果需要在输入失败后继续使用流,可以调用fitData.clear()重置错误状态,并调用fitData.ignore()跳过错误的输入内容,但在该场景下直接终止循环更为合理。


内容的提问来源于stack exchange,提问作者troppapolvere

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 10:55:17