1

特定の行にあるテキスト ファイルからデータを取得しようとしています (1 番目、7 番目、13 番目など - 必要なデータは次の 6 行目に配置されます)。

これまでの私のコードは次のとおりです。

txtfile = "titles.txt";
ifstream txt(txtfile);
const int buffer_size = 80;
char title_buffer[buffer_size];
const int titleLineDiff = 6;
if (txt.is_open())
{
    while(!txt.eof())
    {
        static int counter = 1;
        txt.getline(title_buffer, buffer_size);
        cout << "Title: \"" << counter << "." << title_buffer << "\"" << endl;
        counter++;
        //seek to the next title...difference is 6 lines
        for(int i = 0; i < titleLineDiff; i++)
            txt.getline(title_buffer, 40);
    }
}

今、私が作成したこのファイルでうまく動作します:

testONE
two
three
four 
five
six

testTWO
bla

そして、「testONE」と「testTWO」を出力しますが、データを含むファイルを開こうとすると、無限ループが発生し、出力は

タイトル: "counter_increasing_number."

テキスト ドキュメントはインターネットからコピーされたものであり、これが読み取りの問題の原因である可能性があります。

これについて何ができますか?


コードを次のように変更しました。

while(getline(txt,title_buffer))
{
    static int counter = 1;
    //getline(title_buffer, buffer_size);
    cout << "Title: \"" << counter << "." << title_buffer << "\"" << endl;
    counter++;
    //seek to the next title...difference is 6 lines
    for(int i = 0; i < titleLineDiff; i++)
    {
        getline(txt, title_buffer);
    }
}

そしてそれはうまくいきました。

誰かが最初にうまくいかなかった理由を説明してもらえますか?

4

3 に答える 3

2

手始めに、getline成功したかどうかを確認せずにの結果を使用しています。(2番目のバージョンでは、これは内側のループにのみ当てはまります。)

最初のバージョンが間違っている理由について:eof最後に正常に読み取られた後に設定されるのか、最初に失敗した後に設定されるのかは、実際には指定されていません。そしてもちろん、ファイルの終わり以外に、入力が失敗する可能性がある他の理由があります。熟考されたイディオムは、ループまたはifの制御式として常にgetline(およびその他の入力)を使用することです。式が考慮されるtrue場合、入力は成功しています。入力が失敗したことがわかった後で確認すると便利な場合があります。eof()が真でない場合eof()、問題は別の場所にあります。ハードウェアエラー(bad()真)またはフォーマットのエラーのいずれかです。

テストデータと実際のデータの動作が異なる理由については、両方を見ずに言うのは難しいです。いくつかの考えられる理由:異なる行終了規則、おそらく1セットのデータが不完全な行で終了する(データがWindowsエディターで生成された場合)、またはバッファーより長い行(最初の場合)。

于 2013-02-26T23:51:15.620 に答える
2

ここに行きます(コメントを読むことを忘れないでください):

例:

void Example( void )
{
    // DECLARATION
    // *Declare iFile as std::ifstream and attempt to open file: Example.txt
    std::ifstream iFile( "Example.txt" );

    // *If iFile is open, do this:
    if( iFile.is_open( ) )
    {
        // DECLARATION
        // *You could declare strLine as an array of char if you want
        std::string strLine = "";
        unsigned int nLineCount = 0;

        // DO WHATEVER
        // *Read iFile line by line using std::getline
        while( std::getline( iFile, strLine ) )
        {
            // *For the line after every 6th line, we shall print
            // as a title
            // *( nLineCount % 6 ) gives us the remainder of
            // nLineCount / 6 and if the remainder is 0, then
            // do this:
            if( !( nLineCount % 6 ) )
            {
                std::cout << "Title = " << strLine << std::endl;
            }
            // *For every other line, we shall print it normally
            else
            {
                std::cout << strLine << std::endl;
            }

            // *Increase nLineCount by 1;
            nLineCount ++;
        }
        // CLEAN-UP
        // *Done using inFile - so close it
        inFile.close( );
    }
};

テスト済み:

Title = 1
2
3
4
5
6
Title = 7
8
9
10
11
12
Title = 13
...

Debugging > Paused! Enter any key to continue...

詳細... コメントなし:

void Example( void ) {
    std::ifstream iFile( "Example.txt" );

    if( iFile.is_open( ) ) {
        std::string strLine = "";
        unsigned int nLineCount = 0;

        while( std::getline( iFile, strLine ) ) {
            if( !( nLineCount % 6 ) )
                std::cout << "Title = " << strLine << std::endl;
            else
                std::cout << strLine << std::endl;
            nLineCount ++;
        }
        iFile.close( );
    }
};

Forループ方式、短くてクリーン:

void Example( void )
{
    std::ifstream iFile( "Example.txt" );

    if( iFile.is_open( ) )
    {
        std::string strLine = "";

        for( unsigned int nLineCount = 0; std::getline( iFile, strLine ); nLineCount ++ ) {
            if( !( nLineCount % 6 ) )
                std::cout << "Title = " << strLine << std::endl;
            else
                std::cout << strLine << std::endl;
        }
        iFile.close( );
    }
};
于 2013-02-27T03:24:48.003 に答える
1

2番目のファイルには、7行が予想されるため、行数が等しくなく、最後のチャンクはそれよりも少なくなっています。これにより、チェックする前に eof を超えてしまいました。内部 for ループに eof 条件を入れる必要があります。

編集: 各行が 80 文字以内であることを確認してください。

于 2013-02-26T23:31:36.047 に答える