0

我正在寻找示例代码或如何改进下面的代码(IMO 非常慢,但这是我可以编写的)以最快的方式将 2D 数组转换为 achar*并将 a 复制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");
}

如何优化?

4

4 回答 4

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;
}

我根据我认为您要完成的操作进行了一些更改, join 的第一个参数是用于分隔组合字符串的字符分隔符,第二个是 arr 中的字符串数,第三个显然是数组。

代码应该编译并运行,输出“assdasd bgsfsdf asdasisc”,即我在填充数组进行测试时在键盘上捣碎的内容:P

于 2012-07-20T17:21:19.767 回答
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;
}
于 2012-07-20T16:49:28.583 回答
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);
}
于 2012-07-20T17:10:33.913 回答
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;
}
于 2012-07-20T17:16:58.660 回答