C++ разделенная строка
Я пытаюсь разбить строку, используя пробелы в качестве разделителя. Я хотел бы хранить каждый токен в массиве или векторе.
Я пытался.
string tempInput;
cin >> tempInput;
string input[5];
stringstream ss(tempInput); // Insert the string into a stream
int i=0;
while (ss >> tempInput){
input[i] = tempInput;
i++;
}
Проблема в том, что если я введу "это тест", то массив, похоже, будет хранить только input[0] = "this". Он не содержит значений для ввода [2] через input[4].
Я также пытался использовать вектор, но с тем же результатом.
4 ответа
Перейдите к дублирующимся вопросам, чтобы узнать, как разбить строку на слова, но ваш метод на самом деле правильный. Фактическая проблема заключается в том, как вы читаете входные данные, прежде чем пытаться разделить их:
string tempInput;
cin >> tempInput; // !!!
Когда вы используете cin >> tempInput
, вы получаете только первое слово из ввода, а не весь текст. Есть два возможных пути выхода из этого, самый простой из которых - забыть о stringstream
и непосредственно итерации на входе:
std::string tempInput;
std::vector< std::string > tokens;
while ( std::cin >> tempInput ) {
tokens.push_back( tempInput );
}
// alternatively, including algorithm and iterator headers:
std::vector< std::string > tokens;
std::copy( std::istream_iterator<std::string>( std::cin ),
std::istream_iterator<std::string>(),
std::back_inserter(tokens) );
Этот подход даст вам все токены на входе в одном векторе. Если вам нужно работать с каждой строкой отдельно, вам следует использовать getline
от <string>
заголовок вместо cin >> tempInput
:
std::string tempInput;
while ( getline( std::cin, tempInput ) ) { // read line
// tokenize the line, possibly with your own code or
// any answer in the 'duplicate' question
}
Обратите внимание, что гораздо проще использовать copy
:
vector<string> tokens;
copy(istream_iterator<string>(cin),
istream_iterator<string>(),
back_inserter(tokens));
Что касается того, почему ваш код не работает: вы используете повторно tempInput
, Не делай этого. Кроме того, вы сначала читаете одно слово из cin
не вся строка. Вот почему только одно слово помещается в stringstream
,
Самый простой способ: Boost.Tokenizer
std::vector<std::string> tokens;
std::string s = "This is, a test";
boost::tokenizer<> tok(s);
for(boost::tokenizer<>::iterator it=tok.begin(); it != tok.end(); ++it)
{
tokens.push_back(*it);
}
// tokens is ["This", "is", "a", "test"]
Вы можете задать параметры разделителей и экранирующих последовательностей, чтобы они занимали только пробелы, если хотите, по умолчанию они разделяются на пробелы и знаки препинания.
Here a little algorithm where it splits the string into a list just like python does.
std::list<std::string> split(std::string text, std::string split_word) {
std::list<std::string> list;
std::string word = "";
int is_word_over = 0;
for (int i = 0; i <= text.length(); i++) {
if (i <= text.length() - split_word.length()) {
if (text.substr(i, split_word.length()) == split_word) {
list.insert(list.end(), word);
word = "";
is_word_over = 1;
}
//now we want that it jumps the rest of the split character
else if (is_word_over >= 1) {
if (is_word_over != split_word.length()) {
is_word_over += 1;
continue;
}
else {
word += text[i];
is_word_over = 0;
}
}
else {
word += text[i];
}
}
else {
word += text[i];
}
}
list.insert(list.end(), word);
return list;
}
There probably exists a more optimal way to write this.