簡體   English   中英

逐行讀取文件時出現問題

[英]Problem with reading file line-by-line

我正在嘗試完成一個練習,以編寫帶有以下命令行參數的程序:輸入文件,輸出文件和未指定數量的單詞。 該程序將逐行讀取輸入文件的內容,為給定的每個單詞查找包含單詞的行,並將行號與行號一起打印到輸出文件中。 這是我的代碼:

#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) ,它仍然給我同樣的錯誤輸出。

編輯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;
}

無論如何,感謝您的所有幫助! 練習本身並沒有說必須以任何方式格式化輸出,因此我認為輸出已完全完成。

i=3 ,在內部while(getline())循環中將文件讀取到EOF。 因此,在i=4,5,6…該文件不再可供讀取。

您可能需要倒帶輸入文件返回到開始的內循環結束后,或切換循環順序( while(getline(...)) { ... for (int i = 3; ...) { ... } ... }

您正在遍歷要查找的字符串,但是您具有在循環中讀取文件的getline()。 你真的想要:

for each input line
   getline
    for each string we are looking for
       is string in line?

您可以使用in.seekg (0, ios::beg); 快退到文件的開頭,然后再次讀取。

我的猜測是,每次通過for循環時,都需要將文件指針重置為輸入文件的開頭。 現在,您可以在循環外打開它一次,並且沒有任何技巧可以將其重置為后面的單詞開頭。

要倒帶流,首先需要調用in.clear()來取消設置流的狀態標志。 只有這樣做之后,您才能調用in.seekg(0, ios::beg)將獲取位置移回開頭。

正如@Neils答案所暗示的,您的算法有缺陷。 他的偽代碼對您來說是一個很好的起點。 我建議您嘗試一下,並嘗試將每個步驟編寫為更詳細的偽代碼。 重復執行此操作,直到您認為偽代碼可以輕松轉換為真實代碼為止。 我發現這種方法非常有用,對於以后可能遇到的更復雜的問題也是如此。 諷刺地說,在編寫代碼之前請三思。

提示您應該考慮將所需的單詞存儲在某些數據結構中,以便您可以反復遍歷它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM