John
John

Reputation: 358

How do I concatenate the string elements of my array into a single string in C?

I have an array of strings and I would like to create a new string that is a concatenation of all the array elements. Any help is appreciated, thanks

Upvotes: 1

Views: 13162

Answers (3)

Michel Billaud
Michel Billaud

Reputation: 1816

There are two possible interpretations of your question:

  1. To fill a destination char array with the concatenation, or
  2. To (m)allocate a new (big enough) string and fill it with the concatenation

The second problem can obviously be reduced to the first one:

 char *concatenation_of(char *strings[], size_t number) {

     size_t sum;
     for (size_t i = 0; i < number; i++) {
           sum += strlen(strings[i]);
     }

     return strcatarray(malloc(sum + 1), strings, number);
 } 

So let's focus now on the concatenation of an array of strings into a destination area.

The naive version, using strcat:

char *strcatarray(char * dest, char *strings[], size_t number)
{
     dest[0] = '\0';
     for (size_t i = 0; i < number; i++) {
         strcat(dest, strings[i]);
     }
     return dest;
}

Despite its simplicity, this has a major drawback: the destination string gets larger and larger, and it takes more and more time to find where to append the next strings[i]. This is also a quadratic algorithm.

A small and easy fix is to keep the address of the terminating null char, and append there:

char *strcatarray(char * dest, char *strings[], size_t number) {
    char *target = dest;               // where to copy the next elements
    *target = '\0';
    for (size_t i = 0; i < number; i++) {
        strcat(target, strings[i]);
        target += strlen(strings[i]);   // move to the end
    };
    return dest;
}

Lastly, if you wish to "join" the string elements with some glue:

char *strjoinarray(char * dest, char *strings[], size_t number, char * glue) {
    size_t glue_length = strlen(glue);

    char *target = dest;               // where to copy the next elements
    *target = '\0';
    for (size_t i = 0; i < number; i++) {
        if (i > 0) {                   // need glue
            strcat(target, glue);
            target += glue_length;
        }
        strcat(target, strings[i]);
        target += strlen(strings[i]);   // move to the end
    };
    return dest;
}

Upvotes: 3

Abhishek Choubey
Abhishek Choubey

Reputation: 883

First of all make sure that the destination size if at least one more than, the size of all
the strings in the array taken together, otherwise you will end up writing the strings at
some random memory address which will not be accessible to you, and you might end up having
a segmentation fault.
Its better to use "strncat" than "strcat", the former will enable you to copy only the
intended number of bytes. Do not forget to append a null terminator after all the strings have been copied successfully.

Upvotes: 1

BLUEPIXY
BLUEPIXY

Reputation: 40145

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *concatenate(size_t size, char *array[size], const char *joint){
    size_t jlen, lens[size];
    size_t i, total_size = (size-1) * (jlen=strlen(joint)) + 1;
    char *result, *p;


    for(i=0;i<size;++i){
        total_size += (lens[i]=strlen(array[i]));
    }
    p = result = malloc(total_size);
    for(i=0;i<size;++i){
        memcpy(p, array[i], lens[i]);
        p += lens[i];
        if(i<size-1){
            memcpy(p, joint, jlen);
            p += jlen;
        }
    }
    *p = '\0';
    return result;
}

int main(){
    char *ss[] = { "first", "second", "last" };
    char *cat = concatenate(3, ss, "");
    puts(cat);
    free(cat);
    cat = concatenate(3, ss, ", ");
    puts(cat);
    free(cat);
    return 0;
}

Upvotes: 4

Related Questions