Implementation of string concatenation - c

This is the strcat function that I have implemented, but I get a segmentation fault when I go to the line *dst++ = *src++;. I have incremented src till '\0' as I want to append the next string starting from there. Can you please tell me why it gives segmentation fault? Am I doing any logical mistake by doing *dst++ = *src++;?
char *strconcat(char *dst, char *src)
{
char *fdst;
fdst = dst;
if (dst == '\0' || src == '\0')
return fdst;
while (*dst != '\0')
dst++;
while (*src != '\0')
*dst++ = *src++;
return fdst;
}
Hey i went through many solution given below and i made following changes but still i get segmentation problem when i start concatenate two strings, here is my entire code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *strconcat(char *dst, const char *src);
void main()
{
char *str1 = "Stack";
char *str2 = "overflow";
printf("MY CONCAT:%s\n",strconcat(str1, str2));
printf("INBUILT CONCAT:%s\n",strcat(str1, str2));
}
char *strconcat(char *dst, const char *src)
{
char *fdst;
int dst_len = 0, src_len = 0;
dst_len = strlen(dst);
src_len = strlen(src);
fdst = (char *) malloc(dst_len + src_len + 1);
fdst = dst;
if (src == NULL)
return fdst;
while(*dst)
{
dst++;
fdst++;
}
while(*src)
*fdst++ = *src++;
*fdst = '\0';
return fdst;
}

The idiomatic way is
while (*dst++ = *src++);

Some observations:
You're not copying the termination, leaving a non-terminated string in dst. This is the cause of the actual problems.
This: if(dst == '\0'||src == '\0') is weird, if the intent was comparing against NULL you should do so more directly and not use character literals.
The src argument should be const char * since it's read-only. Using const for pointers that are "input" arguments is a very good idea, since it communicates intent right there in the prototype. It also helps avoid mistakingly writing to the wrong string.
You can't have a function beginning with str, that "namespace" is reserved for the standard library.

Multiple problems here:
PROBLEM - I
The memory allocated with malloc
fdst = (char *) malloc(dst_len + src_len + 1);
is lost as some lines later you are doing this:
fdst = dst;
replacing the address returned by malloc in 'fdst' with the address of the target string..!! Hope you fix it on your own, its darn simple.
PROBLEM - II
After fixing that above problem, you'll have to fix this:
while(*dst)
{
dst++;
fdst++;
}
don't only increment, you'll also have to copy your characters from dst to fdst as this will be your concatenated string.
PROBLEM - III
finally, you are doing this in the end..!!
return fdst;
you realize the mistake there right? Hope you can take care of that [ Hint: save the starting address and return it in the end, not the incremented pointer ;) ]
Note: Not an optimised solution but, fixes your code.

Possible crash causes:
1) may be the length of your dst is not enougth to support concatunation of src and dst.
2) may be you have called your function with input char pointers which they are not pointed to allocated memory (staic or dynamic)
3) may be your input dst char pointer is pointing to a constant string.
another remark you have to finish your dst string with '\0' after the second while
while (*src != '\0')
*dst++ = *src++;
*dst='\0';

Try this:
while(*original)
original++;
while(*add)
{
*original = *add;
add++;
original++;
}
*original = '\0';
It may be helpful.

