从数量可变的参数构建字符串 #包括 #包括 #包括 #包括 int main(int argc,char*argv[]) { char*arr[]={“ab”、“cd”、“ef”}; 字符**ptr,**p,*str; int num=3; int size=0; ptr=calloc(num,4); p=ptr; 对于(;num>0;num--) 大小+=strlen(*(p++)=arr[num-1]); str=calloc(1,+尺寸); sprintf(str,“%s%s%s”,ptr[0],ptr[1],ptr[2]); printf(“%s\n”,str); 返回0; }

从数量可变的参数构建字符串 #包括 #包括 #包括 #包括 int main(int argc,char*argv[]) { char*arr[]={“ab”、“cd”、“ef”}; 字符**ptr,**p,*str; int num=3; int size=0; ptr=calloc(num,4); p=ptr; 对于(;num>0;num--) 大小+=strlen(*(p++)=arr[num-1]); str=calloc(1,+尺寸); sprintf(str,“%s%s%s”,ptr[0],ptr[1],ptr[2]); printf(“%s\n”,str); 返回0; },c,arrays,string,pointers,printf,C,Arrays,String,Pointers,Printf,输出:“efcdab”如预期 现在,如果sprintf的参数计数是预先确定和已知的,那么这一切都是好的和合适的。但是,如果参数计数是可变的(ptr[any]),我试图实现的是一种优雅的方式来构建字符串 第一个问题:需要传递给sprintf的第二个参数是const char*格式 第二:第三个参数是根据提供的格式构建字符串所传递的参数的实际数量 我如何实现以下目标: sprintf(str,“…”,…) 基本上,如果函数接收到4个(或更多)字符指针,我想从中构建一个完整的字符串(目前,在上面提供的

输出:
“efcdab”
如预期

现在,如果
sprintf
的参数计数是预先确定和已知的,那么这一切都是好的和合适的。但是,如果参数计数是可变的(
ptr[any]
),我试图实现的是一种优雅的方式来构建字符串

第一个问题:需要传递给
sprintf
的第二个参数是
const char*格式

第二:第三个参数是根据提供的
格式
构建字符串所传递的参数的实际数量

我如何实现以下目标:

sprintf(str,“…”,…)

基本上,如果函数接收到4个(或更多)字符指针,我想从中构建一个完整的字符串(目前,在上面提供的代码中,只有3个)。这意味着,第二个参数必须(至少)采用
“%s%s%s”
的形式,后跟
ptr[0]、ptr[1]、ptr[2]、ptr[3]
的参数列表

首先,如何对
sprintf
(或
vsprintf
)进行这样的“组合”调用?如果我可以提供一个完整的指针数组(**ptr)作为第三个参数,事情就会变得更简单。。但这似乎不可行?至少,
sprintf
似乎无法理解它。。因为它需要一些特殊形式的
格式


想法/建议?

karlphillip的
strcat
建议似乎是这里的解决方案。或者更确切地说,您更可能希望使用类似于
strncat
(不过,如果您使用的是支持它的C库,我建议使用
strlcat
,在我看来,这比
strncat
要好得多)

因此,不是
sprintf(str,“%s%s%s”,ptr[0],ptr[1],ptr[2]),您可以执行以下操作:

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


int main(int argc, char * argv[])
{
    char *arr[] = { "ab", "cd", "ef" };
    char **ptr, **p, *str;
    int num = 3;
    int size = 0;

    ptr = calloc(num, 4);
    p = ptr;

    for (; num > 0; num--)
            size += strlen(*(p++) = arr[num - 1]);

    str = calloc(1, ++size);
    sprintf(str, "%s%s%s", ptr[0], ptr[1], ptr[2]);

    printf("%s\n", str);

    return 0;
}
inti;
对于(i=0;i

(或者
strlcat(str,arr[i],size);
strlcat
的好处是,如果目标缓冲区太小,它的返回值将指示重新分配需要多少字节,但它不是标准的C函数,很多系统都不支持它。)在C中,没有其他方法可以在不操纵缓冲区的情况下执行此操作


但是,您可以切换到C++并使用出色的
std::string
使您的生活更轻松。

您的第一个问题由以下人员处理:
const char*
是函数的问题,而不是您的问题。把你自己的字符串放在一起——这个签名仅仅意味着函数不会改变它

您的第二个问题由以下人员处理:传入您自己的va_列表。你是怎么得到的?创建自己的varargs函数:

int i;

for (i = 0; i < any; i++)
    strncat(str, arr[i], size - strlen(str) - 1);
char*汇编_字符串(整数计数,…)
{
va_列表数据_列表;
va_列表len_列表;
整数大小;
char*arg;
char*formatstr;
char*str;
int i;
va_开始(len_列表、计数);
对于(i=0,size=0;i

当然,您需要某种方法来终止varargs,如果字符串列表完全在varargs中,那么将其传递给vsprintf就容易得多了,因为标准C至少需要一个常规参数。

我将用于最后复制到str中的循环类似于:

char *assemble_strings(int count, ...)
{
    va_list data_list;
    va_list len_list;
    int size;
    char *arg;
    char *formatstr;
    char *str;
    int i;

    va_start(len_list, count);
    for (i = 0, size = 0; i < count; i++)
    {
        arg = va_arg(len_list, char *);
        size += strlen(arg);
    }
    va_end(len_list);

    formatstr = malloc(2*count + 1);
    formatstr[2*count] = 0;
    for (i = 0; i < count; i++)
    {
        formatstr[2*i] = '%';
        formatstr[2*i+1] = 's';
    }
    str = malloc(size + 1);

    va_start(data_list, count);
    vsprintf(str, formatstr, data_list);
    va_end(data_list);

    free(formatstr);

    return(str);
}
for(i=0,p=str;i

for(i=0,p=str;i

而不是试图在一次对sprintf的调用中处理数量可变的参数。

主要的问题似乎是sprintf没有做你想做的事情。你听说过strcat吗?@karlphillip:这就是我提到“优雅”的原因,字符串复制解决方案依赖于缓冲区操作。问这个问题的全部目的是为了避免这种行为,并利用某种“分组”。我确实有一个答案。。。切换到C++,使用<代码> STD::字符串< /代码>!但是你在这里做的技术上也是缓冲区操作,不是吗?您的
str
变量在这里充当目标缓冲区。@贾布:我们不要卷入语义争论。是的,当然是。我想你已经完全明白我说的那句话的意思了。如果你对我指定的目标有一个更好的
术语
,我会很高兴听到的。或者人们可以避免添加毫无意义和无用的评论,就像切换到其他东西一样。但是,如果这是正确的并且确实不可能的话,感谢您提供评论的另一部分。这里,
string.h
的一半可以作为解决方案。然而,我不确定这会有多大价值。因为我故意忽略了这种方法,希望有更好的方法。不过,我想我可以用strcat自己管理。如果有什么事情发生,你能找到更好的方法,请告诉我;)您可以创建自己的函数库,支持分段字符串并忽略
for(i=0, p=str; i < num; i++)
    p += sprintf(p, "%s", ptr[i]);
for(i=0, p=str; i < num; i++)
    p += strlen(strcpy(p, ptr[i]));