[英]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.