我正在寻找一个示例代码或如何改进下面的代码(它是非常慢的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); //a b c
if(baa) {
printf("%s\n", baa);
free(baa);
} else {
printf("No memory\n");
}
如何优化?
答案 0 :(得分:1)
我同意Shawn,单个malloc调用可能更有利。在他发布答案的时候,我正在编写自己的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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
答案 1 :(得分:0)
而不是重复调用realloc
,您可以在arr
之间进行第一次循环以确定总长度,然后只调用一次malloc
。在此之后,只需再次循环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;
}
答案 2 :(得分:0)
如果你可以用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);
}
答案 3 :(得分:0)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* join(char c, size_t arrsize, const char* arr[]){
size_t i, total, len[arrsize];
char *buff, *ret;
for(total=i=0;i<arrsize;++i)
total+=(len[i]=strlen(arr[i]));
if(NULL==(ret=buff=(char*)malloc((total + arrsize)*sizeof(char))))
return NULL;
for(i=0;i<arrsize;++i){
memcpy(buff, arr[i], len[i]);
buff+=len[i];
*buff++=c;
}
*--buff='\0';
return ret;
}
int main(){
const char *foo[] = { "a", "b", "c"};
char *baa = join(' ', sizeof(foo)/sizeof(char*), foo); //a b c
if(baa) {
printf("\"%s\"\n", baa);
free(baa);
} else {
printf("No memory\n");
}
return 0;
}