Reputation: 358
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
Reputation: 1816
There are two possible interpretations of your question:
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
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
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