现在的位置: 首页 > 综合 > 正文

What is the difference between fprintf and vfprintf in C++?

2013年05月23日 ⁄ 综合 ⁄ 共 2613字 ⁄ 字号 评论关闭

// 

http://stackoverflow.com/questions/14358497/what-is-the-difference-between-fprintf-and-vfprintf-in-c

 

I haven't been able to find an answer to the following question, and I am having some issues related to the functions.

My main programming is done in C#, and never really learned C++ while studying, but in my current job I have to do some C++ programming aswell.

Most of the C++ programming have been done by a former employee, and he made a function for logging.

Once in a while this function results in an error (Access Violation) - this is not shown to the user, but I see it while running the code through debugger.

When the error happens it points to this line of code:

vfprintf( LogFile, fmt, va );

I then took a closer look at the code before and after, and to put the above into a context the code around is:

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;
}

Actually I dont understand why it is needed (and if it is?) call both fprintf and then vfprintf? I would think the first fprintf call would write the formatted string to the stream (File), and that would be enough?

A little explanation or some information would be much appreciated :)

EDIT: After the comment from nos - I tracked down the specific call to the function which today have often been causing this error.

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

I indeed think this could cause some trouble, as "TimerRestore[%d], Name=%s" should be followed by a decimal and string arguemtn, however only a string argument is given. I need to do some testing, but Im sure the author who wrote this code meant to write:

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

However I still do not understand why the function call does not always seem to result in an error. Or maybe it is cause of the "ReEntrant" variable in FileLog function is blocking it when it does not fail?

Thanks a lot for all the feedback and information.

 

 

vprintf() (and friends) allow to use

va_list
as argument, which is useful when your function has a variable amount of arguments:

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);
}

In your application you can call this function with a variable amount of arguments:

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

I do not know why your function results in an error. Your code snippet does not provide enough details. The amount of type of provided function arguments
might be the cause.

 

【上篇】
【下篇】

抱歉!评论已关闭.