从文件循环输入更合适的方法?

时间:2017-05-19 03:29:30

标签: c++ loops file-io

我希望能够循环打开和关闭此文件,以便不断搜索名称。

第一次没有问题,输出是预期的,当选择y表示是,输出循环发生。

关于为什么会发生这种情况的任何想法?逻辑似乎不正确。

#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;
}

2 个答案:

答案 0 :(得分:0)

首先,这应该是什么意思int end = 'n';你是在指定一个带字符值的整数吗?!

为什么要在循环中打开相同的文件?您应该在程序开始时只打开一次。

并且eof没有要检查的内容,因为您必须从文件中读取才能到达目的地。

答案 1 :(得分:0)

您可以采取一些措施来改善此代码,

  1. 第一个是使用ifstreams并在循环中输入/输出正确的惯用方式,不要使用.eof()检查循环条件下的文件结尾(如果你想知道原因,那么在评论中链接的答案是一个很好的起点,
  2. 你要用简单if (!file)更清洁的IMO检查文件有效性的第二件事。
  3. 第三件事是,当你有一个像代码那样的本地文件句柄时,你可以让它超出范围并让析构函数清理文件并close()它,它&#39 ;是C ++ RAII的做事方式(请注意我已将open()方法移除到构造函数调用(它执行相同的操作)
  4. 使用cerr代替cout报告错误
  5. 使用char代替int代表字符
  6. 没有太大的变化,但在其他答案的注释中使用std::toupper之类的建议是同时检查大写和小写值的可读方式
  7. #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;
    }