3

この小さなカスタム getline 関数は、さまざまな行末の処理に関する質問への 回答として提供されました。

この関数は、2 日前に各行の先頭の空白をスキップしないように編集されるまではうまく機能していました。ただし、編集後、プログラムは無限ループに入ります。コードに加えられた唯一の変更は、これから変更された次の行です。

std::istream::sentry se(is);  // When this line is enabled, the program executes
                              // correctly (no infinite loop) but it does skip
                              // leading white spaces

これに:

std::istream::sentry se(is, true); // With this line enabled, the program goes 
                                   // into infinite loop inside the while loop  
                                   // of the main function.

空白をスキップしないように指定すると、プログラムが無限にループする理由を説明してもらえますか?

ここに完全なプログラムがあります...

std::istream& safeGetline(std::istream& is, std::string& t)
{
    t.clear();

    // The characters in the stream are read one-by-one using a std::streambuf.
    // That is faster than reading them one-by-one using the std::istream.
    // Code that uses streambuf this way must be guarded by a sentry object.
    // The sentry object performs various tasks,
    // such as thread synchronization and updating the stream state.

    std::istream::sentry se(is, true);
    std::streambuf* sb = is.rdbuf();

    for(;;) {
        int c = sb->sbumpc();
        switch (c) {
        case '\r':
            c = sb->sgetc();
            if(c == '\n')
                sb->sbumpc();
            return is;
        case '\n':
        case EOF:
            return is;
        default:
            t += (char)c;
        }
    }
}

そして、ここにテストプログラムがあります:

int main()
{
    std::string path = "end_of_line_test.txt"

    std::ifstream ifs(path.c_str());
    if(!ifs) {
        std::cout << "Failed to open the file." << std::endl;
        return EXIT_FAILURE;
    }

    int n = 0;
    std::string t;
    while(safeGetline(ifs, t))   //<---- INFINITE LOOP happens here. <----
        std::cout << "\nLine " << ++n << ":" << t << std::endl;

    std::cout << "\nThe file contains " << n << " lines." << std::endl;
    return EXIT_SUCCESS;
}

また、関数の最初にこの行を追加しようとしましたが、違いはありませんでした...メイン関数の while ループで、プログラムは依然として無限ループを繰り返していました。

is.setf(0, std::ios::skipws);

ファイルend_of_line_test.txtは、次の 2 行のみを含むテキスト ファイルです。

   "1234" // A line with leading white spaces
"5678"    // A line without leading white spaces
4

1 に答える 1

6

問題は、ストリームsafeGetLineの状態を設定しないことです。eof()

を使用するstd::istream::sentry se(is);、空白を読み取ろうとし、ファイルの終わりにいることを検出します。空白を探さないように頼むと、これは決して起こりません。

is.setstate(ios_base::eofbit)関数のEOF条件に追加する必要があると思います。

于 2012-02-08T07:57:15.623 に答える