How to pass variable number of arguments to printf/sprintf
Solution 1
void Error(const char* format, ...)
{
va_list argptr;
va_start(argptr, format);
vfprintf(stderr, format, argptr);
va_end(argptr);
}
If you want to manipulate the string before you display it and really do need it stored in a buffer first, use vsnprintf
instead of vsprintf
. vsnprintf
will prevent an accidental buffer overflow error.
Solution 2
have a look at vsnprintf as this will do what ya want http://www.cplusplus.com/reference/clibrary/cstdio/vsprintf/
you will have to init the va_list arg array first, then call it.
Example from that link: /* vsprintf example */
#include <stdio.h>
#include <stdarg.h>
void Error (char * format, ...)
{
char buffer[256];
va_list args;
va_start (args, format);
vsnprintf (buffer, 255, format, args);
//do something with the error
va_end (args);
}
Solution 3
I should have read more on existing questions in stack overflow.
C++ Passing Variable Number of Arguments is a similar question. Mike F has the following explanation:
There's no way of calling (eg) printf without knowing how many arguments you're passing to it, unless you want to get into naughty and non-portable tricks.
The generally used solution is to always provide an alternate form of vararg functions, so printf has vprintf which takes a va_list in place of the .... The ... versions are just wrappers around the va_list versions.
This is exactly what I was looking for. I performed a test implementation like this:
void Error(const char* format, ...)
{
char dest[1024 * 16];
va_list argptr;
va_start(argptr, format);
vsprintf(dest, format, argptr);
va_end(argptr);
printf(dest);
}
Solution 4
You are looking for variadic functions. printf() and sprintf() are variadic functions - they can accept a variable number of arguments.
This entails basically these steps:
The first parameter must give some indication of the number of parameters that follow. So in printf(), the "format" parameter gives this indication - if you have 5 format specifiers, then it will look for 5 more arguments (for a total of 6 arguments.) The first argument could be an integer (eg "myfunction(3, a, b, c)" where "3" signifies "3 arguments)
Then loop through and retrieve each successive argument, using the va_start() etc. functions.
There are plenty of tutorials on how to do this - good luck!
Solution 5
Simple example below. Note you should pass in a larger buffer, and test to see if the buffer was large enough or not
void Log(LPCWSTR pFormat, ...)
{
va_list pArg;
va_start(pArg, pFormat);
char buf[1000];
int len = _vsntprintf(buf, 1000, pFormat, pArg);
va_end(pArg);
//do something with buf
}
user5722
Updated on July 08, 2022Comments
-
user5722 almost 2 years
I have a class that holds an "error" function that will format some text. I want to accept a variable number of arguments and then format them using printf.
Example:
class MyClass { public: void Error(const char* format, ...); };
The Error method should take in the parameters, call printf/sprintf to format it and then do something with it. I don't want to write all the formatting myself so it makes sense to try and figure out how to use the existing formatting.
-
Jonathan Leffler almost 15 yearsThe final 'printf(dest);' is mal-formed - it needs at least a format string too.
-
Lodle almost 15 yearsIt doesnt as the string is the format string i.e. printf("a string"); is fine
-
John Kugelman almost 15 yearsYou can get away with printf(dest) up until dest happens to contain "%s" or "%d", then BOOM. Please use printf("%s", dest).
-
MickLH about 10 yearsJust want to come by to point out that a core dump is the best case scenario, do that in server code and hackers will have your CPU for breakfast.
-
aviggiano about 8 yearsvsnprintf's second argument should be the buffer length, including the terminating null byte ('\0'). So you can use 256 in the function call instead of 255.
-
eddyq almost 8 yearsThis is how to make an easy thing hard.
-
eddyq almost 8 yearsTry using "%.16383s" and that will protect the array dest from overflow. (allow for the '\0' terminator)
-
osvein almost 7 years"Using functions with ellipses is not very safe." if your only safe alternative involves c++ and boost, you should explain what you mean by "not very safe", and mention that the printf functions are perfectly safe if you use the correct format specifiers.
-
Anonymouse about 5 yearsand passing magic numbers is BAD... use
sizeof(buffer)
instead of 256.