By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,952 Members | 1,450 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,952 IT Pros & Developers. It's quick & easy.

Concatenating multiple strings into single string while preserving terminating NULL

Markus
Expert 5K+
P: 6,050
Hi, guys.

I'm receiving a dynamic amount of strings and from these strings I need to make a single string containing them all. However, I need to preserve the NULL characters to separate the strings. If you see this page of documentation and scroll down to the REG_MULTI_SZ entry, you'll see the layout of the string needed.

My thoughts on how I would go about this are:
Expand|Select|Wrap|Line Numbers
  1. var full_string // empty
  2.  
  3. foreach strings as string:
  4.     reallocate memory for string based on full_string's length and string's length multiplied by sizeof char.
  5.     concatenate string to empty_string using strcat.
  6.  
The trouble is then how do I include the terminating nulls, and once again for the final null (the string should be terminated with 2)?

I'll give you what I've tried when I have some time.

Mark.
Nov 10 '10 #1

✓ answered by donbock

This will be a merciless code review. Remember that most of the comments will be stylistic; hence reasonable people may differ.
  1. Line 4. Suggest using "static const char * const" instead of "char *". Static makes this a static variable rather than an automatic variable; the initialization occurs once, not each time the function is called. The second const makes the array elements constant (you can't change them to point at other strings). The first const prevents you from changing the strings themselves via names_array.
  2. Line 7. Split off the definition of elements_count into its own line. Then you can use "static const int" for elements_count instead of "int". Use of static and const here is for the same reasons described above for line 4.
  3. Line 7. Change elements_count initializer such that the denominator is "sizeof(names_array[0])" instead of "sizeof(char*)". This relieves you of the responsibility to keep track of the type of the array elements.
  4. Line 15. You should check if realloc failed.
  5. Line 21. You didn't realloc names_string to make room for the terminating null. (Don't forget to check for failure if you call realloc again.)
Only the last two comments are definite problems.

Share this Question
Share on Google+
4 Replies


Expert 100+
P: 2,396
The output is not itself a string because it contains embedded null characters. You need to allocate a memory buffer big enough to hold all of the strings, including all necessary null characters. Then you can copy each string to the output buffer using either memcpy or strcpy, just be sure to offset the destination address to point where the next multi-string should go.
Nov 11 '10 #2

Markus
Expert 5K+
P: 6,050
Yo, Donbock.

Here's a quick try; it works, but I could use your expert's eye:
Expand|Select|Wrap|Line Numbers
  1. int main (int argc, char *argv[])
  2. {
  3.     char *names_string  = NULL;
  4.     char *names_array[] = {
  5.         "mark", "jeff", "josh"
  6.     };
  7.     int elements_count = sizeof names_array / sizeof(char *),
  8.         i, offset = 0;
  9.  
  10.     for (i = 0; i < elements_count; i++)
  11.     {
  12.         /* Include terminating NULL */
  13.         int name_len = strlen(names_array[i]) + 1;
  14.  
  15.         names_string = realloc(names_string, offset + name_len);
  16.         memcpy(names_string + offset, names_array[i], name_len);
  17.  
  18.         offset += name_len;
  19.     }
  20.  
  21.     names_string[offset] = '\0';
  22.  
  23.     while (*names_string)
  24.     {
  25.         printf("name: %s\n", names_string);
  26.         names_string += strlen(names_string) + 1;
  27.     }
  28.  
  29.     return 0;    
  30. }
  31.  
Nov 11 '10 #3

Expert 100+
P: 2,396
This will be a merciless code review. Remember that most of the comments will be stylistic; hence reasonable people may differ.
  1. Line 4. Suggest using "static const char * const" instead of "char *". Static makes this a static variable rather than an automatic variable; the initialization occurs once, not each time the function is called. The second const makes the array elements constant (you can't change them to point at other strings). The first const prevents you from changing the strings themselves via names_array.
  2. Line 7. Split off the definition of elements_count into its own line. Then you can use "static const int" for elements_count instead of "int". Use of static and const here is for the same reasons described above for line 4.
  3. Line 7. Change elements_count initializer such that the denominator is "sizeof(names_array[0])" instead of "sizeof(char*)". This relieves you of the responsibility to keep track of the type of the array elements.
  4. Line 15. You should check if realloc failed.
  5. Line 21. You didn't realloc names_string to make room for the terminating null. (Don't forget to check for failure if you call realloc again.)
Only the last two comments are definite problems.
Nov 11 '10 #4

Markus
Expert 5K+
P: 6,050
Very much appreciated, Donbock. :)
Nov 11 '10 #5

Post your reply

Sign in to post your reply or Sign up for a free account.