There are pretty much errors in your code:
if (dst == '\0' || src == '\0') what you are trying by checking this. First of all this is not clear condition - you should use if (dst == NULL || src == NULL) or if (*dst == '\0' || *src == '\0') to be more accurate and make this more clear. Second even if this condition would be right (if (*dst == '\0' || *src == '\0')) you are not achieving what concatenation should. At least if *src == '\0' you should probably return original string - dst.
You should probably check if dst is long enough to store your new string or you should allocate new buffer inside function big enough to hold both dst and src (malloc (strlen(dst) + strlen(src) + 1) - note extra +1 for holding terminating '/0' character)
You are not terminating your result string.
And the answer for your questions: segmentation fault is probably because your dst is NOT long enough to hold both src and dst. You can use hint in point 2. to modify your code or you can declare bigger buffer outside function that will have size at least (strlen(dst) + strlen(src) + 1.
Another reason could be calling this function with constant string e.g char *str = "string";. In this case most probably string is constant and you are not allowed to modify it (in most operating system this will be located in non-modifiable part of program and you will have only pointer to this location).

Your code is correct , see below for explanation !
I think you are using char * for the src and dst string in the caller.
Using an array declaration there will help, since your program is crashing at
*dst++ = *src++;
because dst and src point to strings which are constants and cannot be modified.
In the following code I have just added main, and your function is unchanged !
#include<stdio.h>
char *strconcat(char *dst, char *src)
{
char *fdst;
fdst = dst;
if (dst == '\0' || src == '\0')
return fdst;
while (*dst != '\0')
dst++;
while (*src != '\0')
*dst++ = *src++;
return fdst;
}
void main()
{
char dest[10] = "one" ;
char src[10] = "two" ;
printf("\n%s " , strconcat( dest , src ) ) ;
}
Although you need to change the if statement to
if (*dst == '\0' || *src == '\0')
return fdst;

Related

why this function returns null?

This code finds the next word in the string.
For example
given an input of " my cake" the function should return "my cake". as the expected output
If I use return then the output is (null), but I use printf then the code works
I would like to know how to get the expected output using return.
#include <stdio.h>
int main()
{
char* str[1000];
printf("enter:");
fgets(str,1000,stdin);
printf("%s",find_word_start(str));
}
char* find_word_start(char* str){
char* result[1000];
int c = 0, d = 0;
while(str[c] ==' ') {
c++;
}
while(str[c] != '\0'){
result[d++] = str[c++];
if(str[c]==' ') {
result[d++] = str[c++];
}
while(str[c]==' ') { //
c++;
}
}
result[d] = '\0';
//print or return char?
return result;
}
char* result[1000]; creates an array of 1000 pointers. That's wrong in a number of ways.
You want a block of 1000 chars, not pointers.
Actually, 1000 is not the number of characters you want. You usually want a smaller number, but you could also want a larger number.
You don't want to store the result in automatically allocated memory, because that will be freed as soon as you exit the function. Use malloc (or something that does a malloc such as strdup).
Fix:
// Returns a copy that needs to be freed.
char* find_word_start(const char* src) {
while (*src == ' ')
++src;
size_t len = 0;
while (str[len] != '\0')
++len;
++len; // Include NUL
result = malloc(len);
char* dst = result;
while (len--)
*(dst++) = *(src++);
return result;
}
Well, I was avoiding using string functions above like you did, but they greatly simplify the solution.
// Returns a copy that needs to be freed.
char* find_word_start(const char* src) {
while (*src == ' ')
++src;
return strdup(src);
}
That said, since you return the tail end of the string, you could simply return a pointer into the existing string.
// Returns a pointer into the provided string.
const char* find_word_start(const char* str) {
while (*str == ' ')
++str;
return str;
}
The following line allocates memory space in the stack but after the function ends everything is gone:
char result[1000];
You need to allocate memory in the heap like that:
char *result = malloc(sizeof(char) *1000);
Note: don't forget to free that memory space by free function.

Char *strcat Implementation leading to Segmentation Fault

char *strcat(char*dest, char*src) {
while (dest != '\0') {
*dest++;
}
while (src != '\0') {
*dest++ = *src++;
}
return dest;
}
I keep getting a segmentation fault on the line *dest++ = *src++. Any ideas on how to fix the problem?
Your code has 4 problems:
you are comparing pointers to the null character instead of comparing the character they point to. Since it will take incrementing the pointer an awful lot of times before it becomes 0, if at all, you are reading and/or writing beyond the end of the buffers, from/to invalid memory before this happens, hence the crash.
you do not null terminate the destination string.
you return the pointer to the end of the destination string instead of the original destination string. This might be a useful API, but you should use a different name for that.
the src pointer should be declared as const char * to conform to the standard declaration for this function and to allow passing pointers to constant strings as sources.
Here is a corrected version:
char *strcat(char *dest, const char *src) {
char *saved = dest;
while (*dest != '\0') {
dest++;
}
while ((*dest++ = *src++) != '\0') {
continue;
}
return saved;
}
Okay: the Kernighan way:
char *strcat(char *dest, char *src)
{
char *org = dest;
while(*dest++){;}
// at this moment, *dest MUST be pointing to '\0'
while(*dest++ = *src++){;}
// at this moment, *dest MUST be pointing to '\0' agian
return org;
}
Update (courtously #chqrlie):
char *strcat(char *dest, char *src)
{
char *org = dest;
for(; *dest; dest++) {;}
// at this moment, dest MUST be pointing to '\0'
while(*dest++ = *src++) {;}
// at this moment, dest points past the '\0', but who cares?
return org;
}
dest and source will never become '\0' if they aren't null to begin with (or maybe after a long time to be correct, but you'll probalby run out of memory long before that).
You should use:
while(*dest != '\0'){
dest++;
}
while(*src != '\0'){
*dest++ = *src++;
}
to check the values underneath the pointers.
There are some other problems too:
the resulting string is not null-terminated.
a pointer to the end of the string is returned.
As mentioned by others: src should be a const pointer too.
This should do it:
char *strcat(char *dest, const char *src)
{
char *start_pos = dest;
while(*dest != '\0')
dest++;
while(*src != '\0')
*dest++ = *src++;
*dest = '\0';
return start_pos;
}
Minor detail: I would give this funtion some other name than the standard used strcat().

How do I make my program abort (without any lib)

I have an exercise in class where I have to copy the strstr() function in C (from <string.h> library). Here is my code
char *ft_strcpy(char *dest, char *src)
{
int i;
i = 0;
while (src[i] != '\0')
{
dest[i] = src[i];
i++;
}
dest[i] = '\0';
return (dest);
}
This code is fully functional but when I try with a dest string that is smaller than the src string, it shows an unpredictable result that ends up overwriting src too. The original strstr() function's answer to that is to abort program in that situation. How can I make my program abort given that I can't use the abort() function?
You must check your string.
May be one of them is NULL.
When you do : While (str[i] ..)
You don't know if (str) is NULL or not.
Do :
While (str && str[i] != '\0')
It's better.
You can also check if dest is malloc fine because if you don't have any memory for your string dest you can't assign value.
I would suggest a compact implementation
char * ft_strcpy(char * dest, const char * src) {
if (strlen(dest) < strlen(src)) { /* abort(); or exit(1); */ }
char * s = dest;
while (*dest++ = *src++);
return s;
}
The actual bounds checking is implemented in the safer version of strcpy, i.e. strcpy_s. You can find an implementation in Safe C Library.

How to set element in array to null in C program

I am writing a C program in Unix and cannot figure out how to set an array element to NULL. I need to be able to do this to remove multiple characters from a string.
You can't assign null to specific char array index as value represented by that index is char instead of pointer. But if you need to remove specific character from given string, you can implement this as follows
void removeChar(char *str, char garbage) {
char *src, *dst;
for (src = dst = str; *src != '\0'; src++) {
*dst = *src;
if (*dst != garbage) dst++;
}
*dst = '\0';
}
Test Program
#include<stdio.h>
int main(void) {
char* str = malloc(strlen("abcdef")+1);
strcpy(str, "abcdbbbef");
removeChar(str, 'b');
printf("%s", str);
free(str);
return 0;
}
output
acdef
If you have a char[], you can zero-out individual elements using this:
char arr[10] = "foo";
arr[1] = '\0';
Note that this isn't the same as assigning NULL, since arr[1] is a char and not a pointer, you can't assign NULL to it.
That said, that probably won't do what you think it will. The above example will produce the string f, not fo as you seem to expect.
If you want to remove characters from a string, you have to shift the contents of the string to the left (including the null terminator) using memmove and some pointer arithmetic:
Example:
#include <stdio.h>
#include <string.h>
int removechars(char *str, size_t pos, size_t cnt) {
size_t len = strlen(str);
if (pos + cnt > len)
return -1;
memmove(str + pos, str + pos + cnt, len - pos - cnt + 1);
return 0;
}
Then use it like so:
char str[12] = "hello world";
if (removechars(str, 5, 4) == 0) /* remove 4 chars starting at str[5] */
printf("%s\n", str); /* hellold */
If you're talking about an array of pointers (say char **), you'd just say array[element] = NULL;. But it sounds as though you really want to just truncate a string (char *), in which case you'd actually want to write string[index] = '\0', where \0 is the null byte. But, as far as I know, 0, '\0', and NULL are all equivalent and equal to 0 (please correct me if I'm wrong). Of course, for clarity, you should use 0 for numbers, '\0' for chars and strings, and NULL for pointers.

