在具有可变数量参数的函数中将文本与数字连接起来

时间:2011-10-27 13:56:26

标签: c type-conversion variadic-functions

我在C中创建了一个函数,它连接了可变数量的字符串。 那是我的代码:

char* texto(const char* s, ...){
        va_list args;
        char *tmp;
        char *res;
        size_t len = strlen(s);

        // pega um handle ao início da lista de parâmetros
        va_start(args, s);
        // calcula o tamanho total de todas as strings - pega o próximo parâmetro da lista, até chegar no NULL
        while ((tmp = va_arg(args, char*))){
            len += strlen(tmp);
        }
        va_end(args);

        res = malloc(len+1);
        if (!res){
                fprintf(stderr, "Erro ao alocar string. Função 'texto'\n");
                exit(EXIT_FAILURE);
        }

        // cria a string concatenada
        strcpy(res, s);

        va_start(args, s);
        // pega o próximo parâmetro da lista, até chegar no NULL
        while ((tmp  = va_arg(args, char*))){ 
            strcat(res, tmp); 
        }
        va_end(args);

        return res;
}

我正在使用这样:

char* txt = texto("a", "b", "c", "d", "e", NULL);
//txt is now: "abcde"

工作正常。 但我无法将数字参数传递给此函数,只能传递字符串。 我需要将功能更改为这样:

char* txt = texto("a", "b", 1, "d", 4.5, "e", NULL);
//txt is now: "ab1d4.5e"

我该怎么做? 我如何使用va_arg()获取不同类型的参数?

我到目前为止找到的解决方案是创建一个函数int2str():

inline char* int2str(int inteiro){
    char* str = malloc(10);
    sprintf(str, "%d", inteiro);
    return str;
}

但我必须这样使用:

char* txtnum = int2str(23);
char* txt = texto("a", txtnum, NULL);
free(txtnum);

否则,我的内存泄漏......

我可以在函数texto()中使用函数int2str()但我不知道如何检查参数的类型!

Ps。:我的代码使用C而不是C ++。

2 个答案:

答案 0 :(得分:0)

  

我该怎么做?我如何使用va_arg()获取不同类型的参数?

不幸的是,这是不可能的,当您使用可变参数列表时,类型信息会丢失。

一个非常简单的解决方案是使用声明“类型”的格式字符串,但话又说明为什么不简单地使用标准函数snprintfReference here

char buffer[256];
snprintf(buffer, sizeof(buffer), "%s%s%d%s%f%s", "a", "b", 1, "d", 4.5, "e", NULL);

答案 1 :(得分:0)

如果您愿意采用特定于gcc的解决方案,可以将int2str更改为此宏:

# define int2str(i)                                                           \
  (__extension__                                                              \
    ({                                                                        \
      char *new = (char *) __builtin_alloca (10);                        \
      sprintf(new, "%d", i); \
      new;                                  \
    }))

这意味着你可以写:

char* txt = texto("a", int2str(23), NULL);

没有泄漏。它的非常非便携式。