stdout — запись в терминал и в файл переполнение стека

Я нашел ответ на этот вопрос для сценариев Python, Java, Linux, но не для C ++:

Я хотел бы записать все выходные данные моей программы на C ++ как в терминал, так и в выходной файл. Используя что-то вроде этого:

int main ()
{
freopen ("myfile.txt","w",stdout);
cout<< "Let's try this";
fclose (stdout);
return 0;
}

выводит его только в выходной файл с именем «myfile.txt» и запрещает его отображение на терминале. Как я могу сделать вывод на оба одновременно? Я использую Visual Studio 2010 Express (если это будет иметь значение).

Заранее спасибо!

4

Решение

Возможное решение: использовать статический поток, похожий на cout-объект, для записи как в cout, так и в файл.

Грубый пример:

struct LogStream
{
template<typename T> LogStream& operator<<(const T& mValue)
{
std::cout << mValue;
someLogStream << mValue;
}
};

inline LogStream& lo() { static LogStream l; return l; }

int main()
{
lo() << "hello!";
return 0;
}

Вам, вероятно, придется явно обрабатывать потоковые манипуляторы.

Вот моя реализация библиотеки.

5

Другие решения

Не существует встроенного способа сделать это за один шаг. Вы должны записать данные в файл, а затем вывести данные на экран в два этапа.

Вы можете написать функцию, которая принимает данные и имя файла и делает это для вас, чтобы сэкономить ваше время, какая-то функция регистрации.

1

У меня есть способ сделать это, и он основан на модели подписчика.

В этой модели вся ваша регистрация ведется «менеджером», а затем у вас есть «подписчики», которые решают, что делать с сообщениями. Сообщения имеют темы (для меня это номер), и регистраторы подписываются на одну или несколько тем.

Для вашей цели вы создаете 2 подписчика, один для вывода в файл, а другой для вывода на консоль.

В логике вашего кода вы просто выводите сообщение, и на этом уровне не нужно знать, что будет с ним делать. В моей модели вы можете сначала проверить, есть ли «слушатели», так как это считается дешевле, чем создание и вывод сообщений, которые в конечном итоге окажутся только в / dev / null (хорошо, вы понимаете, что я имею в виду).

1

Один из способов сделать это — написать небольшую оболочку, например:

class DoubleOutput
{
public:
// Open the file in the constructor or any other method
DoubleOutput(const std::string &filename);
// ...
// Write to both the file and the stream here
template <typename T>
friend DoubleOutput & operator<<(const T& file);
// ...
private:
FILE *file;
}

Наличие класса вместо функции заставляет вас использовать идиому RAII (https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization)

Чтобы использовать это:

DoubleOutput mystream("myfile");
mystream << "Hello World";
0
По вопросам рекламы [email protected]