6

我有一个要求,我也需要使用printfcout显示数据console and file。因为printf我已经做到了,但是cout我很挣扎,怎么做呢?

   #ifdef _MSC_VER
     #define GWEN_FNULL "NUL"
     #define va_copy(d,s) ((d) = (s))
         #else
         #define GWEN_FNULL "/dev/null"
        #endif
        #include <iostream>
        #include <fstream>

        using namespace std;
        void printf (FILE *  outfile, const char * format, ...) 
        {

            va_list ap1, ap2;
            int i = 5;
            va_start(ap1, format);
            va_copy(ap2, ap1);
            vprintf(format, ap1);
            vfprintf(outfile, format, ap2);
            va_end(ap2);
            va_end(ap1);
        }
    /*    void COUT(const char* fmt, ...)
        {
            ofstream out("output-file.txt");
            std::cout << "Cout to file";
            out << "Cout to file";
        }*/
        int main (int argc, char *argv[]) {

            FILE *outfile;
            char *mode = "a+";
            char outputFilename[] = "PRINT.log";
            outfile = fopen(outputFilename, mode);

            char bigfoot[] = "Hello 

World!\n";
        int howbad = 10;

        printf(outfile, "\n--------\n");
        //myout();

        /* then i realized that i can't send the arguments to fn:PRINTs */
        printf(outfile, "%s %i",bigfoot, howbad); /* error here! I can't send bigfoot and howbad*/

        system("pause");
        return 0;
    }

我已经完成了COUT(大写,上面代码的注释部分)。但我想使用 normal std::cout,所以我该如何覆盖它。sting and variables它应该适用于两者

int i = 5;
cout << "Hello world" << i <<endl;

或者无论如何都可以捕获stdout数据,以便它们也可以轻松写入file and console

4

9 回答 9

12

如果您有另一个流缓冲区,则只需替换std::cout's:

std::cout.rdbuf(some_other_rdbuf);

请参阅http://en.cppreference.com/w/cpp/io/basic_ios/rdbuf

于 2013-09-24T07:44:15.540 回答
4

您可以交换底层缓冲区。这是通过 RAII 促成的。

#include <streambuf>

class buffer_restore
{
    std::ostream&   os;
    std::streambuf* buf;
public:
    buffer_restore(std::ostream& os) : os(os), buf(os.rdbuf())
    { }

    ~buffer_restore()
    {
        os.rdbuf(buf);
    }
};

int main()
{
    buffer_restore b(std::cout);
    std::ofstream file("file.txt");

    std::cout.rdbuf(file.rdbuf());
    // ...
}
于 2013-09-24T12:30:46.453 回答
1

我假设您有一些代码正在使用std::cout并且printf您无法修改,否则解决问题的最简单方法是写入不同的流cout并使用,fprintf而不是与printf.

通过遵循这种方法,您可以定义一个新的流类,该类实际上既可以写入标准输出,也可以写入给定文件,还可以定义一个函数,该函数结合了对printf和的调用fprintf

然而,更简单的方法是使用tee最初来自 UNIX 的程序,它将输入复制到输出和给定文件。有了它,您可以简单地以这种方式调用您的程序:

your_program | tee your_log_file

这个问题的答案导致了一些可用于 Windows 的替代实现。就我个人而言,我总是在我的 PC 上安装cygwin以提供 UNIX/Linux 实用程序。

于 2013-09-24T07:45:29.793 回答
1

覆盖 of 的行为std::cout是一个非常糟糕的主意,因为其他开发人员将很难理解使用的std::cout行为不像往常一样。

通过简单的课程明确您的意图

#include <fstream>
#include <iostream>

class DualStream
{
   std::ofstream file_stream;
   bool valid_state;
   public:
      DualStream(const char* filename) // the ofstream needs a path
      :
         file_stream(filename),  // open the file stream
         valid_state(file_stream) // set the state of the DualStream according to the state of the ofstream
      {
      }
      explicit operator bool() const
      {
         return valid_state;
      }
      template <typename T>
      DualStream& operator<<(T&& t) // provide a generic operator<<
      {
         if ( !valid_state ) // if it previously was in a bad state, don't try anything
         {
            return *this;
         }
         if ( !(std::cout << t) ) // to console!
         {
            valid_state = false;
            return *this;
         }
         if ( !(file_stream << t) ) // to file!
         {
            valid_state = false;
            return *this;
         }
         return *this;
      }
};
// let's test it:
int main()
{
   DualStream ds("testfile");
   if ( (ds << 1 << "\n" << 2 << "\n") )
   {
      std::cerr << "all went fine\n";
   }
   else
   {
      std::cerr << "bad bad stream\n";
   }
}

这提供了一个干净的界面,并为控制台和文件输出相同的内容。您可能想要添加刷新方法或以附加模式打开文件。

于 2013-09-24T08:11:29.833 回答
0

如果我猜对了,您希望将输出的所有内容也记录到文件中。

你想要的是一个观察者模式

将代码中的所有直接登录替换为对新中继的调用。日志中继将您的消息发送给观察者。您的一位观察者将消息记录到屏幕上。另一个记录到文件中。如果可能的话,避免让你的继电器成为单例。

此建议仅在您可以编辑所有源文件时才有效。

于 2013-09-24T08:15:57.260 回答
0

std::cout写入stdout文件您可以在 Linux 和 Windows 上执行以下操作

#include <stdio.h>
#include <iostream>



int main()
{
    freopen("test.txt", "w", stdout);
    std::cout << "Hello strange stdout\n";
}

将其改回使用从此处获取的以下内容

#include <stdio.h>
#include <stdlib.h>

void main(void)
{
   FILE *stream ;
   if((stream = freopen("file.txt", "w", stdout)) == NULL)
      exit(-1);

   printf("this is stdout output\n");

   stream = freopen("CON", "w", stdout);

   printf("And now back to the console once again\n");
}

注意:后者仅适用于 windows

于 2013-09-24T09:35:48.927 回答
-1

cout通常实现为对象实例,因此您不能以重载/覆盖函数或类的方式覆盖它。

你最好的选择是不要与之抗争——是的,你可以构建一个my_cout#define cout my_cout但这会使你的代码变得迟钝。

为了可读性,我会保持cout原样。这是一个标准,每个人都知道它能做什么,不能做什么。

于 2013-09-24T07:33:52.213 回答
-1

尝试使用宏 - 像这样(您需要添加包含):

#define MY_COUT(theos,printThis) { cout << printThis ; theos <<  printThis; }

void test()
{
     ofstream myos;
    myos.open("testfile", ios::trunc|ios::out);
    int i = 7;
    MY_COUT(myos, "try this numbers" << i << i + 1 << endl);
    myos.close()
}
于 2013-09-24T08:01:10.243 回答
-1

已经有一个 Boost 类:tee

于 2013-09-24T14:41:36.433 回答