C++ 11を使用して文字列を分割する最も簡単な方法は何ですか?C++を使用して文字列を分割する11
これは、postで使用されているメソッドを見てきましたが、新しい標準を使用してそれを行う方法はあまり冗長でなければなりません。
編集結果:vector<string>
を1文字に区切りたいと思います。
C++ 11を使用して文字列を分割する最も簡単な方法は何ですか?C++を使用して文字列を分割する11
これは、postで使用されているメソッドを見てきましたが、新しい標準を使用してそれを行う方法はあまり冗長でなければなりません。
編集結果:vector<string>
を1文字に区切りたいと思います。
これはあまり冗長ではありませんが、javascriptなどの動的言語で味付けした人にとってはgrokする方が簡単かもしれません。それが使用する唯一のC++ 11の機能はlambdaです。
#include <algorithm>
#include <string>
#include <cctype>
#include <iostream>
#include <vector>
int main()
{
using namespace std;
string s = "hello how are you won't you tell me your name";
vector<string> tokens;
string token;
for_each(s.begin(), s.end(), [&](char c) {
if (!isspace(c))
token += c;
else
{
if (token.length()) tokens.push_back(token);
token.clear();
}
});
if (token.length()) tokens.push_back(token);
return 0;
}
'for(auto const c:s){...}'はなぜですか? –
std::regex_token_iterator
は、正規表現に基づいて一般的なトークン化を実行します。これは、または単一の文字の上に簡単な分割を行うためには過剰であってもなくてもよいが、それは動作しますし、あまりにも冗長ではありません。
std::vector<std::string> split(const string& input, const string& regex) {
// passing -1 as the submatch index parameter performs splitting
std::regex re(regex);
std::sregex_token_iterator
first{input.begin(), input.end(), re, -1},
last;
return {first, last};
}
素晴らしいアイデアは、読みにくいです。 –
これはMSFTに固有のことです。 POSIXシステムには存在しません。 – jackyalcine
[boost。](http://www.boost.org/doc/libs/1_56_0/libs/regex/doc/html/boost_regex/ref/regex_token_iterator.html)でも利用可能です。 – phs
私の選択はboost::tokenizer
ですが、私は巨大なデータを持つ任意の重い作業とテストを持っていませんでした。ラムダ修正とブーストドキュメントから 例:ここでは
#include <iostream>
#include <boost/tokenizer.hpp>
#include <string>
#include <vector>
int main()
{
using namespace std;
using namespace boost;
string s = "This is, a test";
vector<string> v;
tokenizer<> tok(s);
for_each (tok.begin(), tok.end(), [&v](const string & s) { v.push_back(s); });
// result 4 items: 1)This 2)is 3)a 4)test
return 0;
}
なぜ範囲に基づいていないのですか? –
C++ 11では、for(auto && s:tok){v.push_back(s);} } '。 –
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
vector<string> split(const string& str, int delimiter(int) = ::isspace){
vector<string> result;
auto e=str.end();
auto i=str.begin();
while(i!=e){
i=find_if_not(i,e, delimiter);
if(i==e) break;
auto j=find_if(i,e, delimiter);
result.push_back(string(i,j));
i=j;
}
return result;
}
int main(){
string line;
getline(cin,line);
vector<string> result = split(line);
for(auto s: result){
cout<<s<<endl;
}
}
は(あなたが言及したpostに基づく)は、文字列を分割する(多分それほど冗長)の方法です。
#include <string>
#include <sstream>
#include <vector>
std::vector<std::string> split(const std::string &s, char delim) {
std::stringstream ss(s);
std::string item;
std::vector<std::string> elems;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
// elems.push_back(std::move(item)); // if C++11 (based on comment from @mchiasson)
}
return elems;
}
C++ 11を使用している場合は、ベクトルに挿入するときに文字列のコピーを避けるためにこれを行うこともできます。 elems.push_back(std :: move(item)); – mchiasson
これは私の答えです。冗長で読みやすく効率的です。
std::vector<std::string> tokenize(const std::string& s, char c) {
auto end = s.cend();
auto start = end;
std::vector<std::string> v;
for(auto it = s.cbegin(); it != end; ++it) {
if(*it != c) {
if(start == end)
start = it;
continue;
}
if(start != end) {
v.emplace_back(start, it);
start = end;
}
}
if(start != end)
v.emplace_back(start, end);
return v;
}
ここでは、文字列を分割し、抽出された要素をベクトルに埋め込む例をboost
としています。
#include <boost/algorithm/string.hpp>
std::string my_input("A,B,EE");
std::vector<std::string> results;
boost::algorithm::split(results, my_input, is_any_of(","));
assert(results[0] == "A");
assert(results[1] == "B");
assert(results[2] == "EE");
別の正規表現のソリューションinspired by other answersうまくいけば短く、簡単には読み:
ここstd::string s{"String to split here, and here, and here,..."};
std::regex regex{R"([\s,]+)"}; // split on space and comma
std::sregex_token_iterator it{s.begin(), s.end(), regex, -1};
std::vector<std::string> words{it, {}};
を見つける::だけのstd ::文字列を使用してC++ 11のソリューションです()。区切り文字は任意の長さの文字にすることができます。解析されたトークンは出力イテレータを介して出力されます。これは通常、自分のコードのstd :: back_inserterです。
私はこれをUTF-8でテストしていませんが、入力と区切り文字が両方とも有効なUTF-8文字列であれば動作するはずです。
#include <string>
template<class Iter>
Iter splitStrings(const std::string &s, const std::string &delim, Iter out)
{
if (delim.empty()) {
*out++ = s;
return out;
}
size_t a = 0, b = s.find(delim);
for (; b != std::string::npos;
a = b + delim.length(), b = s.find(delim, a))
{
*out++ = std::move(s.substr(a, b - a));
}
*out++ = std::move(s.substr(a, s.length() - a));
return out;
}
いくつかのテストケース:
void test()
{
std::vector<std::string> out;
size_t counter;
std::cout << "Empty input:" << std::endl;
out.clear();
splitStrings("", ",", std::back_inserter(out));
counter = 0;
for (auto i = out.begin(); i != out.end(); ++i, ++counter) {
std::cout << counter << ": " << *i << std::endl;
}
std::cout << "Non-empty input, empty delimiter:" << std::endl;
out.clear();
splitStrings("Hello, world!", "", std::back_inserter(out));
counter = 0;
for (auto i = out.begin(); i != out.end(); ++i, ++counter) {
std::cout << counter << ": " << *i << std::endl;
}
std::cout << "Non-empty input, non-empty delimiter"
", no delimiter in string:" << std::endl;
out.clear();
splitStrings("abxycdxyxydefxya", "xyz", std::back_inserter(out));
counter = 0;
for (auto i = out.begin(); i != out.end(); ++i, ++counter) {
std::cout << counter << ": " << *i << std::endl;
}
std::cout << "Non-empty input, non-empty delimiter"
", delimiter exists string:" << std::endl;
out.clear();
splitStrings("abxycdxy!!xydefxya", "xy", std::back_inserter(out));
counter = 0;
for (auto i = out.begin(); i != out.end(); ++i, ++counter) {
std::cout << counter << ": " << *i << std::endl;
}
std::cout << "Non-empty input, non-empty delimiter"
", delimiter exists string"
", input contains blank token:" << std::endl;
out.clear();
splitStrings("abxycdxyxydefxya", "xy", std::back_inserter(out));
counter = 0;
for (auto i = out.begin(); i != out.end(); ++i, ++counter) {
std::cout << counter << ": " << *i << std::endl;
}
std::cout << "Non-empty input, non-empty delimiter"
", delimiter exists string"
", nothing after last delimiter:" << std::endl;
out.clear();
splitStrings("abxycdxyxydefxy", "xy", std::back_inserter(out));
counter = 0;
for (auto i = out.begin(); i != out.end(); ++i, ++counter) {
std::cout << counter << ": " << *i << std::endl;
}
std::cout << "Non-empty input, non-empty delimiter"
", only delimiter exists string:" << std::endl;
out.clear();
splitStrings("xy", "xy", std::back_inserter(out));
counter = 0;
for (auto i = out.begin(); i != out.end(); ++i, ++counter) {
std::cout << counter << ": " << *i << std::endl;
}
}
予想される出力:スペース上の
Empty input: 0: Non-empty input, empty delimiter: 0: Hello, world! Non-empty input, non-empty delimiter, no delimiter in string: 0: abxycdxyxydefxya Non-empty input, non-empty delimiter, delimiter exists string: 0: ab 1: cd 2: !! 3: def 4: a Non-empty input, non-empty delimiter, delimiter exists string, input contains blank token: 0: ab 1: cd 2: 3: def 4: a Non-empty input, non-empty delimiter, delimiter exists string, nothing after last delimiter: 0: ab 1: cd 2: 3: def 4: Non-empty input, non-empty delimiter, only delimiter exists string: 0: 1:
分割?そして、私はC++ 11がここに何かを追加したとは思わないが、[受け入れられた答え](http://stackoverflow.com/a/237280/845092)は依然として最良の方法だと思う。 –
分割後に何をしたいですか?プリントアウトするには?または部分文字列のベクトルを取得しますか? – balki
これは正規表現解析の目的ではありませんか? –