sprintf、snprintf、vsprintf、asprintf、vasprintf函数

发布时间 2023-10-13 20:48:53作者: UFOFCZ

1. sprintf

extern int sprintf (char *__restrict __s,
                    const char *__restrict __format, ...);

2. snprintf

/* Maximum chars of output to write in MAXLEN.  */
extern int snprintf (char *__restrict __s, size_t __maxlen,
                     const char *__restrict __format, ...);

3. vprintf

/* Write formatted output to stdout from argument list ARG.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int vprintf (const char *__restrict __format, _G_va_list __arg);

4. vsprintf

https://www.runoob.com/cprogramming/c-function-vsprintf.html
vsprintf将格式化后的字符串输出到一个已经分配好的缓冲区中,需要手动指定缓冲区的大小

/* Write formatted output to S from argument list ARG.  */
extern int vsprintf (char *__restrict __s, const char *__restrict __format,
                     _G_va_list __arg) __THROWNL;

5. vsnprintf

int vsnprintf (char *__restrict __s, size_t __maxlen,
                      const char *__restrict __format, _G_va_list __arg);

6. asprintf

vasprintf会自动分配足够大的缓冲区来存储格式化后的字符串,并将指向该缓冲区的指针作为返回值。

int asprintf (char **__restrict __ptr,
                     const char *__restrict __fmt, ...)


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


// int dsl_append_sprintf(char **strp, const char *fmt, ...)
// {
//     va_list args;
//     int     len;

//     va_start(args, fmt);
//     len = vsnprintf(NULL, 0, fmt, args);
//     printf("%d\n", len);
//     if (len < 0) {
//         va_end(args);
//         return -1;
//     }

//     *strp = malloc(len + 1);
//     if (*strp == NULL) {
//         va_end(args);
//         return -1;
//     }

//     va_start(args, fmt);
//     len = vsnprintf(*strp, len + 1, fmt, args);
//     va_end(args);

//     if (ret < 0) {
//         free(*strp);
//         return -1;
//     }
//     return len;
// }

int dsl_append_sprintf(char **buf, const char *fmt, ...)
{
    // va_list ap;
    // va_start(ap, fmt);
    // *buf = NULL;
    // int count = vsnprintf(NULL,  0, fmt, ap);
    // if (count >= 0) {
    //     char *buffer = malloc(count + 1);
    //     if (buffer != NULL) {
    //         buffer[count] = 0;
    //         count = vsnprintf(buffer,  count + 1, fmt, ap);
    //         if (count < 0) {
    //             free(buffer);
    //         } else {
    //             *buf = buffer;
    //         }
    //     }
    // }
    // va_end(ap);
    // return count;
    // char   *message;

    va_list ap;
    va_start(ap, fmt);
    int ret = vsnprintf(NULL,  0, fmt, ap);
    printf("xxxx ret=%d\n", ret);
    // if (vasprintf(buf, fmt, ap) < 0) {
    //     *buf = NULL;
    // }
    va_end(ap);
    *buf = malloc(ret + 1);
    *buf[ret] = 0;
    // va_list ap2;
    va_start(ap, fmt);
    ret = vsprintf(*buf, fmt, ap);
    printf("xxxx 2 ret=%d\n", ret);
    // if (vasprintf(buf, fmt, ap) < 0) {
    //     *buf = NULL;
    // }
    va_end(ap);
    return 0;
}

// char *buffer;//[80];
// int vspfunc(char *format, ...)
// {
//    va_list aptr;
//    int ret;

//    va_start(aptr, format);
//    buffer = malloc(80);
//    ret = vsprintf(buffer, format, aptr);
//    va_end(aptr);

//    return(ret);
// }

int main()
{
//    int i = 5;
//    float f = 27.0;
//    char str[50] = "runoob.com";

//    vspfunc("%d %f %s", i, f, str);
//    printf("%s\n", buffer);
    char *buffer;
    const char* name = "John";
    int age = 25;

    dsl_append_sprintf(&buffer, "My name is %s and I am %d years old.\n", name, age);
    printf("%s", buffer);

    return 0;
}

