Concatenating multiple strings into single string while preserving terminating NULL

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Markus
    Recognized Expert Expert
    • Jun 2007
    • 6092

    Concatenating multiple strings into single string while preserving terminating NULL

    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:
    Code:
    var full_string // empty
    
    foreach strings as string:
        reallocate memory for string based on full_string's length and string's length multiplied by sizeof char.
        concatenate string to empty_string using strcat.
    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.
  • donbock
    Recognized Expert Top Contributor
    • Mar 2008
    • 2427

    #2
    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.

    Comment

    • Markus
      Recognized Expert Expert
      • Jun 2007
      • 6092

      #3
      Yo, Donbock.

      Here's a quick try; it works, but I could use your expert's eye:
      Code:
      int main (int argc, char *argv[])
      {
      	char *names_string  = NULL;
      	char *names_array[] = {
      		"mark", "jeff", "josh"
      	};
      	int elements_count = sizeof names_array / sizeof(char *),
      		i, offset = 0;
      
      	for (i = 0; i < elements_count; i++)
      	{
      		/* Include terminating NULL */
      		int name_len = strlen(names_array[i]) + 1;
      		
      		names_string = realloc(names_string, offset + name_len);
      		memcpy(names_string + offset, names_array[i], name_len);
      		
      		offset += name_len;
      	}
      	
      	names_string[offset] = '\0';
      	
      	while (*names_string)
      	{
      		printf("name: %s\n", names_string);
      		names_string += strlen(names_string) + 1;
      	}
      
      	return 0;	
      }

      Comment

      • donbock
        Recognized Expert Top Contributor
        • Mar 2008
        • 2427

        #4
        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_a rray[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.
        Last edited by donbock; Nov 11 '10, 04:07 PM. Reason: Had the const explanations for Line 4 backwards.

        Comment

        • Markus
          Recognized Expert Expert
          • Jun 2007
          • 6092

          #5
          Very much appreciated, Donbock. :)

          Comment

          Working...