[英]Why does std::cin fail to read my input properly?
我正在使用以下代碼為我的 C++ 類做作業:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
string fileName;
string cheek,s;
long count;
ifstream input;
bool ask=1;
int main(){
while(ask){
cout<<"Enter a filename :\n";
cin>>fileName;
cout<<"reading file...";
input.open(fileName);
if(input){
ask=0;
}
}
istringstream iss;
cout<<"dumping contents...";
while(getline(input,cheek)){
//
}
iss.str(cheek);
cout<<"parsing...";
while(iss.peek()!=EOF){
s=iss.peek();
if(s=="A"||s=="E"||s=="I"||s=="O"||s=="U"||s=="a"||s=="e"||s=="i"||s=="o"||s=="u"){
count++;
}
}
cout<<"\nCOUNT="<<count<<"\nresetting...\n";
count=0;
iss.str("");
input.close();
fileName="";
cheek="";
s="";
}
出於某種原因, cin
無法識別我何時明確按下Enter鍵。 有解決方法嗎?
while(getline(input,cheek)){
只要while
循環條件的計算結果為邏輯true
這個while
循環就會繼續運行。 每次調用getline()
時,都會讀取文件中的下一行,並且getline()
返回true
。 到達文件末尾后, getline()
最終返回 false。
循環本身似乎沒有發生任何事情:
//
}
就是這樣。 這就是整個循環。 那么,用你自己的話,你能描述一下循環中發生了什么嗎? 您可以給出的唯一答案是:在存儲在cheek
變量中之后,整個文件已被讀取並且其內容一次一行地被丟棄。 由於std::getline
所做的第一件事就是擦除它作為參數獲取的字符串,因此在整個過程結束時,您將始終以空cheek
結束,並且整個文件已被完全讀取。
這個循環之后有一些代碼,似乎認為有什么東西在cheek
那是值得探討的,但是,由於上述原因概括,沒有任何那里。
這就是為什么顯示的代碼什么也沒完成。 看起來您希望將后續邏輯放置在while
循環內,而不是在它之后。 要做到這一點,你所要做的就是遵循計算機編程的黃金法則:“你的計算機總是完全按照你的要求去做,而不是你想讓它做什么”。 根據此規則,您所要做的就是將邏輯的適當部分移入 while 循環本身。
除了 Sam 的回答中解決的問題之外,您還有許多其他問題。 避免使用全局變量。 相反,聲明所需范圍內的所有變量。 例如,您可以在main()
包含所有值,在while (getline ...
) 循環中包含一些值,例如
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main(){
string fileName;
string cheek;
long count = 0, /* count must be initialized */
line = 0;
ifstream input;
正如評論中提到的,您的ask
變量是多余的。 這沒有錯,但是您可以通過不斷循環來簡單地完成相同的事情,然后在收到好的輸入時break
讀取循環,例如
while (true) {
cout << "Enter a filename : ";
cin >> fileName;
cout << "reading file...\n";
input.open(fileName);
if (input){
break;
}
}
您的文件讀取循環非常尷尬。 您的循環條件是正確的,但最好簡單地檢查每行中的字符。 您可以使用istringstream
,但不要使用peek()
,只需提取一個字符,然后根據您的元音列表檢查該字符,例如
cout << "dumping contents...\n";
while (getline(input, cheek)) {
char c;
istringstream iss (cheek);
cout << "parsing line " << (line++) << '\n';
while (iss >> c) {
if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' ||
c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
count++;
}
}
}
您實際上並沒有“轉儲”任何文件內容。 如果您確實想轉儲每一行輸入,請添加:
cout << input << '\n';
在cout << "parsing line ...
之前的文件讀取循環中。
請注意添加了一個line
計數器,您還可以報告檢查的行數以及找到的元音數。 行計數器可以作為一個簡單的調試工具來確認每一行的解析,然后在不再需要時將其刪除。 最終輸出可以是:
cout << "\nLINES = " << line << " COUNT = " << count << '\n';
}
沒有理由關閉文件或重置變量,因為您不會循環讀取另一個文件。
示例輸入文件
$ cat dat/fleas2line.txt
my dog has fleas
my cat has none
示例使用/輸出
$ ./bin/dumpfile
Enter a filename : dat/fleas2line.txt
reading file...
dumping contents...
parsing line 0
parsing line 1
LINES = 2 COUNT = 8
雖然在這個簡短的任務中沒有什么不同,但請確保您閱讀並理解為什么“使用命名空間標准;” 被認為是不好的做法?
如果您還有其他問題,請告訴我。 為您提供方便的完整來源是:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main(){
string fileName;
string cheek;
long count = 0, /* count must be initialized */
line = 0;
ifstream input;
while (true) {
cout << "Enter a filename : ";
cin >> fileName;
cout << "reading file...\n";
input.open(fileName);
if (input){
break;
}
}
cout << "dumping contents...\n";
while (getline(input, cheek)) {
char c;
istringstream iss (cheek);
cout << "parsing line " << (line++) << '\n';
while (iss >> c) {
if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' ||
c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
count++;
}
}
}
cout << "\nLINES = " << line << " COUNT = " << count << '\n';
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.