7. vasprintf

/* Write formatted output to a string dynamically allocated with `malloc'.
   Store the address of the string in *PTR.  */
extern int vasprintf (char **__restrict __ptr, const char *__restrict __f,
                      _G_va_list __arg)

8. fprintf

/* Write formatted output to STREAM.
   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int fprintf (FILE *__restrict __stream,
                    const char *__restrict __format, ...);

9. vfprintf

/* Write formatted output to S from argument list ARG.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern int vfprintf (FILE *__restrict __s, const char *__restrict __format,
                     _G_va_list __arg);

10. vdprintf

/* Write formatted output to a file descriptor.  */
extern int vdprintf (int __fd, const char *__restrict __fmt,
                     _G_va_list __arg)

https://www.cnblogs.com/ph829/p/4089837.html

freopen() https://www.runoob.com/cprogramming/c-function-freopen.html
https://www.cnblogs.com/bonelee/p/6568011.html
https://blog.csdn.net/choumin/article/details/114459238 fmemopen和open_memstream
https://blog.csdn.net/drdairen/article/details/51912828
https://www.cnblogs.com/sunbines/p/17508753.html

int dsl_debug;
#define F_EOF  16
#define F_NORD 4
#define F_NOWR 8
#define UNGET  8

struct _dsl_io_file {
    unsigned       flags;
    unsigned char *rpos, *rend;
    int (*close)(FILE *);
    unsigned char *wend, *wpos;
    unsigned char *mustbezero_1;
    unsigned char *wbase;
    size_t (*read)(FILE *, unsigned char *, size_t);
    size_t (*write)(FILE *, const unsigned char *, size_t);
    off_t (*seek)(FILE *, off_t, int);
    unsigned char          *buf;
    size_t                  buf_size;
    FILE                   *prev, *next;
    int                     fd;
    int                     pipe_pid;
    long                    lockcount;
    int                     mode;
    volatile int            lock;
    int                     lbf;
    void                   *cookie;
    off_t                   off;
    char                   *getln_buf;
    void                   *mustbezero_2;
    unsigned char          *shend;
    off_t                   shlim, shcnt;
    FILE                   *prev_locked, *next_locked;
    struct __locale_struct *locale;
};
typedef struct _dsl_io_file DSL_FILE;

struct cookie {
    size_t         pos, len, size;
    unsigned char *buf;
    int            mode;
};

typedef struct _dsl_mem_FILE {
    DSL_FILE      fptr;
    struct cookie coki;
    unsigned char buf[UNGET + BUFSIZ], buf2[];
} mem_FILE_t;

static off_t mseek(FILE *std_f, off_t off, int whence)
{
    DSL_FILE      *f = (DSL_FILE *)std_f;
    ssize_t        base;
    struct cookie *c = f->cookie;
    if (whence > 2) {
        goto fail;
    }
    base = (size_t[3]){0, c->pos, c->len}[whence];
    if (off < -base || off > (ssize_t)c->size - base) {
        goto fail;
    }
    return c->pos = base + off;
fail:
    errno = EINVAL;
    return -1;
}

static size_t mread(FILE *std_f, unsigned char *buf, size_t len)
{
    DSL_FILE      *f = (DSL_FILE *)std_f;
    struct cookie *c = f->cookie;
    size_t         rem = c->len - c->pos;
    if (c->pos > c->len) {
        rem = 0;
    }
    if (len > rem) {
        len = rem;
        f->flags |= F_EOF;
    }
    (void)memcpy_s(buf, len, c->buf + c->pos, len);
    c->pos += len;
    rem -= len;
    if (rem > f->buf_size) {
        rem = f->buf_size;
    }
    f->rpos = f->buf;
    f->rend = f->buf + rem;
    (void)memcpy_s(f->rpos, len, c->buf + c->pos, rem);
    c->pos += rem;
    return len;
}

