2011-12-30 34 views
4

やや私のコードは以下のようになります。スペースで区切られた文字列をC++で複数の文字列に分割する方法は?

static int myfunc(const string& stringInput) 
{ 
    string word; 
    stringstream ss; 

    ss << stringInput; 
    while(ss >> word) 
    { 
     ++counters[word]; 
    } 
    ... 
} 

ここでの目的は、変数word文字列に(空白で区切って '「)入力文字列を取得することですが、ここでのコードは、オーバーヘッドの多くを持っているようです - 入力文字列を文字列ストリームに変換し、文字列ストリームから目的の文字列に読み込みます。

同じ目的を達成するためのよりエレガントな方法がありますか?

+0

の可能な複製を( http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c) – user7116

+3

私はこの質問がすでに数回尋ねられていると思います:http://stackoverflow.com/questions/1894886/parsing-a-comma-delimited-stdstring http://stackoverflow.com/questions/4328685/input-line-by-line-from-an-input-file-and-tokenize-using-strtok-and-the-アウトプt http://stackoverflow.com/questions/536148/c-string-parsing-python-style http://stackoverflow.com/questions/1511029/c-tokenize-a-string-and-include-delimiters http:///stackoverflow.com/questions/3162108/a-better-way-to-split-a-string-into-an-array-of-strings-in-cc-using-whitespac –

+0

ブーストはあなたの友人です – marcinj

答えて

5

あなたは、文字列を分割する方法を求めています。ブーストは役に立つユーティリティブースト::スプリット()

http://www.boost.org/doc/libs/1_48_0/doc/html/string_algo/usage.html#id3115768

を持ってここでベクターに結果の単語を置く例を示します

#include <boost/algorithm/string.hpp> 
std::vector<std::string> strs; 
boost::split(strs, "string to split", boost::is_any_of("\t ")); 
+0

ありがとうございますが、可能であればストリームの使用を破棄するつもりです。 –

+1

ありがとう、アレックス。ええ、これは私が欲しいものです。しかし、私のg ++​​コンパイラにブーストライブラリが付属しているかどうか、ブーストの存在をチェックする方法はわかりません。 Btw、ソースコードのコンパイルに使用する追加の-lコマンド?使用可能なブーストがない場合、STLに同様のユーティリティ機能がありますか? –

+0

忍者のために申し訳ありませんが編集します。私は最初にあなたの質問に間違いました。 –

0

使用ostringstream、多分

istringstream(stringInput); // initialize with the string 
+0

ええ、これは少し節約します。しかし、基本的なアイデアはまだ同じです:ストリングストリームを構築し、このストリームから読み込みます。ストリームストリームはまったく使用できませんか?そして、まだスペースで区切られた文字列を 'word'に読み込みますか? –

1

利用ストリームイテレータと標準機能:

その後、
static int myfunc(std::string const& stringInput) 
{ 
    std::stringstream ss(stringInput); 

    std::for_each(std::istream_iterator<std::string>(ss), 
        std::istream_iterator<std::string>(), 
        [&counters](std::string const& word) { ++counters[word];} 
       ) 
    ... 
} 

あなたが持っていない場合はラムダ:

struct Helper 
{ 
    void operator()(std::string const& word) const {++counters[word];} 
    Helper(CounterType& c) : counters(c) {} 
    CounterType& counters; 
}; 

static int myfunc(std::string const& stringInput) 
{ 
    std::stringstream ss(stringInput); 

    std::for_each(std::istream_iterator<std::string>(ss), 
        std::istream_iterator<std::string>(), 
        Helper(counters) 
       ) 
    ... 
} 
+0

ありがとう、ロキ。あなたのコードは素晴らしく見えます。それでも、私はストリームを巻き込まない方法を好む。 :-) –

0

Visual C++ 11では、TR1のregex_token_iteratorを使用できます。

sregex_token_iterator::regex_type white_space_separators("[[:space:]]+",regex_constants::optimize); 

for(sregex_token_iterator i(s.begin(),s.()end,white_space_separators,-1),end; i!=end; i++) 
{ 
cout << *i << endl; 
// or use i.start, i.end which is faster access 
} 

パフォーマンス(と文字列のコピーのようなオーバーヘッド)を懸念し、あなたがあなた自身のルーチン書くことができた場合:[?C++で文字列を分割する方法]

#include <ctype.h> 

#include <string> 
#include <iostream> 
using namespace std; 

int main() 
{ 
string s = "Text for tokenization "; 

const char *start = s.c_str(); 
const char *end = start + s.size(); 
const char *token = start; 

while (start!=end) 
{ 
    if(isspace(*start)) 
    { 
    if (token < start) 
    { 
     // Instead of constructing string, you can 
     // just use [token,start] part of the input buffer 
     cout << string(token,start) << ' '; 
    } 

    start++; 
    token = start; 
    } 
    else 
    { 
    start++; 
    } 
} 

if (token < start) 
{ 
    cout << string(token,start) << ' '; 
} 

} 
+0

ありがとう、ペトロ。分割ルーチンはAndrew Koenigの "Accelerated C++"によく似ています。両方とも素晴らしい機能です。 –

3
Code in c++ 
#include<sstream> 
#include<vector> 
using namespace std;  
string diskNames="vbbc anmnsa mansdmns"; 
string temp; 
vector <string> cds; 
stringstream s (diskNames); 
while(s>> temp) 
cds.push_back(temp); 
関連する問題