1

次のコード行では、入力テキスト ファイル (単語は改行で区切られています) 内のすべての単語を文字列のベクトルに配置し、各単語を裏返しにして、この変換された単語が入力ファイル内の単語のリスト。

私のバイナリ検索機能と wordTurn 機能は問題なく動作すると思います。コードでいくつかの簡単なテストを行ったところ、while(!myFile.eof()) ループを 2 回使用すると、コードが機能しない原因になる可能性があることがわかりました。機能しないということは、出力ファイル(「pairs.txt」)を空のドキュメントとして取得することを意味します(単語のペアのリストであるはずです)。

つまり、2 番目の while(!myFile.eof()) ループ本体に簡単な印刷コードを入れたところ、印刷されず、このループには達していないと結論付けました。最初の while(!myFile.eof()) ループをコメントアウトしたときに出力されたので、これは可能性が高いです。最初の while ループを最初の else 本体に配置しましたが、これは違いはありませんでした。

何が問題だと思いますか?これら 2 つのループ本体を 2 番目のループに結合しようとしたところ、出力ファイルに何かが生成されましたが、これはこのコードが行うべきことではなく、論理的に正しくありませんでした。

アドバイスをいただければ幸いです。

int main(int argc, char* argv[]) {

    vector<string> words;
    ifstream myFile(argv[1]);
    ofstream outputFile("pairs.txt");
    string vocab;
    string s;
    int count;

    while(!myFile.eof()) {                //first while(!myFile.eof()) loop
        getline(myFile, s);
        words.push_back(s);
    }

    if(argc != 2) {
        cout << "Usage: provide the name of one input file after the dictlookupHN executable file." << endl;
        return (1);
    }
    else {
        if(!myFile.is_open()) {
            cerr << "Error: unable to open file " << argv[1] << endl;
            return (1);
        }
        else {
            while(!myFile.eof()) {      //second while(!myFile.eof()) loop
                getline(myFile, vocab);
                string turnedWord = wordTurn(vocab);
                if(binsearch(words, turnedWord) != "") {
                    outputFile << vocab << ":" << turnedWord << endl;
                    count++;
                }
            }
        }

    }
    myFile.close();
    outputFile.close();

    return 0;
}
4

7 に答える 7

3

ifstream クラスは、ストリーム データへの内部オフセットを維持し、次の操作のためにどこから読み取る必要があるかを追跡します。

このオフセットが最後に到達すると、最初のループが停止します ( eof()false を返します)。再度読み取る前に、この内部位置をファイルの先頭にリセットする必要があります。

あなたは次のように言ってそれを行います:

myFile.clear(); // clear stream flags and error state
myFile.seekg(0, ios::beg); // reset read position

2 番目のループの前。

編集: への呼び出しを追加しましたclear()

于 2013-03-01T16:26:59.443 に答える
2

何が起こっているかというと、ファイルの最初の実行を完了すると、ファイルのシーク ポインターがファイルの最後にあるということです。ファイルを再度シークする場合は、2 番目のループmyFile.seekg(0, ios::beg);の前に使用してファイル ポインターをリセットする必要があります。whileこのようなもの:

        ...
        else {
                myFile.seekg(0, ios::beg);
                while(!myFile.eof()) {      //second while(!myFile.eof()) loop
        ...

これで問題は解決するはずです。

于 2013-03-01T16:29:46.430 に答える
2

[ファイル全体を最後まで読み取った後で] ファイルを再度読み取りたい場合は、不良/失敗ビットをリセットし、先頭までシークする必要があります。ファイルの終わりは、それをリセットするために何かが行われない限り、永続的な状態です。

だから、あなたが必要myFile.clear();とし、myFile.seekg(0, ios_base::beg);

この特定のケースでは、実際には別のファイルを開きたいと思いますが、その場合は、現在のファイルを閉じて、別の変数を使用することをお勧めします-それらはそれほど高価ではなく、コードがより明確になります [特に、たとえば]vocabFileの代わりに、それを賢明なものと呼ぶ場合myFile

于 2013-03-01T16:30:02.943 に答える
2

ファイルの先頭から再度読み取るには、次を使用します。

myFile.seekg(0, ios::beg);

ただし、これはファイルから読み取る良い方法ではないことに注意してください。

string vocab;
while(!myFile.eof()) {
    getline(myFile, vocab);
    ...
}

これは次のようになります。

string vocab;
while(getline(myFile, vocab)) {
    if (vocab.empty())
        continue;               // empty line might be read
    ...
}

以下をご覧ください:入力がファイルの終わりを超えて処理されているように見えるのはなぜですか?

于 2013-03-01T16:31:44.430 に答える
0

最初のループはEOFに達しました。これは「読み取りマーカー」の位置であるため、2番目のEOFは2番目のループの最初として読み取られます。

簡単に言えば、ループ間でファイルを閉じたり開いたりしてみてください。

より良いアイデアは、seekgを使用して先頭から再度読み取ることです。

于 2013-03-01T16:26:28.860 に答える
0

最初のループはファイルの終わりに達し、2 番目の読み取りの前にリセットしていません。最初のループの後にファイルの先頭をシークする必要がありmyFile.seekg (0, ios::beg);ます。これは自動的に行われます。

于 2013-03-01T16:28:20.593 に答える
0

皆様、良いアドバイスの言葉をありがとうございます。それらは、ifstream と eof がどのように機能するかを理解するのに本当に役立ちました。

私の TA のアドバイスは、2 番目の while(!myFile.eof()) ループの代わりに for ループを使用することでした。私はこのオプションを使用しているかもしれませんが、eof を 2 回使用する必要がある場合、あなたの回答は非常に役立ちます。

ありがとうございました!

                    while(!myFile.eof()) { 
                            string s;
                            getline(myFile, s);
                            words.push_back(s);
                    }

                    for(int i=0; i<words.size(); i++) {
                            //LOOP INV: 
                            string vocab = words.at(i);
                            string turnedWord = wordTurn(vocab);
                            if(binsearch(words, turnedWord) == 1 && turnedWord.length() > 3) {
                                    outputFile << vocab << ":" << turnedWord << endl;
                                    count++;
                            }
于 2013-03-01T21:59:19.493 に答える