Create my_printf that sends data for both sprintf and regular printf?

I play with printf, and the idea is to write my_printf (...), which calls regular printf and sprintf, which sends the result to a special function. (I was thinking about sprintf, since it behaves the same as printf on most platforms).

My idea was to write a little macro that did this:

#define my_printf (X, Y ...) do {printf (X, ## Y); \
    char * data = malloc (strlen (X) * sizeof (char)); \
    sprintf (data, X, ## Y); \
    other_print (data); \
    free (data);} while (0)

But since sprintf can expand the string to a much larger size than X, this method breaks almost directly.

And just to add a number, malloc seems like the wrong way to attack the problem, since then I would just move the problem to the future and the day I want to print a large expression ...

Does anyone have a better idea on how to attack this problem? Or how can I find out how big the sprintf result will be?

Thanks Johan


Update: I forgot that printf returns the number of characters it prints, and since I already call printf in the macro, it was very easy to add an int that stores the number.

#define buf_printf (X, Y ...) do {int len ​​= printf (X, ## Y); \
    char * data = malloc ((len + 1) * sizeof (char)); \
    sprintf (data, X, ## Y); \
    other_print (data); \
    free (data);} while (0)

: , , , . , -, v- printf (vprintf, vsprintf vsnprintf). , .

Johan

+3
4

- varargs. , printf(), varargs sprintf, , printf ( "% s" ) .

4K printf() , , . , , .

, , , printf() /dev/null. printf() , . , printf() - .

+5

snprintf . man:

" - , ( '\ 0'), , "

snprintf C99. C89, : . , man, glibc 2.1 -1, , .

, sizeof (char) 1 C: -)

+8

Linux, asprintf() - GNU, . C99 varagrs.

, :

#define MY_PRINT(...) do { \
                          char *data; \
                          asprintf(&data, __VA_ARGS__); \
                          printf("%s", data); \
                          other_print(data); \
                          free(data); \
                      } while (0)

NB! C99 GNU

: , - ( "% d", ++) .

+5

glibc (, Linux GNU userland), asprintf , sprintf, .

int my_printf(const char *fmt, ...) {
    char *buf = NULL;
    int len;
    va_list ap;

    va_start(ap, &fmt);
    len = vasprintf(&buf, fmt, ap);
    va_end(ap);

    if (len < 0) {
        /* error: allocation failed */
        return len;
    }

    puts(buf);
    other_print(buf);

    free(buf);
    return len;
}

Pax , ​​ /dev/null : POSIX, snprintf NULL 0, , - , , .

int my_printf(const char *fmt, ...) {
    char *buf;
    int len, len2;
    va_list ap;

    va_start(ap, &fmt);
    len = vsnprintf(NULL, 0, fmt, ap);
    va_end(ap);

    buf = malloc(len + 1);
    if (!buf) {
        /* error: allocation failed */
        return -1;
    }

    va_start(ap, &fmt);
    len2 = snprintf(buf, len + 1, fmt, ap);
    buf[len] = '\0';
    va_end(ap);

    /* has another thread been messing with our arguments?
       oh well, nothing we can do about it */
    assert(len == len2);

    puts(buf);
    other_printf(buf);

    free(buf);
    return len;
}

, , snprintf. ...

+2

Source: https://habr.com/ru/post/1702524/


All Articles