2016-11-29 43 views
0

我在下面的程序中出現了分段錯誤。
爲什麼會發生這種情況,我該如何解決?從程序中創建一個向量的程序中的分段錯誤

#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; 
} 
+3

使用'std :: istringstream'拆分空間上的單詞。你不需要編寫這些類型的循環來完成這項工作。 – PaulMcKenzie

+1

確保你有一個調試版本,然後在你的調試器下運行該程序。發生分段錯誤時,它會向您顯示它發生的位置和程序狀態。或者,您可以檢查現有的核心文件。 PS,沒有什麼能阻止'j'跑完了...... – Useless

回答

0

我認爲,只要你使用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表格字符組合,但不可打印的字符組合(包括空格),並且達到您的目標。

2

我不知道原因

你必須與你的代碼的幾個問題。最明顯的一點是你沒有返回split_words函數中的矢量v。不返回來自定義爲返回值的函數的值是未定義的行爲

第二個問題是j在最後一個單詞上落下了句號,因爲您的循環僅在s[j]爲空時停止。字符串不會以空白字符結尾,因此您的循環會超出字符串的長度。在說了這個之後,如果你的目標是在空格字符上分割一個字符串,就沒有必要寫這樣的代碼來完成這項工作。只需使用std::istringstreamoperator >>

#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 >>,並在每次迭代呼籲push_back對遇到的每個分析的字符串。

0

當你忘記檢查\0或字符串的長度時,錯誤就在這裏。

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

啊忘了我曾見過Alexsandrescu談哨兵,所以你實際上可以解決的問題,如果你已經輸入後添加一個(空間)。 在split_words作爲第一行添加

s += ' '; 
0

需要這些變化。在下面的代碼中也提到了內聯。

// 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; 
}