olidev
olidev

Reputation: 20644

varargs to printf all arguments

if I have this function:

printAll(const char *message, ...)
{
    va_list argptr = NULL;
    va_start(argptr, message);
   
    // todo: how to printf all the arguments in the message?   
 
    va_end(argptr);    
}

Suppose I call the function like this:

printAll("My info: Value1 = %d, Value 2=%d", 1, 2);

In this line: // todo: how to printf all the arguments in the message?

How can I print them all in order to have:

My info: Value1 = 1, Value 2=2

Upvotes: 3

Views: 6225

Answers (3)

Jeff Archer
Jeff Archer

Reputation: 79

Here is a printAll() that will do exactly as you would like...

#ifdef __cplusplus
#include <cstring>
#include <cstdio>
#include <cstdarg>
using namespace std;
#else
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#endif



void printAll(const char* fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    const size_t MAX_LEN = 1023;
#ifdef __cplusplus
    char msg[MAX_LEN+1] = {0};
#else
    char msg[MAX_LEN+1];
    for (int i = 0; i < MAX_LEN+1; i++)
    {
       msg[i] = 0;
    }
#endif
    vsnprintf(msg, MAX_LEN, fmt, ap);
    printf("%s\n", msg);
    va_end(ap);
}

int main() {
    printAll("My info: Value1 = %d, Value 2=%d", 1, 2);
    return 0;
}

My info: Value1 = 1, Value 2=2

Upvotes: 1

Jerry Coffin
Jerry Coffin

Reputation: 490108

Here's a sketch of the general idea (though a finished version, has to deal with quite a few more things such as field width, precision, more conversions, etc.

#include <stdarg.h>
#include <stdio.h>
#include <string.h>

int my_vfprintf(FILE *file, char const *fmt, va_list arg) {

    int int_temp;
    char char_temp;
    char *string_temp;
    char ch;
    int length = 0;

    char buffer[512];

    while ( ch = *fmt++) {
        if ( '%' == ch ) {
            switch (ch = *fmt++) {
                /* %% - print out a single %    */
                case '%':
                    fputc('%', file);
                    length++;
                    break;

                /* %c: print out a character    */
                case 'c':
                    char_temp = va_arg(arg, int);
                    fputc(char_temp, file);
                    length++;
                    break;

                /* %s: print out a string       */
                case 's':
                    string_temp = va_arg(arg, char *);
                    fputs(string_temp, file);
                    length += strlen(string_temp);
                    break;

                /* %d: print out an int         */
                case 'd':
                    int_temp = va_arg(arg, int);
                    itoa(int_temp, buffer, 10);
                    fputs(buffer, file);
                    length += strlen(buffer);
                    break;

                /* %x: print out an int in hex  */
                case 'x':
                    int_temp = va_arg(arg, int);
                    itoa(int_temp, buffer, 16);
                    fputs(buffer, file);
                    length += strlen(buffer);
                    break;
            }
        }
        else {
            putc(ch, file);
            length++;
        }
    }
    return length;
}

int my_printf(char const *fmt, ...) {
    va_list arg;
    int length;

    va_start(arg, fmt);
    length = my_vfprintf(stdout, fmt, arg);
    va_end(arg);
    return length;
}

int my_fprintf(FILE *file, char const *fmt, ...) {
    va_list arg;
    int length;

    va_start(arg, fmt);
    length = my_vfprintf(file, fmt, arg);
    va_end(arg);
    return length;
}


#ifdef TEST 

int main() {
    my_printf("%s", "Some string");
    return 0;
}

#endif

Upvotes: 1

FatalError
FatalError

Reputation: 54551

You're looking for the vprintf() function which was designed to do exactly this:

vprintf(message, argptr);

The v*printf() family of functions work basically in the same way as their normal counterparts, except they take a va_list instead of varargs. They don't call va_end() for you, so the way you have it now is correct.

Upvotes: 15

Related Questions