文字列をトークン化する C++ で何かを書きたいと思います。私が何を望んでいるかを説明するには、次の文字列を使用します。
add string "this is a string with spaces!"
これは次のように分割する必要があります。
add
string
this is a string with spaces!
標準ライブラリベースの迅速なアプローチはありますか?
ライブラリは必要ありません。繰り返しでタスクを実行できます(説明したほど単純な場合)。
string str = "add string \"this is a string with space!\"";
for( size_t i=0; i<str.length(); i++){
char c = str[i];
if( c == ' ' ){
cout << endl;
}else if(c == '\"' ){
i++;
while( str[i] != '\"' ){ cout << str[i]; i++; }
}else{
cout << c;
}
}
それが出力する
add
string
this is a string with space!
ここに完全な関数があります。必要に応じて変更してください。文字列の一部をベクトルstrings( qargs
)に追加します。
void split_in_args(std::vector<std::string>& qargs, std::string command){
int len = command.length();
bool qot = false, sqot = false;
int arglen;
for(int i = 0; i < len; i++) {
int start = i;
if(command[i] == '\"') {
qot = true;
}
else if(command[i] == '\'') sqot = true;
if(qot) {
i++;
start++;
while(i<len && command[i] != '\"')
i++;
if(i<len)
qot = false;
arglen = i-start;
i++;
}
else if(sqot) {
i++;
start++;
while(i<len && command[i] != '\'')
i++;
if(i<len)
sqot = false;
arglen = i-start;
i++;
}
else{
while(i<len && command[i]!=' ')
i++;
arglen = i-start;
}
qargs.push_back(command.substr(start, arglen));
}
for(int i=0;i<qargs.size();i++){
std::cout<<qargs[i]<<std::endl;
}
std::cout<<qargs.size();
if(qot || sqot) std::cout<<"One of the quotes is open\n";
}
Boost ライブラリにはtokenizer
、escaped_list_separator
. これらの組み合わせは、探しているものを提供するように見えます。
これは、この投稿の時点で最新のブースト ドキュメントへのリンクであり、これを読んだ時点ではほぼ確実に古いバージョンです。
https://www.boost.org/doc/libs/1_73_0/libs/tokenizer/doc/tokenizer.htm
https://www.boost.org/doc/libs/1_73_0/libs/tokenizer/doc/escaped_list_separator.htm
この例は、boost のドキュメントから抜粋したものです。私自身の例を作成していないことを許してください。
// simple_example_2.cpp
#include<iostream>
#include<boost/tokenizer.hpp>
#include<string>
int main(){
using namespace std;
using namespace boost;
string s = "Field 1,\"putting quotes around fields, allows commas\",Field 3";
tokenizer<escaped_list_separator<char> > tok(s);
for(tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end();++beg){
cout << *beg << "\n";
}
}
標準ライブラリには簡単なアプローチはないと思います。間接的に次のアルゴリズムが機能します。
a) で '\"' をstring::find('\"')
検索します。何か見つかった場合は を使用して次の '\"' を検索しstring::find('\'',prevIndex)
、見つかった場合は を使用しますstring::substr()
。元の文字列からその部分を破棄します。
b)' '
同じ方法で文字を検索します。
注: 文字列全体を反復処理する必要があります。