2016-11-29 20 views
0

次のプログラムでセグメンテーションフォルトが発生しました。
なぜこのようなことが起こり、どうすれば解決できますか?検索は、すべての一致するように文字列からベクトルを作成するプログラムのセグメンテーションフォルト

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

私は思う
#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以降を使用していることを提供しました空白を含む印刷不可能なものを除き、単一の(拡張されていない)ASCIIテーブル文字の組み合わせ。

2

私はあなたがあなたのコードにはいくつかの問題を抱えている

理由を知りません。目立つものの1つは、split_wordsファンクションのベクトルvを返さなかったことです。値を返すように定義されている関数から値を返さないのは、未定義の動作です。

2番目の問題は、ループがs[j]が空白になるだけで終了するため、最後の単語の末尾にある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; 
} 
関連する問題