0

私は 2 つのコードを持っていmain()ます。

vector<int> v;

cout << "Enter sequance of integers "<< "(press q to quit) : ";
istream_iterator<int> start_cin(cin);
istream_iterator<int> end_of_cin;
copy(start_cin,end_of_cin,back_inserter(v));

for ( vector<int>::iterator It = v.begin();It != v.end(); It++ )
    cout << *It << "\t";
cout << endl;

vector<string> vS;
cout << "Enter three strings : ";
for ( int i = 0; i < 3; i++ )
    vS.push_back(*istream_iterator<string>(cin));

ostream_iterator<string> sIt(cout,", ");
copy(vS.begin(),vS.end(),sIt);
cout << endl;

これら2つの部分が一緒に使用される場合、つまり

#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <string>
using namespace std;

int main ()
{
    // first part

    vector<int> v;

    cout << "Enter sequance of integers "<< "(press q to quit) : ";
    istream_iterator<int> start_cin(cin);
    istream_iterator<int> end_of_cin;
    copy(start_cin,end_of_cin,back_inserter(v));

    for ( vector<int>::iterator It = v.begin();It != v.end(); It++ )
        cout << *It << " \t";
    cout << endl;


    vector<string> vS;
    cout << "Enter three strings : ";
    for ( int i = 0; i < 3; i++ )
        vS.push_back(*istream_iterator<string>(cin));

    ostream_iterator<string> sIt(cout,", ");
    copy(vS.begin(),vS.end(),sIt);

    cout << endl;

    return 0;
}

ここで最初の部分は機能しましたが、2番目の部分は出力を提供します: Enter Three Strings : , , ,. この動作の背後にある理由は何ですか?

ありがとう。

4

2 に答える 2

3

copy()が完了した後、「整数」の読み取りに失敗したためcin、読み取り不能な状態 ( ) になります。これは、後続のループが何も読み取れないことを意味します。!cin.good()qfor

追加:

cin.clear();
cin.ignore(); // To skip the unread "q"

forループ前。

編集:

James Kanzeがコメントしたように、次"q"の終了の原因が次のcopy()とおりであることを確認してください。

...

cin.clear();
string int_read_terminator;
cin >> int_read_terminator;
if ("q" != int_read_terminator)
{
    cerr << "Integer copy() failure: " << int_read_terminator << "\n";
}
else
{
    ...
于 2012-04-16T09:33:34.843 に答える
0

で問題の 1 つが発生しましたinput_iterator。ファイル全体が 1 つのタイプである必要があります。これを回避するにはいくつかの方法があります。最も一般的な方法は、実際のソースとストリームの間にフィルタリング streambuf を挿入することです。したがって、たとえば、ストリームの最初の部分は、次の'q'ような ,だけで 1 行を入力すると終了する必要があります。

class UntilQStreambuf : public std::streambuf
{
    std::streambuf*     mySource;
    char                myBuffer;
    bool                myIsAtStartOfLine;

protected:
    int underflow()
    {
        int                 results = mySource->sbumpc();
        if ( results == 'q' 
                && myIsAtStartOfLine
                && mySource->sgetc() == '\n' ) {
            mySource->sbumpc();     //  remove terminator line.
            results = traits_type::eof();
        }
        if ( results != traits_type::eof() ) {
            myBuffer = results;
            setg( &myBuffer, &myBuffer, &myBuffer + 1 );
        }
        return results;
    }

public:
    UntilQStreambuf( std::istream& source )
        :  mySource( source->rdbuf() )
        ,  myIsAtStartOfLine( true )
    {
    }
};

boost::iostream(これを書くのがかなり簡単になるいくつかのサポートがあると思います。)次に、 streambuffrom std::cin(またはどこでも)を使用して、数値を読み取るための別のストリームを設定します。

std::vector<int>
getNumbers( std::istream& source )
{
    UntilQStreambuf     localSB( source );
    std::istream        src( &localSB );
    std::vector<int>    results( (std::istream_iterator<int>( src )),
                                 (std::istream_iterator<int>()) );
    if ( !src.eof() ) {
        //  Some other error occurred...
    }
    return results;
}

別のストリームを使用すると、元のストリームで終了条件が設定されず、後で続行できます (おそらく同じ手法をさらに使用します)。

于 2012-04-16T10:15:42.983 に答える