从数量可变的参数构建字符串 #包括 #包括 #包括 #包括 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]));