簡體   English   中英

如何在C ++中覆蓋cout?

[英]How to override cout in C++?

我有一個要求,我需要使用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 (caps,上面代碼的注釋部分)中完成了它。 但我想使用普通的std::cout ,所以如何覆蓋它。 它應該適用於sting and variables

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

或者無論如何都要捕獲stdout數據,以便它們也可以輕松地寫入file and console

如果你有另一個流緩沖區,你可以只替換std::cout

std::cout.rdbuf(some_other_rdbuf);

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

您可以交換底層緩沖區。 這是通過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());
    // ...
}

覆蓋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";
   }
}

這提供了一個干凈的界面,並為控制台和文件輸出相同的內容。 您可能需要添加flush方法或以追加模式打開文件。

我假設你有一些代碼使用std::coutprintf你無法修改,否則解決問題的最簡單方法是從cout寫入不同的流並使用fprintf而不是或與printf一起使用。

通過遵循該方法,您可以定義實際寫入標准輸出和給定文件的新流類,以及將調用組合到printffprintf printf

然而,更簡單的方法是使用最初來自UNIX的tee程序,該程序將其輸入復制到輸出和給定文件。 有了它,你可以這樣簡單地調用你的程序:

your_program | tee your_log_file

這個問題的答案導致一些可用於Windows的替代實現。 就個人而言,我總是在我的電腦上安裝cygwin ,以提供UNIX / Linux實用程序。

如果我猜對了,你想將輸出的所有內容都記錄到文件中。

你想要的是一個觀察者模式

通過調用新中繼替換代碼中的所有直接日志記錄。 日志記錄中繼將您的消息發送給觀察者。 您的一位觀察者將消息記錄到屏幕上。 另一個登錄到文件。 如果可能的話,避免讓你的繼電器成為單件。

只有在您可以編輯所有源文件時,此建議才有效。

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

cout通常作為對象實例實現,因此您不能以重載/覆蓋函數或類的方式覆蓋它。

你最好的選擇不是打架 - 是的,你可以建立一個my_cout#define cout my_cout但這會讓你的代碼變得遲鈍。

為了便於閱讀,我會留下cout 這是一個標准,每個人都知道它能做什么,不能做什么。

嘗試使用宏 - 這樣的東西(你需要添加包含):

#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()
}

已有一個Boost類: tee

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM