В чем разница между fprintf и vfprintf в C ++?

Я не смог найти ответ на следующий вопрос, и у меня возникли некоторые проблемы, связанные с функциями.

Мое основное программирование выполняется на C #, и я никогда не изучал C ++ во время учебы, но в моей нынешней работе я должен также заняться программированием на C ++.

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

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

Когда ошибка происходит, это указывает на эту строку кода:

vfprintf( LogFile, fmt, va );

Затем я более внимательно посмотрел на код до и после, и поместил вышеизложенное в контекст, вокруг которого написано:

void FileLog( char *fmt, ... )
{
va_list       va;
struct  time  t;
struct  date  d;
long          clk;
static int    ReEntrant = 0;

if( FileLogEnabled == false )
return;

ReEntrant++;
if( ReEntrant > 1 )
return;

if( LogFile == NULL )
LogFile = fopen( LogFileName, "a+" );
if( LogFile != NULL )
{
gettime( &t );
getdate( &d );
fprintf( LogFile, "\n%d-%02d-%02d %2d:%02d:%02d.%02d0> ", d.da_year, d.da_mon, d.da_day, t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund );

va_start( va, fmt );
vfprintf( LogFile, fmt, va );
va_end( va );

fflush( LogFile );
...
}
ReEntrant = 0;
}

На самом деле я не понимаю, зачем это нужно (и если это так?) Вызывать оба fprintf, а затем vfprintf? Я думаю, что первый вызов fprintf запишет отформатированную строку в поток (File), и этого будет достаточно?

Небольшое объяснение или некоторая информация будет высоко ценится 🙂

РЕДАКТИРОВАТЬ: После комментария от nos — я отследил конкретный вызов функции, которая сегодня часто вызывает эту ошибку.

FileLog( "TimerRestore[%d], Name=%s", Package.CurGame->Timers[ Index ].Name.c_str() );

Я действительно думаю, что это может вызвать некоторые проблемы, так как «TimerRestore [% d], Name =% s» должно сопровождаться десятичной дробью и строкой arguemtn, однако указывается только строковый аргумент. Мне нужно провести некоторое тестирование, но я уверен, что автор, который написал этот код, хотел написать:

FileLog( "TimerRestore[%d], Name=%s", Index, Package.CurGame->Timers[ Index ].Name.c_str() );

Однако я до сих пор не понимаю, почему вызов функции не всегда приводит к ошибке. Или, может быть, причина того, что переменная «ReEntrant» в функции FileLog блокирует ее, когда она не выходит из строя?

Большое спасибо за все отзывы и информацию.

4

Решение

vprintf() (и друзья) позволяют использовать va_list в качестве аргумента, что полезно, когда ваша функция имеет переменное количество аргументов:

void log(FILE *file, const char* format, ... )
{
va_list args;
va_start (args, format);
fprintf(file, "%s: ", getTimestamp());
vfprintf (file, format, args);
va_end (args);
}

В вашем приложении вы можете вызвать эту функцию с переменным количеством аргументов:

log(file, "i=%d\n", i);           // 3 arguments
log(file, "x=%d, y=%d\n", x, y);  // 4 arguments

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

7

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

Во-первых, используя fprintf() и особенно) vfprintf() в С ++ есть злой.

К точке: fprintf() является переменной функцией, она принимает произвольное количество аргументов. Внутренне, переменные функции реализуются путем «распаковки» аргументов с использованием va_list, va_start() а также va_end(),

vfprintf() используется, когда вы хотите получить доступ к функциональности fprintf() от вашей собственной вариационной функции после Вы распаковали свои собственные аргументы (то есть, у вас есть доступ к va_list пример). vfprintf() является не VARIADIC; он принимает va_list хранение аргументов.

Вы не разместили объявление вызова вашей функции fprintf() а также vfprintf(), но мы можем предположить, что это вариативно. Сначала использует fprintf() распечатать некоторые данные в LogFile, а затем использует vfprintf() печатать свои собственные аргументы variadic там.

2

vfprintf Позволяет вам иметь список переменных аргументов Это означает, что вы можете динамически создавать список параметров во время выполнения.

0

Это довольно часто для регистрации. Вы хотите создать сообщение журнала в стиле printf, например:

Log("The value of x is now %d", x);

Но это требует переменных аргументов. Так вам нужно vfprintf, Причина fprintf используется также потому, что он хочет написать отметку даты / времени, и вы не можете добавить этот дополнительный материал в существующий формат, переданный в vfprintf,

Другой способ сделать это — использовать строковую версию vsprintfи сделайте одну большую строку, затем запишите ее в файл. Но это более подвержено ошибкам (например, переполнение буфера).

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector