homior
homior

Reputation: 191

C - How to concatenate Strings without string.h and with dynamic memory allocation

I have to do an exercise and I have this structure given:

typedef struct {
    char *str;
    unsigned int len;
} String;

My Task is to write a String Concat which concats "Kartoffel" and "puffer" to "Kartoffelpuffer" (potato fritter).

String concat(String l, String r)

Both Strings l and r should not be changed after running the function. First I created the two Strings in the main:

String1 *l = malloc(sizeof(String1));
String1 *r = malloc(sizeof(String1));
(*l).str = malloc(sizeof("Kartoffel"));
(*r).str = malloc(sizeof("puffer"));
(*l).str = "Kartoffel";
(*r).str = "puffer";
(*l).len = 9;
(*r).len = 6;

Then I wrote the concat function:

String1 concat(String1 l, String1 r) {
    unsigned int i = 0;
    String1 *newStr = malloc(sizeof(String1));
    /* +1 for '\0' at the end */
    newStr->str = malloc(l.len + r.len + 1);
    newStr->str = l.str;
    /* The following line is not working */
    newStr->str[l.len] = *r.str;
    newStr->len = l.len + r.len;
    return *newStr;
}

What Im trying to do is working with pointer arithmetic. When there is a pointer which points to the beginning of a storage area like char *str, it should be possible to move the pointer with a[b] or *((a) + (b)) right? When I run the code I get Segmentation fault (I hope its the right translation. Original: "Speicherzugriffsfehler"). If someone could give me a hint I would be thankful. PS: Sorry for my English.

Upvotes: 0

Views: 915

Answers (3)

homior
homior

Reputation: 191

Thank you very much for your help! I wrote another method to copy the string as you guys said.

char * copyStr (char * dest,char * src){
    unsigned int index;
    for (index = 0; src[index] != '\0'; index++) {
            dest[index] = src[index];
    }
    dest[index] = '\0';
    return dest;
}

And I edited my concat like that:

String1 concat (String1 l, String1 r){
    String1 *newStr = malloc(sizeof(String1));
    newStr->str = malloc(l.len+r.len+1);
    copyStr(newStr->str,l.str);
    copyStr((newStr->str+l.len),r.str);
    newStr->len = l.len+r.len;
    return *newStr;
}

with newStr->str+l.len the pointer will be moved. If l.len is 9, the pointer will point to the 10th byte, which is the end of the first string l. So the the String r will be copied in the memory storage behind the first string l.

Upvotes: 1

xing
xing

Reputation: 2508

After allocating memeory to newStr and newStr->str
Two pointers could be used. char *to, *from;
Set the pointers with to = newStr->str; and from = l.str;
copy the characters with *to = *from;
Advance the pointers with to++; and from++;
Repeat until *from == 0
Set from with from = r.str;
to does not need to be reset as it is correctly positioned at the end of newStr->str.
Repeat the copy of characters.
Repeat advancing the pointers.
Set a terminating 0 with *to = 0;

Upvotes: 1

mnistic
mnistic

Reputation: 11020

First, (*l).str = "Kartoffel"; makes (*l).str point to the "Kartoffel" string literal, meaning that the original memory allocated to (*l).str with malloc() is lost. Same for (*r).str = "puffer";. One of the things you can do to avoid this is copy the string into the allocated buffer by looping over the characters in a for loop (since you can't use string.h).

Then, in your concat() function, you do the same thing. You allocate the memory for newStr->str with malloc() (properly allocating an extra char for the null-terminator), but on the next line you re-assign that pointer to point to l.str, which is still pointing to the string literal. Then, with newStr->str[l.len] = *r.str; you are attempting to modify the string literal, which in C is undefined behavior.

The way to fix this could be, again, to copy the two strings into the buffer allocated with newStr->str = malloc(l.len+r.len+1);.

Upvotes: 2

Related Questions