Разбиение строки на целые числа с использованием istringstream в C ++ - PullRequest
15 голосов
/ 02 марта 2011

Я пытаюсь использовать istringstream, чтобы разбить простую строку на серию целых чисел:

#include <string>
#include <iostream>
#include <sstream>
#include <vector>

using namespace std;

int main(){

    string s = "1 2 3"; 
    istringstream iss(s);   

    while (iss)
    {
        int n;
        iss >> n;
        cout << "* " << n << endl;
    } 
}

И я получаю:

* 1
* 2
* 3
* 3

Почему последний элемент всегда появляется дважды? Как это исправить?

Ответы [ 2 ]

31 голосов
/ 02 марта 2011

Это происходит дважды, потому что ваш цикл неправильный, как объяснено (косвенно) на http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5 (while (iss) не отличается от while (iss.eof()) в этом сценарии).

В частности, натретья итерация цикла iss >> n завершается успешно, получает 3 и оставляет поток в хорошем состоянии.Затем цикл выполняется в четвертый раз из-за этого хорошего состояния, и только после следующего (четвертого) iss >> n последующего сбоя условие цикла нарушается.Но до окончания этой четвертой итерации вы все равно выводите n ... в четвертый раз.

Попробуйте:

#include <string>
#include <iostream>
#include <sstream>
#include <vector>

using namespace std;

int main()
{
    string s = "1 2 3"; 
    istringstream iss(s);   
    int n;

    while (iss >> n) {
        cout << "* " << n << endl;
    } 
}
0 голосов
/ 04 ноября 2013

Надеюсь, это поможет:
iss: 1 2 3
Итерация 1
iss: 1 2 3 (Изначально)
n = 1
iss: 2 3
// * 1 напечатано
Итерация 2:
iss: 2 3 (Изначально)
n = 2
iss: 3
// * 2печатается
Итерация 3
iss: 3
n = 3
iss: ''
Итерация 4
iss: ''
n не изменено // Флаг установлен для eof of iss, поскольку нет дальнейшего ввода из потока
iss: ''

И, как справедливо отмечено в приведенном выше постеwhile (iss) не отличается от while (iss.eof ()).
Внутренне функция (istream :: operator >>) обращается к входной последовательности, сначала создав объект sentry (сnoskipws установлен в false [Это означает, что пробел является разделителем, и ваш список будет 1,2,3]).Затем (если хорошо [здесь eof не достигнут]), он вызывает num_get :: get [Получить следующее целое число] для выполнения операций извлечения и синтаксического анализа, регулируя внутреннюю часть потокагосударственные флаги соответственно.Наконец, он уничтожает часовой объект перед возвратом.

См .: http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/

...