2014-02-08 6 views
16

Если я решил создать Windows-консольное приложение и реализовать код printf\cout в коде, где пишет printf\cout? Записывает ли он буфер stdout? Если да, есть ли все-таки прочитать его от stdout и распечатать его в каком-то текстовом файле или сделать MessageBox с текстом (просто чтобы убедиться, что я прочитал его правильно)?Где «printf» записывается в Windows-консольном приложении?

EDIT :: Просто чтобы уточнить, что я не хочу перенаправлять вывод в любом месте. Я хотел бы знать, где пишет printf/cout? И если он пишет в буфер по умолчанию, есть ли способ прочитать вывод, просто чтобы убедиться, что я прочитал правильный вывод и из правильного буфера. Пожалуйста, не давайте мне решения для перенаправления «stdout».

+4

Технически это не писать где угодно, но вы можете перенаправить его в текстовый файл, используя 'freopen («file.txt»,«ж», стандартный вывод) ; ' – Predelnik

+1

возможный дубликат [Как я могу перенаправить stdout на какой-либо видимый экран в приложении Windows?] (Http://stackoverflow.com/questions/573724/how-can-i-redirect-stdout-to-some-visible -display-in-a-windows-приложение) –

+1

@MartinR :: Я не хочу перенаправлять вывод. Я хочу знать, где он пишет, если не перенаправлен, и есть способ прочитать это местоположение для проверки. – Abhineet

ответ

13

Под Windows stdout является оболочкой функций нижнего уровня, обращающихся к дескриптору, возвращаемому GetStdHandle(STD_OUTPUT_HANDLE).

При запуске приложения без консоли двойным щелчком (я попытался под Windows 7, 64 бит) GetStdHandle(STD_OUTPUT_HANDLE) вернет недействительный дескриптор. Это означает, что printf и другие команды ничего не будут писать, но низкоуровневые функции, вызванные внутренним вызовом printf, вернут код ошибки.

Однако, как уже было сказано даже программы без консоли можно запустить следующим образом:

program_name > output_file.txt 

В этом случае printf выход будет записан в выходной файл.

- EDIT -

Если вы хотите «поймать» printf() вывод и записать его на MessageBox() есть два пути для достижения этой цели:

Первый работает программа дважды в то время как вход одного экземпляра является стандартным выходом другого. Поведение может быть объяснено с помощью следующей командной строки:

program_name | program_name /msgbox 

вторая возможность работы без запуска двух программ и без запуска программы дважды: Вы можете подключить файл ручки # 1. Это должно быть по крайней мере, возможно при использовании msvcrt.dll:

HANDLE hRead,hWrite; 

CreatePipe(&hRead,&hWrite,NULL,0); 
dup2(_open_osfhandle(hWrite,O_WRONLY),1); 

// Now printf() output can be read from handle hRead 

printf("Hello world 2!\n"); 

// In a separate thread do: 
ReadFile(hRead,...); 
+0

+1 До сих пор ваше решение выглядит наиболее подходящим для меня. – Abhineet

2

printf или cout всегда печатать до stdout.

Вам необходимо запустить программу из командной строки и передать ее вывод в текстовый файл, чтобы сделать его доступным для чтения.

В противном случае вам понадобится выходной поток для файла в tmp, который будет сгенерирован внутри вашего кода.

Трубопровод можно сделать следующим образом (если ваше имя приложения будет Foo):

foo > log.txt 

Затем можно прочитать файл log.txt, если вы перейдете в свой каталог, который может быть найден с

dir 
+0

Заявление 'printf или cout всегда печатается в stdout'is plain wrong –

+0

они печатаются на stdout, которые вы должны перенаправить в качестве вызывающего абонента – nesreka

+4

@ Dieter Действительно? «Объект cout управляет выходом в буфер потока, связанный с объектом stdout» (27.4.2/3) –

4

Я разрабатываю визуальный движок, и я использую следующие две вещи в качестве замены стандартного ввода/вывода между ПК и пользователем, которые вы получаете в консольном приложении.

1: Использовать sprintf(int sprintf (char * str, const char * format, ...)). То, что он делает, это печатать в строку вместо stdout (вам не нужно использовать временный файл). После этого вы можете использовать MessageBox со строкой, на которой вы только что напечатали.

2: Сделайте фактическое окно консоли (при сохранении основного) и перенаправьте stdin, stdout и stderr из главного окна на консоль. Вот класс для строительства:

ConsoleWindowClass.h:

#pragma once 
#include <windows.h> 
#include <stdio.h> 
#include <fcntl.h> 
#include <io.h> 
#include <iostream> 
#include <fstream> 
class ConsoleWindowClass 
{ 
public: 
    ConsoleWindowClass(void); 
    ~ConsoleWindowClass(void); 
    void Create(); 
}; 

ConsoleWindowClass.cpp:

#include "ConsoleWindowClass.h" 

using namespace std; 

// maximum mumber of lines the output console should have 
static const WORD MAX_CONSOLE_LINES = 500; 

ConsoleWindowClass::ConsoleWindowClass(void) 
{ 
    Create(); 
} 

ConsoleWindowClass::~ConsoleWindowClass(void) 
{ 
} 

void ConsoleWindowClass::Create() 
{ 
    int hConHandle; 
    long lStdHandle; 
    CONSOLE_SCREEN_BUFFER_INFO coninfo; 
    FILE *fp; 

// allocate a console for this app 
    AllocConsole(); 

// set the screen buffer to be big enough to let us scroll text 
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&coninfo); 
    coninfo.dwSize.Y = MAX_CONSOLE_LINES; 
    SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),coninfo.dwSize); 

// redirect unbuffered STDOUT to the console 
    lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE); 
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); 

    fp = _fdopen(hConHandle, "w"); 

    *stdout = *fp; 

    setvbuf(stdout, NULL, _IONBF, 0); 

// redirect unbuffered STDIN to the console 

    lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE); 
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); 

    fp = _fdopen(hConHandle, "r"); 
    *stdin = *fp; 
    setvbuf(stdin, NULL, _IONBF, 0); 

// redirect unbuffered STDERR to the console 
    lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE); 
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); 

    fp = _fdopen(hConHandle, "w"); 

    *stderr = *fp; 

    setvbuf(stderr, NULL, _IONBF, 0); 

// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog 
// point to console as well 
    ios::sync_with_stdio(); 
} 

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

+0

Если вы хотите использовать только C, а не C++, вы можете вырезать и ios :: sync_with_stdio(). Вам также придется делать это без класса. Вот что делает последняя строка: http://www.cplusplus.com/reference/ios/ios_base/sync_with_stdio/ – Vladivarius

+0

Спасибо за ваше решение, но любезно прочитайте «Изменить». – Abhineet

+0

Да, я понял вопрос после того, как написал ответ. Во всяком случае, это, надеюсь, послужит кому-то, кто ищет перенаправление :) – Vladivarius

10

Поскольку ваш вопрос, кажется, просто для информации, приложение Windows без консоли, имеет свои stdout, дескрипторы stderr закрыты. Любая функция, которая пытается вывести на эти дескрипторы, просто получает вызов, проверяет открытый дескриптор, находит его закрытым и возвращается без каких-либо действий.

Вы можете сказать, ваш выход в этом случае заканчивается нигде не найти :)

Если вы хотите, чтобы прочитать этот вывод, то вам нужно открыть ручки либо путем выделения консоли, или использовать один из описанные здесь методы.

Смежные вопросы