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()”或类似的方法后,我有点放弃了。我in.seekg(0, ios::beg)在while循环之后添加,它仍然给我同样的错误输出。

编辑 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

You are looping through the strings you are looking for, but you have the getline() that reads the file in the loop. You really want:

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

You can use the function in.seekg (0, ios::beg); to rewind to the beginning of the file before reading it again.

于 2010-04-26T16:34:55.593 回答
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 回答
0

To rewind the stream you first need to call in.clear() to unset the state flags of the stream. Only after doing this can you call in.seekg(0, ios::beg) to move the get position back to the beginning.

于 2010-04-26T17:05:56.257 回答
0

As @Neils answer suggests, your algorithm is flawed. His pseudo-code is a good starting-point for you. I suggest you take it and try to write each step as pseudo-code a bit more detailed. Do that repeatedly, until you feel that the pseudo-code easily translates into real code. I find this approach very useful, also for the more complex problems you may encounter later. Sarcastically speaking, think before you code.

Hint You should consider storing the words you are looking for in some data-structure, so that you can repeatedly iterate through them.

于 2010-04-26T17:07:22.163 回答