将2D数组转换为char *数组并将char复制到字符串结尾的最快方法

我正在寻找一个示例代码或如何改进下面的代码(它是非常慢的IMO,但我可以写),以最快的方式将2D数组转换为char*并将char复制到它。

 char* join(int c, size_t arrsize, const char* arr[]) { char *buf, *tbuf, *val; size_t i, vsize, total; buf = malloc(1); for(i = total = 0; i < arrsize; ++i) { val = arr[i]; vsize = strlen(val); if((tbuf = realloc(buf, total + vsize + 2)) == NULL) { if(buf != NULL) free(buf); return NULL; } buf = tbuf; memcpy(buf + total, val, vsize); total += vsize; buf[total] = c; total += 1; } buf[total] = '\0'; return buf; } 

调用

 const char *foo[] = { "a", "b", "c"}; char *baa = join(' ', 2, foo); //abc if(baa) { printf("%s\n", baa); free(baa); } else { printf("No memory\n"); } 

如何优化?

我同意Shawn的观点,单一的malloc调用可能更有利。 在他发布答案时,我正在编写自己的代码:

 #include  #include  #include  char* join(char delimiter, size_t arrsize, const char* arr[]) { size_t i; size_t total; char* joined; for (i = total = 0; i < arrsize; i++) { if (arr[i] != NULL) total += strlen(arr[i]) + 1; // size of c-style string + delimiter } // Note that last delimiter will actually be null termination joined = (char*)malloc(sizeof(char) * total); if (joined != NULL) { // first character isn't guaranteed to be null termination // set it so strcat works as intended, just in case joined[0] = '\0'; for (i = 0; i < arrsize; i++) { if (arr[i] != NULL) { strcat(joined, arr[i]); if ((i + 1) != arrsize) strncat(joined, &delimiter, 1); } } return joined; } int main(int argc, char** argv) { const char* foo[] = { "aasdasd", "bgsfsdf", "asdasisc" }; char* baa = join(' ', 3, foo); if (baa != NULL) { printf("%s\n", baa); free(baa); } else { printf("No memory\n"); } return 0; } 

我根据我认为你想要完成的事情做了一些改变,第一个连接参数是用于分隔组合字符串的字符分隔符,第二个是arr中字符串的数量,第三个显然是数组。

代码应该编译运行,yeilding“assdasd bgsfsdf asdasisc”,也就是说,当我填充数组进行测试时,我在键盘上捣碎了:P

如果你可以在arr中绑定字符串的总大小(例如,2048)。 有了这个,您可以删除strcpy和strlen函数中迭代的开销:

 char* join(int c, size_t arrsize, const char* arr[]) { char *buffer; size_t i, vsize; char *b; buffer = malloc(2048); b = buffer; vsize = 0; for(i = 0; i < arrsize; ++i) { char *p = arr[i]; while (*p) { *b = *p; b++; p++; vsize++; } *b = c; b++; } buffer[vsize++] = '\0'; return realloc(buffer, vsize); } 
 #include  #include  #include  char* join(char c, size_t arrsize, const char* arr[]){ size_t i, total, len[arrsize]; char *buff, *ret; for(total=i=0;i 

您可以在arr上执行第一个循环来确定总长度,然后再调用malloc ,而不是重复调用realloc 。 之后,只需再次循环arr并使用正确的偏移调用memcpy

也许这样的事情(请注意,这是未经测试的 ,可能包含错误):

 /* join strings in arr with c as separator */ char* join(int c, size_t arrsize, const char* arr[]) { char *buf; size_t i, len, total = 0; /* determine total length of all strings */ for (i = 0; i < arrsize; ++i) { total += strlen(arr[i]); } /* allocate mem */ buf = malloc(total + arrsize); if (!buf) return NULL; /* copy in all strings from arr */ total = 0; for (i = 0; i < arrsize; ++i) { len = strlen(arr[i]); memcpy(buf + total, arr[i], len); total += len; /* append separator (or NUL if last string) */ buf[total++] = (i == arrsize-1) ? '\0' : c; } return buf; }