簡體   English   中英

為什么 std::cin 無法正確讀取我的輸入?

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

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