【问题标题】:Reading from text file or stdin从文本文件或标准输入读取
【发布时间】:2014-05-27 20:00:00
【问题描述】:

我有一个程序,它基本上读取一个文本文件并计算每行中每个单词的出现次数。使用 ifstream 从文本文件读取时一切正常,但是,如果未在命令行中输入文件名,我需要改为从标准输入读取。

我目前使用以下打开和读取文件:

map<string, map<int,int>,compare> tokens;
ifstream text;
string line;
int count = 1;

if (argc > 1){
    try{
        text.open(argv[1]);
    }
    catch (runtime_error& x){
        cerr << x.what() << '\n';
    }

    // Read file one line at a time, replacing non-desired char's with spaces
    while (getline(text, line)){
        replace_if(line.begin(), line.end(), my_predicate, ' ');

        istringstream iss(line);    
        // Parse line on white space, storing values into tokens map
        while (iss >> line){                
            ++tokens[line][count];
        }
        ++count;
    }
}

else{
while (cin) {
    getline(cin, line);
    replace_if(line.begin(), line.end(), my_predicate, ' ');

    istringstream iss(line);
    // Parse line on white space, storing values into tokens map
    while (iss >> line){
        ++tokens[line][count];
    }
    ++count;
}

有没有办法将 cin 分配给 ifstream 并在 argc > 1 失败时简单地添加一个 else 语句,然后使用相同的代码而不是像这样复制?我还没有找到方法来做到这一点。

【问题讨论】:

标签: c++ input stdin ifstream


【解决方案1】:

我只是放了一个简单的方法让程序读取文件,如果给定其他使用标准输入,并正确关闭它。

#include <fstream>
#include <iostream>
#include <memory>
#include <string>

int main(int argc, char* argv[]) {
    auto fp_deletor = [](std::istream* is_ptr) {
        if (is_ptr && is_ptr != &std::cin) {
            static_cast<std::ifstream*>(is_ptr)->close();
            delete is_ptr;
            std::cerr << "destroy fp.\n"; 
        }
    };

    std::unique_ptr<std::istream, decltype(fp_deletor)> is_ptr{nullptr, fp_deletor};
    if (argc > 2) {
        std::cerr << "usage: " << argv[0] << "[input-file]";
        return -1;
    } else if (argc == 1) {
        std::cerr << "using stdin as input.\n";
        is_ptr.reset(&std::cin); 
    } else {
        is_ptr.reset(new std::ifstream(argv[1]));
    }

    std::string line;
    while (std::getline(*is_ptr, line)) {
        // your logic....
    }

    // just return, unique_ptr manage the istream
    return 0;
}

【讨论】:

    【解决方案2】:

    让阅读部分成为它自己的功能。将ifstreamcin 传递给它。

    void readData(std::istream& in)
    {
       // Do the necessary work to read the data.
    }
    
    int main(int argc, char** argv)
    {
       if ( argc > 1 )
       {
          // The input file has been passed in the command line.
          // Read the data from it.
          std::ifstream ifile(argv[1]);
          if ( ifile )
          {
             readData(ifile);
          }
          else
          {
             // Deal with error condition
          }
       }
       else
       {
          // No input file has been passed in the command line.
          // Read the data from stdin (std::cin).
          readData(std::cin);
       }
    
       // Do the needful to process the data.
    }
    

    【讨论】:

      【解决方案3】:

      您不能将 cin 分配给 ifstream。
      但是您可以将 cin 重新打开到某个文件。

      无论如何,更好的方法是将您的代码模块化并仅使用std::istream&amp;

      【讨论】:

        最近更新 更多