【问题标题】:C++ common interface for "cin" and "File"“cin”和“File”的C++通用接口
【发布时间】:2010-09-24 23:41:16
【问题描述】:

cin和文件输入有通用接口吗?

我想做一个有可选参数的程序

prog [input-file]

如果指定了输入文件,则应从该文件中读取,否则应从 cin 中读取。

据我所知,它们都实现了istream。您将如何设置它以便我可以执行类似in >> var 的操作,其中inistream

【问题讨论】:

    标签: c++ io cin istream


    【解决方案1】:
    #include <iostream>
    #include <fstream>
    
    int main(int argc, char **argv)
    {
        std::ifstream f;
        if (argc >= 2) {
            f.open(argv[1]);
        }
        std::istream &in = (argc >= 2) ? f : std::cin;
    
        // use in here
    }
    

    您可以将其中的一些工作转移到一个辅助类中,以便更清楚地了解正在发生的事情(请注意,在无法打开文件的情况下,其行为略有不同):

    #include <iostream>
    #include <fstream>
    
    class ifstream_or_cin_t {
        std::ifstream f;
    
    public:
        ifstream_or_cin_t(const char *filename)
        {
            if (filename) {
                f.open(filename);
            }
        }
    
        operator std::istream &() { return f.is_open() ? f : std::cin; }
    };
    
    static void do_input(std::istream &in)
    {
        // use in...
    }
    
    int main(int argc, char **argv)
    {
        do_input(
            ifstream_or_cin_t((argc >= 2) ? argv[1] : NULL));
    }
    

    【讨论】:

    • @Martin & @dave:虽然这当然是对的,但我更喜欢 James 的回答。将问题(决定从哪里读取与实际读取)分解为函数使代码更易于阅读。
    • @sbi 分解效果如何? ;)
    • 首先,我不喜欢为算法引入类。算法最好实现为函数,类很适合存储对象,即:状态(成员数据)加上操作(成员函数)。选择流是一种算法。但这可能只是我的喜好。第二个问题不那么有争议:如果你不能打开文件,这段代码会默默地从控制台读取。想象一下,用户输入错误的文件名,然后坐着盯着闪烁的提示,不知道该怎么做!
    • @sbi, @James:经过考虑,对于更简单的程序类型,我确实更喜欢 James 版本。但是对于需要解析大量命令行参数的情况(您通常不会在 main 中这样做),我需要考虑更多。
    【解决方案2】:

    您可以编写一个引用std::istream 的函数:

    void do_input(std::istream& the_istream)
    {
        int my_awesome_variable;
        the_istream >> my_awesome_variable;
    }
    

    使用示例:

    int main()
    {
        // reading from stdin:
        do_input(std::cin);
    
        // reading from a file:
        std::ifstream fs("test.txt");
        do_input(fs);
    }
    

    【讨论】:

      【解决方案3】:

      我的 2P 价值:

      #include <iostream>
      #include <fstream>
      #include <string>
      
      extern char const* findFlag(int,char*[],char const*);
      int main(int argc,char* argv[])
      {
          std::string     isFile  = findFlag(argc,argv,"-f");
          std::ifstream   file;
      
          if (isFile != "")
          {   file.open(isFile.c_str());
          }
          std::istream&   data    = isFile != "" ? file : std::cin;
      
      
      }
      

      【讨论】:

      • 只是一个小风格点...因为对于普通的 c-strings a == 或 != 比较将不起作用,我更喜欢从 c-string 显式创建一个 std::string 当我正在比较它们。
      • @San Jacinto:我理解你在一般情况下的观点。但我认为 x == "" 实际上比 x == std::string("") 更清晰。
      • !isFile.empty() 不是更好吗?
      【解决方案4】:
      istream& input = cin;
      

      inputFileStream ifstream(fileName);
      istream& input = inputFileStream;
      

      但是我认为这不是一个很好的方法,因为 cin 没有 close() 而 ifstream 有。

      【讨论】:

      • 您不能重新定位参考;即使您修复了明显的语法错误,input = inputFileStream 也无法工作。关于close(),通常你不必打电话给close();你只需让析构函数处理它。
      猜你喜欢
      • 1970-01-01
      • 2022-01-25
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-27
      相关资源
      最近更新 更多