1

次のコマンド ライン引数を取るプログラムを作成する演習を完了しようとしています: 入力ファイル、出力ファイル、および指定されていない単語数。このプログラムは、入力ファイルの内容を 1 行ずつ読み取り、その単語が含まれる行を指定して各単語を検索し、その行を行番号と共に出力ファイルに出力します。これが私のコードです:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;

int main(int argc, char* argv[]) {
    if (argc < 4) {
        cerr << "Error #1: not enough arguments provided\n";
        return 1;
    }
    ifstream in(argv[1]);
    if (!in.is_open()) {
        cerr << "Error #2: input file could not be opened\n";
        return 2;
    }
    ofstream out(argv[2]);
    if (!out.is_open()) {
        cerr << "Error #3: output file could not be opened\n";
        return 3;
    }
    ostringstream oss;
    for (int i = 3; i < argc; ++i) {
        int k = 0;
        string temp;
        oss << argv[i] << ":\n\n";
        while (getline(in, temp)) {
            ++k;
            unsigned x = temp.find(argv[i]);
            if (x != string::npos)
                oss << "Line #" << k << ": " << temp << endl;
        }
    }
    string copy = oss.str();
    out << copy;
    in.close();
    out.close();
    return 0;
}

それを実行しようとすると、指定された最初の単語の予測出力が得られますが、その後の単語は見つかりません。たとえば、上記のソース コードの場合、次の出力が得られます。

in:

Line #1: #include <iostream>
Line #2: #include <fstream>
Line #3: #include <string>
Line #4: #include <sstream>
Line #5: using namespace std;
Line #7: int main(int argc, char* argv[]) {
Line #12:     ifstream in(argv[1]);
Line #13:     if (!in.is_open()) {
Line #14:         cerr << "Error #2: input file could not be opened\n";
Line #22:     ostringstream oss;
Line #23:     string temp;
Line #24:     for (int i = 3; i < argc; ++i) {
Line #26:         int k = 0;
Line #28:         while (getline(in, temp)) {
Line #30:             unsigned x = temp.find(argv[i]);
Line #31:             if (x != string::npos)
Line #32:                 oss << "Line #" << k << ": " << temp << endl;
Line #35:     string copy = oss.str();
Line #37:     in.close();
out:

つまり、指定された最初の単語のすべてのインスタンスが検索されますが、後続の単語は検索されません。ここで何が間違っていますか?

編集:ファイルの先頭に戻る方法を見つけようとしていましたが、「rewind()」などと呼ばれるメソッドが見つからなかったため、あきらめました。while ループの後に追加しましin.seekg(0, ios::beg)たが、それでも同じ間違った出力が得られます。

EDIT 2:さて、私は最終的にあきらめて、ペアのベクトルを使用するためのある種のワイルドな試みなしでは、元の目的の出力を取得できないことに気付いたので、あきらめて、この形式で印刷することにしました:

found in at line #31:         cerr << "Error #2: input file could not be opened\n";
found out at line #34:     ofstream out(argv[2]);

つまり、すべての行を順番に出力し、見つかった特定の単語を各行の先頭に付けます。while ループは次のとおりです。

ostringstream oss;
string temp;
while(getline(in,temp)) {
    static int count = 1;
    for (int i = 3; i < argc; ++i) {
        unsigned foundWord = temp.find(argv[i]);
        if (foundWord != string::npos)
            oss << "found " << argv[i] << " at line #" << count << ": " << temp << endl;
    }
    ++count;
}

とにかく、すべての助けをありがとう!演習自体は、出力を何らかの方法でフォーマットする必要があるとは言っていないので、完全に完了したと考えています。

4

6 に答える 6

5
于 2010-04-26T16:29:48.860 に答える
3

探している文字列をループしていますが、ループ内のファイルを読み取るgetline()があります。あなたは本当に欲しい:

for each input line
   getline
    for each string we are looking for
       is string in line?
于 2010-04-26T16:32:00.413 に答える
1

この関数in.seekg (0, ios::beg);を使用して、ファイルを再度読み取る前にファイルの先頭に巻き戻すことができます。

于 2010-04-26T16:34:55.593 に答える
0

ストリームを巻き戻すには、最初に呼び出しin.clear()てストリームの状態フラグの設定を解除する必要があります。in.seekg(0, ios::beg)これを行った後でのみ、get位置を最初に戻すために呼び出すことができます。

于 2010-04-26T17:05:56.257 に答える
0

@Neilsの回答が示唆しているように、アルゴリズムに欠陥があります。彼の擬似コードはあなたにとって良い出発点です。それを実行して、各ステップをもう少し詳細な擬似コードとして記述してみることをお勧めします。擬似コードが実際のコードに簡単に変換できると感じるまで、これを繰り返し行います。このアプローチは、後で遭遇する可能性のあるより複雑な問題に対しても非常に役立つと思います。皮肉なことに、コーディングする前に考えてください。

ヒント探している単語をデータ構造に格納して、それらを繰り返し繰り返すことができるようにすることを検討する必要があります。

于 2010-04-26T17:07:22.163 に答える
0

My guess is that you need to reset your file pointer to the beginning of the input file each time through your for loop. Right now, you open it once outside the loop and have no mechanic to reset it back to the beginning for following words.

于 2010-04-26T16:30:29.597 に答える