C++按空白分词时如何保留双引号包裹的含空格字符串
解决方案
原有分词逻辑直接按指定分隔符硬切割,未实现双引号字符串的识别规则,是导致带空格字符串被拆分错误的核心原因。采用逐字符遍历的简单状态机实现即可解决问题,逻辑可控且方便后续扩展语法规则。
核心逻辑只需要维护两个状态:
- 普通分词状态:遇到空格、制表符就截断当前缓存内容作为独立token;遇到双引号时,先把已缓存的普通token存入结果,切换到字符串读取状态
- 字符串读取状态:所有字符(包括空格、制表符)都直接存入当前缓存,直到遇到闭合的双引号,再把整个带引号的字符串作为完整token存入结果,切回普通分词状态
实现代码
#include <vector> #include <string> std::vector<std::string> tokenize(std::string str, char delim = ' ') { std::vector<std::string> out; std::string current_buf; bool in_quoted_string = false; for (char c : str) { if (in_quoted_string) { current_buf += c; // 碰到闭合双引号,结束字符串读取 if (c == '"') { in_quoted_string = false; out.push_back(current_buf); current_buf.clear(); } } else { if (c == '"') { // 碰到字符串起始标记,先把之前缓存的普通token存下 if (!current_buf.empty()) { out.push_back(current_buf); current_buf.clear(); } in_quoted_string = true; current_buf += c; } else if (c == delim || c == '\t') { // 碰到分隔符/制表符,截断普通token if (!current_buf.empty()) { out.push_back(current_buf); current_buf.clear(); } } else { current_buf += c; } } } // 处理遍历结束后剩余的缓存内容 if (!current_buf.empty()) { out.push_back(current_buf); } return out; }
效果说明
- 输入
print "hello are you there?"时,分词结果为["print", "\"hello are you there?\""],带空格的字符串会被识别为单个独立token,不会触发关键字识别错误 - 非引号包裹的普通标识符、关键字仍然按空白字符正常拆分,和原有逻辑的预期行为一致
- 后续如果需要支持转义字符(比如字符串内部通过
\"表示双引号本身),只需要在字符串状态下增加一个转义标记位即可判断,扩展成本极低
内容的提问来源于stack exchange,提问作者st3ph4nnnn
相关产品推荐
相关产品推荐