Remove first char of string C

Im trying to remove the first char of the string and keep the remainder, my current code doesnt compile and im confused on how to fix it.
My code:
char * newStr (char * charBuffer)
{
int len = strlen(charBuffer);
int i = 1;
char v;
if(charBuffer[0] == 'A' || charBuffer[0] == 'Q'){
for(i=1;i<len;i++)
v = v + charBuffer[i];
}
v = v + '\0';
return v;
}
Gcc: "Warning: return makes pointer from integer without a cast"
Also: "char * newStr (char * charBuffer)" needs to remain the same.
Strings don't work like this in C. You're summing up all of the characters in the buffer into the v variable. You can't use + to concatenate. The code you posted has some serious problems which indicate that there's an understanding gap with how to use C.
Try this:
char *newStr (char *charBuffer) {
int length = strlen(charBuffer);
char *str;
if (length <= 1) {
str = (char *) malloc(1);
str[0] = '\0';
} else {
str = (char *) malloc(length);
strcpy(str, &charBuffer[1]);
}
return str;
}
or this:
char *newStr (char *charBuffer) {
char *str;
if (strlen(charBuffer) == 0)
str = charBuffer;
else
str = charBuffer + 1;
return str;
}
Depending on whether you want to allocate a new string or not. You'll also have to add the code for handling the cases that don't start with 'Q' or 'A'. I didn't include those because I'm not sure exactly what you're trying to do here.
Make sure you do some research into allocating and deallocating memory with malloc and free. These are fundamental functions to be able to use if you're going to be doing C programming.
Well, your description says you want to deal with "strings", but you code deals with char buffers/pointers. The simplest approach to remove the first character for strings would be
const char *newStr(const char *string)
{
return string+1;
}
but as that doesn't look at all like what your code is doing, you probabaly want something different. For example, if you want to just remove a leading 'A' or 'Q' and then copy the string to a buffer, you want something like
char *newStr(const char *string)
{
if (string[0] == 'A' || string[0] == 'Q')
string++;
return strdup(string);
}
You can simply move your char pointer one character in:
char* newstring = oldstring + 1;
Your function is declared to return a char * and you are returning a char.
Furthermore, why don't you just return a pointer to the second character?
char * newStr (char * charBuffer)
{
if (charBuffer && (*charBuffer == 'A' || *charBuffer == 'Q')) return charBuffer + 1;
return charBuffer;
}
Several of the other answers recommended returning charBuffer + 1. As I noted in my previous comment:
This is bad practice. What if the string is dynamically allocated? Perhaps eventually the storage will be freed (starting from the second character). The string should be copied to new storage first.
Freeing a piece of storage from the middle will result in undefined behavior.
Instead, try the strdup function which will return a duplicate of the given string.
#include <string.h>
#include <stdio.h>
char *newStr(char* charBuffer) {
if (charBuffer && (charBuffer[0] == 'A' || charBuffer[0] == 'Q'))
return strdup(charBuffer + 1);
else
return strdup(charBuffer);
}
void main() {
char a[7] = "Advait";
char b[5] = "John";
printf("%s\n",newStr(a)); // Prints "dvait"
printf("%s\n",newStr(b)); // Prints "John"
}

Resources