Как я могу печатать в 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

Ты знаешь sprintf? В основном то же самое и с fprintf. Первый аргумент - это место назначения (файл в случае fprintfiestderr ), второй аргумент - это строка формата, а остальные - обычные аргументы.

Я также рекомендую эту printf(и семейную) ссылку .

Какой-то чувак-программист
источник
5

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

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

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

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

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

lxiange
источник
Вы также можете дать ему отдельное имя 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");
winterli
источник
Это ничего не добавляет к предыдущим ответам и на самом деле не отвечает на вопрос.
Фантастический мистер Фокс
Этот оператор sprintf () вызывает повреждение памяти! ... Я настоятельно рекомендую вам прочитать, как работают указатели, массивы и строки.
BlueChip