[英]How to override cout in C++?
我有一個要求,我需要使用printf
和cout
將數據顯示到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);
您可以交換底層緩沖區。 這是通過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::cout
和printf
你無法修改,否則解決問題的最簡單方法是從cout
寫入不同的流並使用fprintf
而不是或與printf
一起使用。
通過遵循該方法,您可以定義實際寫入標准輸出和給定文件的新流類,以及將調用組合到printf
和fprintf
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.