Как заставить функцию printf выводить ее в файл или на консоль? - PullRequest
0 голосов
/ 31 января 2020

Как заставить функцию printf выводить ее в файл или на консоль? Если быть более точным c, если в основной функции у меня есть два мнения: 1. printf вывод в файл или 2. printf вывод в консоль; и у меня есть другая функция, которая имеет выход, мне нужно будет вернуть этот вывод в основную функцию, верно? Или есть другой способ?

Ответы [ 3 ]

3 голосов
/ 31 января 2020

Самый простой способ - НЕ использовать printf, а вместо этого использовать fprintf. В основном printf(arg1, arg2, ...) совпадает с fprintf(stdout, arg1, arg2, ...). Насколько я знаю, printf всегда будет печатать на консоли независимо от того, что вы делаете, поэтому, если вы хотите перенаправить ее, вам придется делать это через оболочку при вызове программы. В bash это будет что-то вроде ./a.out > file.txt. Возможно, существует какой-то способ перенаправить стандартный вывод в файл из программы, но я подозреваю, что это будет не очень идиоматическое решение c, а скорее всего лишь доказательство того, что это теоретически возможно.

Вот пример того, как вы можете решить это с помощью fprintf:

int main(int argc, char ** argv)
{
    FILE * fp;

    // If the program was invoked with an argument, treat it as a filename
    // and write the output to that file. Otherwise, write to stdout.
    if(argc == 2) fp = fopen(argv[1], "w");
    else          fp = stdout;

    fprintf(fp, "Hello, world!\n");
    fflush(fp); // Make sure everything gets printed.
    fclose(fp);
}

Я исключил все проверки ошибок здесь. Ты не должен. Вы должны проверить, если fopen удалось, например. Условие в операторе if также далеко от идеального. Это просто демонстрация.

0 голосов
/ 31 января 2020

В вашем случае вам нужно fprintf вместо printf.

fprintf работает почти так же, как printf, за исключением того, что вы передаете ему дополнительный первый аргумент. Этот аргумент - то место, где будет выводиться ваш вывод.

  1. Если вы хотите выводить файл, передайте указатель FILE* на ваш файл в качестве этого аргумента.

  2. Если вы хотите вывод на консоль, передайте stdout в качестве этого аргумента.

Например,

FILE* myFile = fopen("demo.txt", "w");

int dummy = 22;

fprintf(myFile, "%d will be written in <demo.txt>", dummy);

fprintf(stdout, "%d will be written in the console", dummy);

Примечание:

Вам не нужен новый заголовочный файл для fprintf. Он находится внутри регулярно включенного stdio.h. Здесь - полный справочник по fprintf.

0 голосов
/ 31 января 2020

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

Что-то вроде

bool print_to_file = false;
FILE *file;

print_to_file = get_print_to_file_choice();
if (print_to_file)
    file = get_file_to_print_to();

// ...

if (print_to_file)
    fprintf(file, "some text here...\n");
else
    printf("some text here...\n");

Теперь вышесказанное легко реализовать, но сложно поддерживать. Что если строку нужно изменить? Затем вам нужно помнить, что нужно изменить оба для вызовов fprintf и printf.

Таким образом, вы можете поместить это в функцию, которая принимает в качестве аргументов переменную флага и файла вместе со строкой формата и аргументы. Эта функция может использовать варианты функций печати varargs (vfprintf и vprintf) и выполнять условие в функции. В вашем основном коде вы могли бы затем вызвать эту функцию вместо этого.

Возможно, что-то вроде

void my_printf(bool print_to_file, FILE *file, const char *fmt, ...)
{
    va_list va;

    va_start(va, fmt);
    if (print_to_file)
        vfprintf(file, fmt, va);
    else
        vprintf(fmt, va);
    va_end(va);
}

// ...

my_printf(print_to_file, file, "Some text here...\n");

Возможны и другие решения, например, использование freopen, как упомянуто в комментарии. Или вы можете просто напечатать в stdout (с простым printf) и затем перенаправить вывод в оболочке или командной строке в файл.

...