C++ 字符串解析器问题

Posted

技术标签:

【中文标题】C++ 字符串解析器问题【英文标题】:C++ string parser issues 【发布时间】:2017-10-04 21:10:55 【问题描述】:

好的,所以我正在使用 C++ 编写一个家庭作业项目,但遇到了一个问题,似乎找不到解决方法。该函数应该在用户定义的分隔符处断开输入字符串,并将子字符串存储在一个向量中以供以后访问。我想我已经弄清楚了基本的解析器,但它不想拆分输入的最后一部分。

int main() 
    string input =  "comma-delim-delim&delim-delim";
    vector<string> result;
    vector<char> delims;
    delims.push_back('-');
    delims.push_back('&');
    int begin = 0;

    for (int i = begin; i < input.length(); i++ )
       for(int j = 0; j < delims.size(); j++)
          if(input.at(i) == delims.at(j))
           //Compares chars in delim vector to current char in string, and 
           //creates a substring from the beginning to the current position 
           //minus 1, to account for the current char being a delimiter.
              string subString = input.substr(begin, (i - begin));
              result.push_back(subString);
              begin = i + 1;
           

上面的代码可以很好地分割输入代码直到最后一个破折号。之后的任何事情,因为它没有遇到另一个分隔符,所以它不会保存为子字符串并推入结果向量。因此,为了纠正这个问题,我整理了以下内容:

else if(input.at(i) == input.at(input.length()))
   string subString = input.substr(begin, (input.length() - begin));
   result.push_back(subString);

但是,我在上述部分中不断出现超出范围的错误。拆分子字符串的边界似乎存在问题,我不知道如何解决它。有什么帮助吗?

【问题讨论】:

我建议存储最后一次拆分发生的索引,并且在循环结束时,如果该值不是字符串的结尾,则将最后一次拆分后的所有内容推送到您的结果中。您现在拥有的内容有些可疑,因为它会考虑与要匹配的最后一个字符相同的字符(除了越界问题)。 您是否尝试过添加守车?即在您的字符串中附加一个分隔符。 所以你想使用两个分隔符-&amp; @DOUGLASO.MOEN 是绝对正确的。在你的循环之前添加类似input.push_back(delims.at(0)); 的东西,一切都应该完美运行(见here)。相反,您也可以在循环之后使用 begin 的最后一个值再次获取子字符串(但您必须小心检查您是否已经在字符串的末尾)。 【参考方案1】:

在您的代码中,您必须记住 .size() 将比您的最后一个索引多 1,因为它从 0 开始。因此,大小为 1 的数组在 [0] 处被索引。所以如果你这样做 input.at(input.length()) 总是会溢出 1 个位置。 input.at(input.length()-1) 是最后一个元素。这是一个对我有用的例子。在你的循环之后,只需抓住字符串的最后一段。

if(begin != input.length())
    string subString = input.substr(begin,(input.length()-begin));
    result.push_back(subString);

【讨论】:

像魅力一样工作!感谢您的帮助。【参考方案2】:

从问题中的代码开始,我已经替换了迭代器,以便我们可以检查输入的 end()

int main() 
    string input = "comma-delim-delim&delim-delim";
    vector<string> result;
    vector<char> delims;
    delims.push_back('-');
    delims.push_back('&');
    auto begin = input.begin(); // use iterator

    for(auto ii = input.begin(); ii <= input.end(); ii++)
        for(auto j : delims) 
            if(ii == input.end() || *ii == j)
                string subString(begin,ii); // can construct string from iterators, of if ii is at end
                result.push_back(subString);
                if(ii != input.end())
                    begin = ii + 1;
                else
                    goto done;
            
        
    
done:
    return 0;

【讨论】:

您为什么决定使用goto 而不是简单的break @scohe001 break 只会跳出内部for 循环,而外部循环实际上会进入end(),这意味着不允许ii++ 啊,我的错,我看到 goto 并获得了隧道视野。标志不是better C++ practice吗? @scohe001 这可能无法通过代码审查,但goto 树的果实是如此甜蜜...【参考方案3】:

这个程序使用std::find_first_of来解析多个分隔符:

int main() 
    string input = "comma-delim-delim&delim-delim";
    vector<string> result;
    vector<char> delims;
    delims.push_back('-');
    delims.push_back('&');
    auto begin = input.begin(); // use iterator

    for(;;) 
        auto next = find_first_of(begin, input.end(), delims.begin(), delims.end());
        string subString(begin, next); // can construct string from iterators
        result.push_back(subString);
        if(next == input.end())
            break;
        begin = next + 1;
    

【讨论】:

以上是关于C++ 字符串解析器问题的主要内容,如果未能解决你的问题,请参考以下文章

并行解析 C++

在 C++ 中在左侧拆分字符串

解析器与词法分析器和 XML

c ++中的布尔表达式(语法)解析器

C++ 使用存储在字符串中的函数名称获取函数指针或评估函数

字符串函数不返回字符串? c++ [关闭]