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.

Другие вопросы по тегам