问题
I'm looking for an example code or how to improve the below code (that it's very slow IMO, but it's that I can write) to the fastest way to convert an 2D-array into a char*
and copy a char
to it.
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;
}
calling
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");
}
How can this be optimised?
回答1:
I agree with the Shawn, a single malloc call is probably more advantageous. I was writing up my own take on your code while he was posting his answer:
#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;
}
I made some changes depending on what I thought you were trying to accomplish, the first argument to join is the character delimiter used to separate combined strings, the second is the number of string in arr, and the third is obviously the array.
The code should compile and run, yeilding "assdasd bgsfsdf asdasisc", that is, what I mashed on my keyboard when populating the array to test :P
回答2:
If you can bound the total size of the strings in arr (e.g., 2048). With this you can remove the overhead of iterations in strcpy and strlen functions:
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:
#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;
}
回答4:
Instead of repeated calls to realloc
, you could do a first loop across arr
to determine the total length then call malloc
just the once. After that it's just a matter of looping through arr
again and doing calls to memcpy
with the correct offsets.
Something like this perhaps (note that this is untested and may contain errors):
/* 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;
}
来源:https://stackoverflow.com/questions/11583613/fastest-way-to-convert-2d-array-into-char-array-and-copy-a-char-into-end-of-str