Как я могу печатать в stderr на C?


121

В C печать в стандартный вывод выполняется легко с помощью printffrom stdio.h.

Однако как можно печатать в stderr? fprintfОчевидно, мы можем использовать для этого, но его синтаксис кажется странным. Может быть, мы можем использовать printfдля печати в stderr?


5
Что такого «странного» в его синтаксисе? Это распечатать где , как и что .
Евгений Ш.

5
Я сосредотачиваюсь на этом. Единственная проблема, которая возникает из-за того, что вы находите решение "странным". В остальном нет вопросов. Используйте fprintf.
Евгений Ш.

@Eugene. Я согласен с тобой. Я подумал, что это странно, так как я не понимал, что stderr - это ФАЙЛ :)
wad

Ответы:


180

Синтаксис почти такой же, как у printf. С помощью printfвы указываете формат строки и ее содержимое, т.е.

printf("my %s has %d chars\n", "string format", 30);

С fprintfним то же самое, за исключением того, что теперь вы также указываете место для печати:

File *myFile;
...
fprintf( myFile, "my %s has %d chars\n", "string format", 30);

Или в вашем случае:

fprintf( stderr, "my %s has %d chars\n", "string format", 30);

35

Примеры:

printf("%s", "Hello world\n");              // "Hello world" on stdout (using printf)
fprintf(stdout, "%s", "Hello world\n");     // "Hello world" on stdout (using fprintf)
fprintf(stderr, "%s", "Stack overflow!\n"); // Error message on stderr (using fprintf)

10
#include<stdio.h>

int main ( ) {
    printf( "hello " );
    fprintf( stderr, "HELP!" );
    printf( " world\n" );
    return 0;
}

$ ./a.exe
HELP!hello  world
$ ./a.exe 2> tmp1
hello  world
$ ./a.exe 1> tmp1
HELP!$
  1. stderr обычно не буферизуется, а stdout обычно. Это может привести к тому, что результат будет выглядеть странно, что говорит о том, что код выполняется в неправильном порядке. Это не так, просто буфер stdout еще не очищен. Перенаправленные или передаваемые по конвейеру потоки, конечно, не увидят это чередование, поскольку обычно они видят только вывод только stdout или только stderr.

  2. Хотя изначально на консоль выводятся как stdout, так и stderr, оба являются отдельными и могут быть перенаправлены индивидуально.



5

Если вы не хотите изменять текущие коды и просто для отладки.

Добавьте этот макрос:

#define printf(args...) fprintf(stderr, ##args)
//under GCC
#define printf(args...) fprintf(stderr, __VA_ARGS__)
//under MSVC

Изменить stderrнаstdout если хотите откатиться.

Это полезно для отладки, но это не очень хорошая практика.


Вы также можете дать ему отдельное имя eprintfили что-то в этом роде. (: O На самом деле это пример макроса с переменным числом аргументов из GCC (3.2): gcc.gnu.org/onlinedocs/gcc-3.2/cpp/Variadic-Macros.html )
Соломон Юко

0

Чтобы распечатать свой контекст, вы можете написать такой код:

FILE *fp;
char *of;
sprintf(of,"%s%s",text1,text2);
fp=fopen(of,'w');
fprintf(fp,"your print line");

Это ничего не добавляет к предыдущим ответам и на самом деле не отвечает на вопрос.
Фантастический мистер Фокс

Этот оператор sprintf () вызывает повреждение памяти! ... Я настоятельно рекомендую вам прочитать, как работают указатели, массивы и строки.
BlueChip
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.