20

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

4

2 に答える 2

34

http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5で(間接的に)説明されているように、ループが間違っているため、2回出てきます(このシナリオwhile (iss)とは異なります) while (iss.eof()).

具体的には、3 回目のループ反復で、iss >> nが成功して を取得3し、ストリームを良好な状態のままにします。その後、この良好な状態のためにループが 4 回実行され、次 (4 回目)iss >> nが失敗するまで、ループ条件が壊れることはありません。しかし、その 4 回目の反復が終了する前に、まだn4 回目の ... を出力します。

試す:

#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;
    } 
}
于 2011-03-02T14:19:25.843 に答える
1

iss
: 1 2 3
Iteration 1
iss : 1 2 3 (最初)
n=1
iss : 2 3
//* 1 が表示される
Iteration 2:
iss : 2 3 (最初)
n=2
iss : 3
// * 2 が出力される
Iteration 3
iss : 3
n=3
iss : ''
Iteration 4
iss : ''
n not changed //ストリームからの入力がこれ以上ないため、 issのeof
にフラグを設定 iss : ''

上記の投稿で正しく述べたように、while (iss) は while (iss.eof()) と似ていません。
内部的には、関数 (istream::operator>>) は、まず(noskipws を false に設定して)セントリーオブジェクトを構築することによって入力シーケンスにアクセスします [これは、スペースが区切り文字であり、リストが 1,2,3 になることを意味します]。次に ( [ここでは eof に達していない] が適切な場合)、 num_get::get [次の整数を取得] を呼び出して、抽出操作と解析操作の両方を実行し、それに応じてストリームの内部状態フラグを調整します。最後に、戻る前に歩哨オブジェクトを破棄します。

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

于 2013-11-04T11:11:54.280 に答える