【问题标题】:Segmentation fault in program which creates a vector from a string从字符串创建向量的程序中的分段错误
【发布时间】:2016-11-29 17:42:38
【问题描述】:

我在以下程序中遇到了分段错误。
为什么会发生这种情况,我该如何解决?

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>

std::vector<std::string> split_words(std::string s) {
    std::vector<std::string> v(1, "");
    int i=0;
    int wortanzahl = 0;
    while(i<s.size()) {
        if (s[i]!=' ') {
            v.resize(wortanzahl + 1, "");
            for (int j=i; s[j]!=' '; ++j) {
                v[wortanzahl] += s[j];
                i=j;
            }
            ++wortanzahl;
        }
        ++i;
    }
}

int main() {
    std::string s = "Alpha beta! Gamma";
    split_words(s);
    return 0;
}

【问题讨论】:

  • 使用std::istringstream 分割空格上的单词。你不需要编写这些类型的循环来完成这项工作。
  • 确保你有一个调试版本,并在你的调试器下运行程序。当发生分段错误时,它会显示发生故障的行以及程序状态。或者,您可以检查现有的核心文件。 PS,没有什么能阻止j跑到最后......

标签: c++ arrays fault


【解决方案1】:

不知道原因

您的代码有几个问题。最明显的一点是您未能在split_words 函数中返回向量v。不从定义为返回值的函数返回值是未定义的行为

第二个问题是 j 在最后一个单词的末尾掉线,因为您的循环仅在 s[j] 为空白时停止。字符串不会以空白字符结尾,因此您的循环会不断超出字符串的长度。

话虽如此,如果您的目标是在空格字符上拆分字符串,则无需编写这样的代码来完成这项工作。相反,只需使用std::istringstreamoperator &gt;&gt;

#include <vector>
#include <sstream>
#include <string>
#include <iostream>

std::vector<std::string> split_words(std::string s) 
{
    std::vector<std::string> v;
    std::istringstream iss(s);
    std::string temp;
    while (iss >> temp)
       v.push_back(temp);
    return v;
}
 
int main() 
{
   std::string s = "Alpha beta! Gamma";
   auto vect = split_words(s);
   for (auto& word : vect)
      std::cout << word << "\n";
   return 0;
} 

Live Example

循环只是在流上调用operator &gt;&gt;,每次迭代都会为遇到的每个解析字符串调用push_back

【讨论】:

    【解决方案2】:

    我认为,如果您使用 C++11 或更高版本,您应该使用正则表达式,并执行以下操作:

    std::vector<std::string> split_words(std::string s) {
        std::vector<std::string> v;
        std::regex pattern("[!-~]+");
        std::cmatch result;
    
        while(regex_search(s.c_str(), result, pattern)) {
            for(auto it : result)
               v.push_back(it);
            s = result.suffix().str();
        }
    
        return v;
    }
    

    这样您的搜索就可以匹配除不可打印的字符组合(包括空格)之外的所有单个(非扩展)ASCII 表字符组合,从而实现您的目标。

    【讨论】:

      【解决方案3】:

      当您到达最后一个单词时忘记检查\0 或字符串的长度时,错误就在这里。

      for (int j=i; s[j]!=' ' && j < s.size(); ++j) {
        v[wortanzahl] += s[j];
        i=j;
      }
      

      啊忘了我看过 Alexsandrescu 谈论哨兵,所以如果你在输入后添加一个(空格),你实际上可以解决这个问题。 作为split_words 添加的第一行

      s += ' ';
      

      【讨论】:

        【解决方案4】:

        这些更改是必需的。在下面的代码中也提到了内联。

        // 0.可以尝试using namespace std;清理代码。

        // 1. 在下面的循环中检查字符串的结尾。

        // 2. 返回字符串向量。 (这修复了崩溃)。

        // 3. 使用向量输出分割后的字符串。

        #include <string>
        #include <vector>
        #include <iostream>
        #include <algorithm>
        
        // 0. can try using std to clean up code.
        std::vector<std::string> split_words(std::string s)
        {
            std::vector<std::string> v(1, "");
            int i=0;
            int wortanzahl = 0;
            while(i<s.size())
            {
                if (s[i]!=' ')
                {
                    v.resize(wortanzahl+1, "");
                    // 1. check for end of string in below loop
                    for (int j=i; s[j] && s[j]!=' '; ++j)
                    {
                        v[wortanzahl] += s[j];
                        i=j;
                    }
                    ++wortanzahl;
                }
                ++i;
            }
        
            // 2. return the vector of strings
            return v;
        }
        
        int main()
        {
            std::string s = "Alpha beta! Gamma";
            std::vector<std::string> v = split_words(s);
        
            // 3. output the split strings using vector
            for (int i = 0; i < v.size(); ++i)
                std::cout << v[i] << std::endl;
            return 0;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-06-02
          • 2017-02-02
          • 1970-01-01
          • 2021-03-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-07-25
          相关资源
          最近更新 更多