使用stringstream解析含空格引号字符串时出现无限循环问题
问题原因分析
你的核心问题出在没有区分引号内的空格和普通空格。当前代码用空格作为全局分隔符,但引号包裹的字符串内部的空格属于字符串内容,不能当成分割token的标志。
当输入x = "Foo and" .add. "Bar"时,你的getline(ss, stringToken, ' ')会先读取到x,然后是=,接下来读取到"Foo(因为第一个空格在Foo后面)。如果你的代码里有尝试拼接引号内容的逻辑,但处理不当的话,会错误地把后面的and" .add. "Bar全部当成引号内的内容,拼成"Foo and .add. Bar"。之后stringstream的读取位置会卡在异常状态,导致getline反复读取空内容,直接触发无限循环。
简单说,你的分割逻辑完全没考虑带空格的字符串字面量这种特殊情况,默认把所有空格都当成分隔符,既破坏了引号内字符串的完整性,又让流读取状态异常,最终导致死循环。
修复方案
你需要修改分割逻辑,增加对引号的状态跟踪,区分“引号内”和“引号外”的空格处理:
void splitLine(string aLine) { vector<string> tokens; string currentToken; bool inQuotes = false; for (char c : aLine) { if (c == '"') { // 切换引号状态,同时保留引号字符 inQuotes = !inQuotes; currentToken += c; // 如果是结束引号,直接把当前完整字符串token存入列表 if (!inQuotes) { tokens.push_back(currentToken); currentToken.clear(); } } else if (isspace(c) && !inQuotes) { // 只有不在引号内的空格才作为分隔符 if (!currentToken.empty()) { tokens.push_back(currentToken); currentToken.clear(); } } else { // 其他字符(包括引号内的空格)都加入当前token currentToken += c; } } // 处理最后一个未被分割的token if (!currentToken.empty()) { tokens.push_back(currentToken); } // 测试输出(可根据需求替换为你的业务逻辑) for (const string& token : tokens) { cout << "|" << token << "| "; } cout << endl; }
这个逻辑会正确处理两种输入场景:
- 输入
x = "Foo" .add. "Bar"时,得到|x| |=| |"Foo"| |.add.| |"Bar"| - 输入
x = "Foo and" .add. "Bar"时,得到|x| |=| |"Foo and"| |.add.| |"Bar"|
额外注意点
- 如果你的语法支持转义引号(比如
"Foo \"Bar\" Baz"),还需要添加转义字符的处理逻辑,避免把转义的引号误判为字符串结束标志 - 建议补充未闭合引号的异常处理,比如输入
x = "Foo时,避免程序进入未知状态
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

