我需要将以下字符串存储在C:
中的3个char *变量中[foo]
[foo]:[bar]
[foo]:[bar]:[tat]
通过char *指针在一个时间点接收诸如“foo”的每个单独的字符串,在接收第二个字符串之前立即产生相应的输出字符串,并且始终知道各个字符串的总数。
可以有任意数量的字符串。
我编写了以下代码来打印字符串:
for(i=0;i<num;i++)
{
for(j=0;j<=i;j++)
{
printf("[%s]",str[j]);
if(j!=i)
{
printf(":");
}
else
{
printf("\n");
}
}
}
但是我无法想出一种在变量中存储所需输出字符串的方法,除了使用strcat()&amp ;;编写一个混乱的逐个案例函数。一些额外的自定义函数。
有没有办法做到这一点,看起来像打印字符串一样干净?
答案 0 :(得分:3)
这是一个内存管理和字符串处理在C中的繁琐问题。如果我认为对于n个输入字符串,你想要n个输出字符串,每个字符串都比最后一个更长,我会这样做:
char **results = malloc(num * sizeof(char*));
if (results == 0) return ENOMEM;
int lastlen = 0;
for (int i = 0; i < num; ++i) {
char *newresult = malloc(lastlen + strlen(str[i]) + 4);
if (newresult == 0) { /* even more tedious freeing code goes here */ }
results[i] = newresult;
char *ptr = newresult;
if (i != 0) {
ptr += sprintf(ptr, "%s:", results[i-1])
}
sprintf(ptr, "[%s]", str[i])
lastlen = strlen(newresult);
}
或类似的东西。显然,这里有一个很好的机会来编写多个函数,将这些字符串的生成与它们在数组中的存储分开。还有一个通常的论点,即我们如何在缓冲风险溢出风险中做得比sprintf
+心算术更好。
编辑:偷走了Oskar使用sprintf
。
另一个编辑:asprintf
的示例,可在GNU和BSD上使用。这包括繁琐的解放代码,成功路径实际上相当不错。成功时返回新分配的数组,出错时返回0。假设调用者知道num
,因此知道数组的长度:如果没有用,那么数组可能是空终止的。
char **results = malloc(num * sizeof(char*));
if (results != 0) {
const char *last = "";
const char *sep = "";
for (int i = 0; i < num; ++i) {
if (asprintf(results + i, "%s%s[%s]", last, sep, str[i]) == -1) break;
last = str[i];
sep = ":";
}
if (i == num) return results; // success!
// asprintf failed, so the value of results[i] is undefined
while (i != 0) free(results[--i]);
free(results);
}
return 0;
答案 1 :(得分:1)
您可以使用sprintf()
。以您的代码为例:
for(i=0;i<num;i++)
{
char s[N];
s[0] = '\0';
for(j=0;j<=i;j++)
{
sprintf(s+strlen(s),"[%s]",str[j]);
if(i!=j)
{
sprintf(s+strlen(s),":");
}
else
{
sprintf(s+strlen(s),"\n");
}
}
/* store 's' somewhere */
}
编辑:我不建议将此解决方案用于任何严肃的事情。但对于一个简单的应用程序,你只想完成它,它应该完成这项工作。只需要 N 足够大,或动态分配它以保存最大的字符串。
答案 2 :(得分:1)
您有两个不同的问题:确保您分配足够的空间以及创建字符串。
有很多方法可以平衡两者,但使用realloc()
可以非常简单。
这是一个检查并在需要时扩大缓冲区的解决方案。
权衡取决于代码复杂性与性能,例如:
strcpy()
与简单使用sprintf()
。我的版本
char *joinCmds( char* str[], /* The strings to concatenate */
int num ) /* the number of strings */
{
int len = 0, i, off = 0;
char *out = NULL, sep;
for(i=0; i<num; i++)
{
while (len < (off+4+strlen(str[i]))) {
len += 16384; /* Larger numbers wastes memory in for better performance */
out = realloc( out, len ); /* Warning: some 'realloc()' take 3 parameters */
/** Handle NULL (Out of Memory errors) */
}
sep = (i < (num-1)) ? ':' : '\n';
off += sprintf(&out[off], "[%s]%c", str[i], sep);
}
return out;
}
答案 3 :(得分:0)
strcpy的解决方案;使用sprintf也很容易。
char out[1000],*p=out; /* out with enough size */
int i=0;
/* num > 0 */
for(; i<num && (p+=strlen(strcpy(p,"]:["))) ; p+=strlen(strcpy(p,str[i++])) ) ;
strcpy(p,"]");
puts(out+2);