I have function called foo and that function takes ..., I want to pass all the argument that passed in ... to the function called oof, sample code:
#include <stdio.h>
#include <stdarg.h>
void oof(FILE * f, const char * fmt, ...){
va_list args;
va_start(args, fmt);
vfprintf(f, fmt, args);
va_end(args);
}
void foo(const char * fmt, ...){
oof(stdout, fmt, ...); // how can I pass the 3 dots?
// do other things in the function block
}
int main(int argc, char *argv[]){
foo("Hello %s\n", "World");
}
I don't want to pass to oof a va_list, but the arguments themselves
You need to change oof to accept a va_list and pass that.
void oof(FILE * f, const char * fmt, va_list args){
vfprintf(f, fmt, args);
}
void foo(const char * fmt, ...){
va_list args;
va_start(args, fmt);
oof(stderr, fmt, args);
va_end(args);
}
You cannot do this with a function but you can do this with a macro:
#define foo(...) oof(__VA_ARGS__)
There is still an issue.
Where do you get FILE *f argument from?
Assuming it is stdout then define the macro as:
#define foo(...) oof(stdout, __VA_ARGS__)
amd if you want to eliminate some parameters (doing the inverse of above, just do the following:
#define foo(a, b, ...) oof(__VA_ARGS__)
This is similar to dbush's answer (dbush should get the credit - do not accept my answer over theirs), but slightly modified because of OP's statement:
I don't want to pass to oof a va_list, but the arguments themselves
Because a va_list needs to be passed to something, I define a different function voof called by both oof and foo:
#include <stdio.h>
#include <stdarg.h>
void voof(FILE * f, const char * fmt, va_list args){
vfprintf(f, fmt, args);
}
void oof(FILE * f, const char * fmt, ...){
va_list args;
va_start(args, fmt);
voof(f, fmt, args);
va_end(args);
}
void foo(const char * fmt, ...){
va_list args;
va_start(args, fmt);
voof(stderr, fmt, args);
va_end(args);
}
int main(int argc, char *argv[]){
foo("Hello %s\n", "World");
}
foo and oof currently do the same thing, apart from the extra FILE * parameter in oof.
Related
This question already has an answer here:
C - Variable Argument with Sprintf?
(1 answer)
Closed 2 years ago.
I try to achieve same thing in vprintf function using sprintf to write into buffer, however I can not do it. What is my mistake?
#include <stdio.h>
#include <stdarg.h>
char latestPrint[1000];
int currentPositionPrint=0;
void WriteFrmtd(char *format, ...) {
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
void WriteToPrint(char *format, ...) {
va_list args;
va_start(args, format);
currentPositionPrint+=sprintf(currentPositionPrint+latestPrint , format, args);
va_end(args);
}
int main () {
WriteFrmtd("%d variable argument\n", 1);
WriteFrmtd("%d variable %s\n", 2, "argumentsqweqweqweqwe");
WriteToPrint("%d variable %s\n", 2, "argumentsqweqweqweqwe");
printf("%s",latestPrint);
return(0);
}
Output:
1 variable argument
2 variable argumentsqweqweqweqwe
1698242904 variable 1698242904 variable
You can use vsprintf (same as vprintf but using an array as output instead of stdout):
void WriteToPrint(char *format, ...)
{
va_list args;
va_start(args, format);
currentPositionPrint += vsprintf(latestPrint + currentPositionPrint, format, args);
va_end(args);
}
You can't use sprintf with variable arguments. You need to use vsprintf instead:
Change:
currentPositionPrint += sprintf(currentPositionPrint+latestPrint , format, args);
to:
currentPositionPrint += vsprintf(currentPositionPrint+latestPrint , format, args);
Free hint: use spaces between operators: foo += bar is more readable than foo+=bar.
I am trying to pass variable arguments that I get to another function I call.
I had written a sample code to test this.
Why is my_printf working but not my2_printf in below code?
#include <stdio.h>
#include <stdarg.h>
my2_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
printf(fmt, ap);
va_end(ap);
}
my_printf(const char *fmt, ...)
{
va_list ab;
va_start(ab, fmt);
vfprintf(stdout, fmt, ab);
va_end(ab);
}
main()
{
int i = 5;
my_printf("This is a test %d => %s\n", i, "done");
my2_printf("This is a test %d => %s\n", i, "done");
}
Output I get is as below:
This is a test 5 => done
This is a test -171084944 =>
Because there's variant of printf that expects a va_list argument. If you have a va_list you must use the functions with the v prefix, such as vprintf.
The call to printf leads to undefined behavior.
I found the following code can add log into syslog. But if i also want to add __FUNCTION__ info to the syslog, how to do it?
openlog(basename(argv[0]), LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON);
int logger(int priority, const char *format, ...) {
int result = 0;
va_list args;
va_start(args, format);
vsyslog(priority, format, args);
vfprintf(stderr, format, args);
va_end(args);
return result;
}
First, modify logger to accept the function name:
int logger_internal(const char* func, int priority, const char* format, ...);
But call it through the macro:
#define logger(priority, format, ...) \
logger_internal(__FUNCTION__, priority, format, __VA_ARGS__)
Modifying the body of logger_internal to take the extra parameter into account is a bit annoying, but not difficult. Probably the most straightforward way would be to prepend the function to the format argument; so something like (untested):
int logger_internal(const char* func, int priority, const char* format, ...) {
va_list args;
size_t func_l = strlen(func);
size_t format_l = strlen(format);
char* fmt = malloc(func_l + format_l + 2);
memcpy(fmt, func, func_l);
fmt[func_l] = ' ';
memcpy(&(fmt[func_l + 1]), format, format_l);
fmt[func_l + 1 + format_l] = '\0';
va_start(args, format);
vsyslog(priority, fmt, args);
va_end(args);
free(fmt);
}
But obviously that part would depend on what you wanted your syslog entry to look like.
#define TRACE2(args) TraceDebug args;
void TraceDebug ( const char * format, ... );
void TraceDebug ( const char * format, ... )
{
static char buffer[256];
va_list args;
va_start (args, format);
vsprintf (buffer,format, args);
va_end (args);
}
int main(void)
{
TRACE2(("ece %d is of %d students.", 1,33));
return 0;
}
The expected output is ece 1 is of 33 students. Why the output screen is blank?
You only print into buffer, but you don't print anything on the screen.
This is what you need:
void TraceDebug ( const char * format, ... )
{
static char buffer[256];
va_list args;
va_start (args, format);
vsprintf (buffer,format, args);
va_end (args);
printf("%s", buffer); // <<< add this
}
Or just use vprintf if you only want output on the screen.
void TraceDebug(const char * format, ...)
{
va_list args;
va_start(args, format);
vprintf(format, args); // <<<<<<<<<<<
va_end(args);
}
Sorry for the simple question, but how could I create the C-function with undefined number of parameters such as
int printf ( const char * format, ... ).
I would like to create function to use it as wrapper for printk:
void my_printk( const char * format, ...)
{
printk("my log:");
printk(format, ...);
printk("\n");
}
Thanks
You have to convert the args to a va_list before you can pass it to another function. Then you can pass it to the 'v' version of the function.
So you can do:
void my_printk( const char * format, ...)
{
va_list ap;
va_start(ap, format);
printk("my log:");
vprintk(format, ap);
printk("\n");
va_end(ap);
}
Most of the time, any function like this will provide a 'v' version, and yours should too:
void my_vprintk( const char * format, va_list ap)
{
printk("my log:");
vprintk(format, ap);
printk("\n");
}
void my_printk( const char * format, ...)
{
va_list ap;
va_start(ap, format);
my_vprintk(format, ap);
va_end(ap);
}
You're close. Have a look here: http://publications.gbdirect.co.uk/c_book/chapter9/stdarg.html
int f(int, ... );
int f(int, ... ) {
.
.
.
}
int g() {
f(1,2,3);
}