static size_t mwrite(FILE *std_f, const unsigned char *buf, size_t len)
{
    DSL_FILE      *f = (DSL_FILE *)std_f;
    struct cookie *c = f->cookie;
    size_t         rem;
    size_t         len2 = f->wpos - f->wbase;
    if (len2) {
        f->wpos = f->wbase;
        if (mwrite((FILE *)f, f->wpos, len2) < len2) {
            return 0;
        }
    }
    if (c->mode == 'a') {
        c->pos = c->len;
    }
    rem = c->size - c->pos;
    if (len > rem) {
        len = rem;
    }
    (void)memcpy_s(c->buf + c->pos, len, buf, len);
    c->pos += len;
    if (c->pos > c->len) {
        c->len = c->pos;
        if (c->len < c->size) {
            c->buf[c->len] = 0;
        } else if ((f->flags & F_NORD) && c->size) {
            c->buf[c->size - 1] = 0;
        }
    }
    return len;
}

static int mclose(EBPF_UNUSED FILE *m)
{
    return 0;
}

FILE *dsl_fmemopen(void *restrict buf, size_t size, const char *restrict mode)
{
    mem_FILE_t *f;
    int         plus = !!strchr(mode, '+');

    if (!strchr("rwa", *mode)) {
        errno = EINVAL;
        return 0;
    }

    if (!buf && size > PTRDIFF_MAX) {
        errno = ENOMEM;
        return 0;
    }

    f = malloc(sizeof *f + (buf ? 0 : size));
    if (!f) {
        return 0;
    }
    (void)memset_s(f, sizeof(mem_FILE_t), 0, offsetof(mem_FILE_t, buf));
    f->fptr.cookie = &f->coki;
    f->fptr.fd = -1;
    f->fptr.lbf = EOF;
    f->fptr.buf = f->buf + UNGET;
    f->fptr.buf_size = sizeof f->buf - UNGET;
    if (!buf) {
        buf = f->buf2;
        (void)memset_s(buf, size, 0, size);
    }

    f->coki.buf = buf;
    f->coki.size = size;
    f->coki.mode = *mode;

    if (!plus) {
        f->fptr.flags = (*mode == 'r') ? F_NOWR : F_NORD;
    }
    if (*mode == 'r') {
        f->coki.len = size;
    } else if (*mode == 'a') {
        f->coki.len = f->coki.pos = strnlen(buf, size);
    } else if (plus) {
        *f->coki.buf = 0;
    }

    f->fptr.read = mread;
    f->fptr.write = mwrite;
    f->fptr.seek = mseek;
    f->fptr.close = mclose;

    return (FILE *)&f->fptr;
}

void *dsl_reallocate(void *memory, size_t old_size, size_t new_size)
{
    void *new_memory = (void *)malloc(new_size);
    if (new_memory == NULL) {
        DSL_LOG_ERR("malloc failed!");
        return NULL;
    }
    if (old_size > 0) {
        if (memcpy_s(new_memory, new_size, memory, old_size) != 0) {
            DSL_LOG_ERR("memcpy_s failed!");
            return NULL;
        }
        if (memory != NULL) {
            free(memory);
        }
    }
    if (new_size > old_size) {
        (void)memset_s(((char *)new_memory) + old_size, new_size - old_size, 0, new_size - old_size);
    }
    return new_memory;
}

int dsl_append_sprintf(char **buf, const char *fmt, ...)
{
    // va_list ap;
    // va_start(ap, fmt);
    // if (vasprintf(buf, fmt, ap) < 0) {
    //     *buf = NULL;
    // }
    // va_end(ap);
    // return 0;
    *buf = NULL;
    va_list ap;
    va_start(ap, fmt);
    int count = vsnprintf(NULL,  0, fmt, ap);
    va_end(ap);
    if (count < 0) {
        return count;
    }

    char *buffer = malloc(count + 1);
    if (buffer == NULL) {
        return -1;
    }
    buffer[count] = 0;

    va_start(ap, fmt);
    count = vsnprintf(buffer,  count + 1, fmt, ap);
    if (count < 0) {
        free(buffer);
    } else {
        *buf = buffer;
    }
    va_end(ap);
    return count;
}