2011-10-27 8 views
1

可変数の文字列を連結する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); 

はそうでない場合、私は、メモリリークを持って...

関数int2str()を関数texto()で使用することはできますが、パラメータのタイプをチェックする方法はわかりません。

Ps:私は自分のコードにC++を使用していません。

+1

"私はコードをC++ではなくCを使用しています。" 'inline'はC++キーワードであり、Cキーワードではありません。 – Constantinius

+0

gcc固有の解決策が受け入れられるでしょうか? – Flexo

+0

@ Constantinius - 私はC99も 'インライン'を追加したと思った? – Flexo

答えて

0

あなたはこのマクロであることをint2strを変更することができますgccの具体的な解決策を取って喜んでいる場合:

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

を漏らすことなく:

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

この後、あなたが書くことができることを意味します。 非常にですが、携帯ではありません。

+0

ありがとう@awoodland!このコードでは、私の実際のコードを問題なく保つことができます! この「__extension__」がどのように動作するかを調べるため、汎用ソリューションを見つけることができます。 Tnksの皆さん、助けてください! – vinigarcia87

0

どうすればいいですか? va_arg()を使用して異なる型のパラメータを取得する方法は?

残念ながら、これは可能ではありませんが、可変引数リストを使用しているときに型情報が失われます。

「型」を宣言する書式文字列を使用するのが簡単な解決策ですが、もう一度単純に標準機能snprintfを使用してください。 Reference here

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

に感謝@ Constantinius、snprintfは私の問題を解決します。 しかし、私は後で使うことができる、文字列を返す関数を探しています。それと同じように。 私は余分な変数やフリー()を使用することについて心配する必要はありません... – vinigarcia87

関連する問題