【问题标题】:C++ Writing to file or console by argumentC++ 通过参数写入文件或控制台
【发布时间】:2013-05-31 18:59:22
【问题描述】:

好的,所以我想做一些我自己觉得很有趣的事情。我想在我的函数中添加一个可选参数,这个参数会做两件事; 1. 决定文本是打印到控制台还是文件 2. 打印到文件,否则打印到控制台

我希望它在同一个函数中,因为我想要非常高效的代码。 这就是我试图解决它的方法,但显然不起作用

void Maze::Print_maze(std::string file = "no!ne") const{
    if (file != "no!ne")
        std::ofstream outfile(file);
    for (int i = 0; i < Map.size(); i++)
    {
        for (int j = 0; j < Map[i].size(); j++)
        {
            if (file == "no!ne")
                std::cout << Map[i][j];
            else
                outfile << Map[i][j];
        }
        if (file == "no!ne")
            std::cout << std::endl;
        else
            outfile << std::endl;
    }
}

对于好奇的人.. 代码来自我正在处理的一个迷宫项目,我正在生成一个随机迷宫,解决它,还有可能从文件中读取迷宫然后解决它。 现在剩下的就是将其打印到文件中。但正如所说,我不想创建两个函数,而是将我的普通打印合并到控制台与打印到文件。我只是想知道如何..有可能吗? 我的“地图[][]”是vector &lt;vector&lt;char&gt; &gt;

【问题讨论】:

    标签: c++ file printing arguments optional


    【解决方案1】:

    void Maze::Print_maze(std::ostream&amp; s = std::cout)

    然后只需传递您要写入的任何流。

    【讨论】:

      【解决方案2】:

      最好的方法是让std::ostream* 指向std::ofstream,如果你想写入文件,或者std::cout,如果你想写入控制台。

      std::ostream* outputTarget = &std::cout;
      
      void output(const std::string& message)
      {
          *outputTarget << message;
      }
      
      void useFileOutput()
      {
          static std::ofstream outFile;
          if (!outFile.is_open())
              outFile.open("log.txt");
          outputTarget = &outFile;
      }
      
      void useCout()
      {
          outputTarget = &std::cout;
      }
      

      【讨论】:

      • 另一种方法是将代码放入一个接受std::ostream&amp; 的函数中。将cout 或文件流传递给函数。
      【解决方案3】:

      在您的情况下,我会创建 3 个功能,其中两个带有您想要消除歧义的签名,另一个具有实际工作的功能。这样一来,您就可以统一让一个功能完成工作并保持两个功能的清洁:

      public:
      void Maze::Print_maze(std::ostream& OutputTarget){
         for (int i = 0; i < Map.size(); i++)
         {
             for (int j = 0; j < Map[i].size(); j++)
             {
                 OutputTarget << Map[i][j];
             }
             OutputTarget << std::endl;
         }
      }
      
      void Maze::Print_maze() const{
         Print_maze(std::cout);
      }
      
      void Maze::Print_maze(std::string file) const{
         std::ofstream Output_file(file.c_str());
         Print_Maze(Output_file);
         Output_file.close();
      }
      

      传递对基本类型的引用允许您的迷宫输出逻辑忽略实际输出类型并专注于渲染迷宫。

      这在某种不太重要的钝感上也会更高效,因为您不需要进行一系列字符串比较。

      更重要的是,这个版本与演示和业务(迷宫渲染现在是一个业务)逻辑分开更简单,因此更易于阅读且不易出错。

      【讨论】:

      • 我喜欢这个,并且没有理由不让 _Print_maze 成为另一个 Print_maze 重载:让最终用户能够传入他们想要的任何 ostream。另外(挑剔,但我以前也这样做过)你不应该用前导 _ 命名变量/成员(包括函数),因为这是编译器标准保留的。
      • @MadScienceDreams 我认为编译器保留名称的 _ 仅适用于全局命名空间中的项目。无论哪种方式,您都是对的,没有充分的理由不让类的用户作为重载访问实际函数,而且 _ 无论如何都不是好习惯。对我的批评投赞成票。
      • 是的,这只是一种不好的做法:-P 与全世界分享我痛苦的代码审查
      【解决方案4】:

      谢谢大家,我阅读了您的回复,感谢您为帮助我所做的所有出色的 cmets 和努力。我找到了一个解决方案,我相信这是我能想出的解决问题的最佳方案。 我还添加了一些错误管理

      void Maze::Print_maze(std::string file) const{
          std::ofstream outfile(file);
          // if file is open, write to file otherwise write to console
          std::ostream &out= (!outfile.is_open()? std::cout : outfile);
          // Check if file failed to open
          if(file != "" && (!outfile.is_open()))
              std::cerr << "File failed to open." << std::endl;
          for (int i = 0; i < Map.size(); i++)
          {
              for (int j = 0; j < Map[i].size(); j++)
              {
                      out << Map[i][j];
              }
                  out << std::endl;
          }
          if(outfile.is_open())
              outfile.close();
      }
      

      编辑: 这个忘记说了。。 我的类的 Maze.h 文件包含以下函数声明:

      void Print_maze(std::string file = "") const;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-03-08
        • 1970-01-01
        • 1970-01-01
        • 2017-08-27
        • 2014-07-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多