web-dev-qa-db-ja.com

C ++でistringstreamを使用して文字列を整数に分割する

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回出てくるのはなぜですか?それを修正する方法は?

17
Znorg

http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5while (iss)は、このシナリオのwhile (iss.eof())と同じです)。

具体的には、3回目のループ反復で、iss >> nが成功して3を取得し、ストリームを良好な状態のままにします。次に、この良好な状態のためにループが4回実行され、次の(4番目の)iss >> nが失敗して初めて、ループ条件が解除されます。ただし、その4回目の反復が終了する前に、4回目に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;
    } 
}

お役に立てれば:
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は変更されません//ストリームからの入力がないため、issのeofにフラグが設定されます
iss: ''

そして、上記の投稿で正しく言及されているように、while(iss)はwhile(iss.eof())と同じです。
内部的に、function(istream :: operator >>)は、最初に sentry オブジェクト(noskipwsをfalseに設定)を作成することによって入力シーケンスにアクセスします[これは、スペースがセパレーターであり、リストであることを意味します1,2,3])になります。次に( good [ここではeofに到達していません])、 num_get :: get [次の整数を取得]を呼び出して、抽出操作と解析操作の両方を実行し、それに応じて、ストリームの内部状態フラグが立てられます。最後に、それは戻る前に歩哨オブジェクトを破壊します。

参照: http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/

1
Sahil Sareen