考虑这个连接所有指定参数并在标准输出中打印它们的简单程序。我使用了 2 个 for 循环来附加字符串,一个用于计算该字符串的长度,一个用于连接字符串。有没有一种方法只用一个循环就可以做到这一点?为每个要连接的字符串重新分配内存不会更有效,不是吗? Java 的 StringBuilder 在 C 中如何实现?它会像我一样循环两次吗?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
size_t len = 0;
// start for loop at i = 1 to skip the program name specified in argv
for(int i = 1; i < argc; i++)
len += strlen(argv[i]) + 1; // +1 for the space
char* toAppend = (char*)malloc(len * sizeof(char) + 1);
toAppend[0] = '\0'; // first string is empty and null terminated
for(int i = 1; i < argc; i++)
{
strcat(toAppend, argv[i]);
strcat(toAppend, " ");
}
printf(toAppend);
free(toAppend);
}
最佳答案
您的分配方法很有效,测量总长度并只分配一次。但是连接循环从一开始就重复测量输出缓冲区的长度以连接到它,导致二次运行时间。
要修复它,请在您前进时跟踪您的位置:
size_t pos = 0;
for(int i = 1; i < argc; i++) {
size_t len = strlen(argv[i]);
memcpy(toAppend+pos, argv[i], len);
pos += len;
toAppend[pos] = ' ';
pos++;
}
toAppend[pos] = 0;
这是在内存中实际连接的最有效方法,但最有效的方法是不连接。相反:
for(int i = 1; i < argc; i++)
printf("%s ", argv[i]);
缓冲 stdio 的全部原因是您不必构建任意长度的内存缓冲区来进行高效输出;相反,它会自动缓冲到固定大小,并在缓冲区已满时刷新。
请注意,如果您的输入在任何地方包含 %
字符,您对 printf
的使用是错误和危险的;它应该是 printf("%s", toAppend);
。
如果您正在编写 POSIX(或 POSIX-ish)系统而不仅仅是普通的 C,另一个选项是 fmemopen
,它允许您像这样编写循环:
for(int i = 1; i < argc; i++)
fprintf(my_memfile, "%s ", argv[i]);
关于c - 在c中连接字符串的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52415807/