2017-05-19 4 views
0

名前を連続して検索するために、このファイルの開閉をループしたいと考えています。ファイルから入力をループさせるより適切な方法は?

最初は問題ありません。出力が期待どおりで、yesを選択すると出力ループが発生します。

これはなぜ起こるのでしょうか?ロジックは正しい以上のようです。これはint end = 'n';を意味することになっているものをすべての

#include <iostream> 
#include <fstream> 
#include <string> 
using namespace std; 

int main() 
{ 
    string boys, girls, name; 
    int rank; 
    char end = 'n'; 
    while (end != 'y' || end != 'Y') 
    { 
     cout << "Enter a name to search"; 
     cin >> name; 
     ifstream input; 
     input.open("Names2016"); 
     if (input.fail()) 
      cout << "Failed to open file.\n"; 
     while (!input.eof()) 
     { 
      input >> rank >> boys >> girls; 
      if (boys == name) 
       cout << name << " ranks " << rank << " among boys.\n"; 
      if (girls == name) 
       cout << name << " ranks " << rank << " among girls.\n"; 
     } 
     input.close(); 
     cout << "Would you like to search another name?\n" 
      << "Enter Y for yes or N for no.\n"; 
     cin >> end; 
    } 
    return 0; 
} 
+1

http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong使用するためにその情報を保存します。 –

+0

あなたのNames2016ファイルを確認できますか? – Tyger

+0

私は非常に新しく、ファイルを表示する方法が不明です。ランク、スペース、そのランクに関連付けられた少年の名前、スペース、およびそのランクに関連付けられた少女の名前が新しい行に移動します。私はhttps://www.ssa.gov/cgi-bin/popularnames.cgiから情報を引き出しましたが、フォーマットを1000の名前に調整する必要があります。私は大変申し訳ありませんが、私はあなたに正確なファイルを与える方法がわかりません – NewToThis

答えて

0

あなたはこのコードを改善するために行うことができますいくつかのものがありますが、

最初は .eof()を使用していない、 ifstreamsを使用すると、入力/出力をループ内で適切な慣用的な方法を提出んです
  1. ループの状態でファイルの終わりをチェックする(コメントにリンクされている答えは、理由を知りたい場合には開始するのに適しています)、
  2. 2番目のことは、ファイルの妥当性をチェックするには単純なif (!file)そのきれいなIMOです。
  3. 3番目のことは、コードのようなローカルファイルハンドルがある場合、スコープから外してデストラクタにファイルをクリーンアップさせ、close()それをC++ RAIIのやり方物事(私は同じことを行いコンストラクタ呼び出し()
  4. 利用cerr代わりの文字
  5. ない大きな変化を表現するために
  6. 代わりintの使用charをエラーを報告するcoutopen()メソッドを削除したことの通知、他の回答のコメントに記載されているようなstd::toupperを使用して同時に、大文字と小文字の値について

#include <iostream> 
#include <fstream> 
#include <string> 
#include <cctype> 
using namespace std; 

int main() 
{ 
    string boys, girls, name; 
    int rank; 
    char end = 'n'; 
    while (std::toupper(end) == 'Y') 
    { 
     cout << "Enter a name to search"; 
     cin >> name; 
     ifstream input{"Names2016"}; 

     // change here 
     if (!input) { 
      cerr << "Failed to open file.\n"; 
     } 

     while (input >> rank >> boys >> girls) 
     { 
      if (boys == name) 
       cout << name << " ranks " << rank << " among boys.\n"; 
      if (girls == name) 
       cout << name << " ranks " << rank << " among girls.\n"; 
     } 
     // change below, just let the file handle go out of scope and close 
     // input.close(); 
     cout << "Would you like to search another name?\n" 
      << "Enter Y for yes or N for no.\n"; 
     cin >> end; 
    } 
    return 0; 
} 

をチェックすることをお読みやすい方法です。しかし、あなたのファイルを変更することが保証されていない場合は、I/Oに良く行うことができます別の反復で(おそらくレースが存在しないことを確認する必要があるかもしれないので、ファイルがあまり変わらないと仮定しています)。一度ファイルを読み込み、後で

#include <iostream> 
#include <fstream> 
#include <string> 
#include <cctype> 
#include <unordered_map> 
#include <vector> 
using namespace std; 

int main() 
{ 
    string boys_name, girls_name, name; 
    int rank; 
    char end = 'n'; 
    ifstream input{"Names2016"}; 
    if (!input) { 
     cerr << "Failed to open file" << endl; 
    } 

    // preprocess the information and store it in a map 
    // making a map from string to vector because it is unclear whether 
    // there is a 1-1 mapping from the name to the rank for each name 
    unordered_map<string, vector<int>> boys; 
    unordered_map<string, vector<int>> girls; 

    while (input >> rank >> boys_name >> girls_name) { 
     boys[boys_name].push_back(rank); 
     girls[girls_name].push_back(rank); 
    } 

    while (std::toupper(end) == 'Y') 
    { 
     cout << "Enter a name to search"; 
     cin >> name; 

     // use the map to do the lookup, much faster than reading 
     // the entire file over and over again    
    } 
    return 0; 
} 
+1

ありがとうあなたの複雑な心のために興味があります。最初のオプションは、今のところ私の現在のC++に対する理解を確実に提供します。しかし、(入力)ではなく(入力)を意味しましたか? – NewToThis

+0

@NewToThisはい、私は良いキャッチでした! – Curious

0

まず、あなたは文字の値を持つ整数を代入していますか。

なぜ、ループ内で同じファイルを開いているのですか?おそらくプログラムの初めに一度だけ開くべきです。

eofは、ファイルの終わりに達するためにファイルから読み込む必要があるため、チェックする必要はありません。

+1

それは '終わりにする必要があります!= 'y' && end!= 'Y'。さらに良いことに、 'toupper(end)!= 'Y''。 –

+0

私の終わりのcoutステートメントを読んでください。ユーザーが続行したいかどうかを尋ねます。したがって、whileループは(end = 'y' || end = "y")と言ってはいけません。 – NewToThis

+0

@NewToThisが修正されました。あなたは何かすべきことは '' char end = 'n'; '' –

関連する問題