简体   繁体   中英

Realloc using stdarg

I'm trying to concatenate strings using stdarg ( library ) header, but I'm doing something wrong. There is a easier way to concatenate strings using realloc?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
void concatenaCodigo(char *string, char *format, ...){
    va_list args;
    va_start(args, format);
    int n = vsnprintf(NULL, 0, format, args);
    string = (char*) realloc (string, n);
    if (string != NULL) {
        printf("Realloc OK!\n");
        vsprintf(string, format, args);
        va_end(args);
    }
    else {
        free (string);
        puts ("Error (re)allocating memory");
        exit (1);
    }

}
int main(){
    char *codigoC = NULL;
    concatenaCodigo(codigoC, "Test%s%s","asd","asd");
    printf("%s\n", codigoC);
}

I made the changes. The code should look like the below? The concatenation is not working yet.

char* concatenaCodigo(char *format, ...){
    va_list args;
    va_start(args, format);
    int n = vsnprintf(NULL, 0, format, args);
    char * newString;
    newString = (char*) malloc(n);
    vsprintf(newString, format, args);
    va_end(args);
    return newString;
}
int main(){
    char *codigoC = NULL;
    codigoC = concatenaCodigo("Test%s%s", "asd", "asd");
    printf("%s\n", codigoC);
}

The problem in the revised code is that you're not resetting your va_list properly. You have:

char* concatenaCodigo(char *format, ...){
    va_list args;
    va_start(args, format);
    int n = vsnprintf(NULL, 0, format, args);
    char * newString;
    newString = (char*) malloc(n);
    vsprintf(newString, format, args);
    va_end(args);
    return newString;
}
int main(){
    char *codigoC = NULL;
    codigoC = concatenaCodigo("Test%s%s", "asd", "asd");
    printf("%s\n", codigoC);
}

You need:

char *concatenaCodigo(char *format, ...)
{
    va_list args;
    va_start(args, format);
    int n = vsnprintf(NULL, 0, format, args) + 1;  /* Note the +1! */
    va_end(args);                                  /* vsnprintf() 'uses up' args */
    char *newString = (char *) malloc(n);
    if (newString != 0)
    {
        va_start(args, format);                        /* Restart args */
        vsprintf(newString, format, args);
        va_end(args);
    }
    return newString;
}

int main(void)
{
    char *codigoC = concatenaCodigo("Test%s%s", "asd", "asd");
    if (codigoC != 0)
        printf("%s\n", codigoC);
    free(codigoC);
    return 0;
}

Note that <stdarg.h> is a header, not a library.

The pointer isn't passed by reference, so when you do:

void concatenaCodigo(char *string, char *format, ...){
    // ...
    string = (char*) realloc (string, n);
}

You're overwriting the pointer that was passed in, and never getting the new value out of the function.

concatenaCodigo should return the newly allocated string:

char* concatenaCodigo(char *format, ...) {
    // ...
    return string;
}

int main() {
    char *codigoC = concatenaCodigo("Test%s%s","asd","asd");
    printf("%s\n", codigoC);
}

Also, you should not call free(string) if realloc failed. You shouldn't pass a NULL pointer to free() .

To avoid losing the reference I changed the function to receive a pointer to char array.

void concatenaCodigo(char **message, char *format, ...)
{
    va_list args;
    va_start(args, format);
    int n = vsnprintf(NULL, 0, format, args) + 1;  /* Note the +1! */
    va_end(args);                                  /* vsnprintf() 'uses up' args */
    char *newString = (char *) malloc(n);
    if (newString != 0)
    {
        va_start(args, format);                        /* Restart args */
        vsprintf(newString, format, args);
        va_end(args);
    }
    *message = newString;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM