Concatenate two char* strings in a C program - c

I wrote the following C program:
int main(int argc, char** argv) {
char* str1;
char* str2;
str1 = "sssss";
str2 = "kkkk";
printf("%s", strcat(str1, str2));
return (EXIT_SUCCESS);
}
I want to concatenate the two strings, but it doesn't work.

The way it works is to:
Malloc memory large enough to hold copies of str1 and str2
Then it copies str1 into str3
Then it appends str2 onto the end of str3
When you're using str3 you'd normally free it free (str3);
Here's an example for you play with. It's very simple and has no hard-coded lengths. You can try it here: http://ideone.com/d3g1xs
See this post for information about size of char
#include <stdio.h>
#include <memory.h>
int main(int argc, char** argv) {
char* str1;
char* str2;
str1 = "sssss";
str2 = "kkkk";
char * str3 = (char *) malloc(1 + strlen(str1)+ strlen(str2) );
strcpy(str3, str1);
strcat(str3, str2);
printf("%s", str3);
return 0;
}

Here is a working solution:
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv)
{
char str1[16];
char str2[16];
strcpy(str1, "sssss");
strcpy(str2, "kkkk");
strcat(str1, str2);
printf("%s", str1);
return 0;
}
Output:
ssssskkkk
You have to allocate memory for your strings. In the above code, I declare str1 and str2 as character arrays containing 16 characters. I used strcpy to copy characters of string literals into them, and strcat to append the characters of str2 to the end of str1. Here is how these character arrays look like during the execution of the program:
After declaration (both are empty):
str1: [][][][][][][][][][][][][][][][][][][][]
str2: [][][][][][][][][][][][][][][][][][][][]
After calling strcpy (\0 is the string terminator zero byte):
str1: [s][s][s][s][s][\0][][][][][][][][][][][][][][]
str2: [k][k][k][k][\0][][][][][][][][][][][][][][][]
After calling strcat:
str1: [s][s][s][s][s][k][k][k][k][\0][][][][][][][][][][]
str2: [k][k][k][k][\0][][][][][][][][][][][][][][][]

strcat concats str2 onto str1
You'll get runtime errors because str1 is not being properly allocated for concatenation

When you use string literals, such as "this is a string" and in your case "sssss" and "kkkk", the compiler puts them in read-only memory. However, strcat attempts to write the second argument after the first. You can solve this problem by making a sufficiently sized destination buffer and write to that.
char destination[10]; // 5 times s, 4 times k, one zero-terminator
char* str1;
char* str2;
str1 = "sssss";
str2 = "kkkk";
strcpy(destination, str1);
printf("%s",strcat(destination,str2));
Note that in recent compilers, you usually get a warning for casting string literals to non-const character pointers.

strcat(str1, str2) appends str2 after str1. It requires str1 to have enough space to hold str2. In you code, str1 and str2 are all string constants, so it should not work. You may try this way:
char str1[1024];
char *str2 = "kkkk";
strcpy(str1, "ssssss");
strcat(str1, str2);
printf("%s", str1);

strcat attempts to append the second parameter to the first. This won't work since you are assigning implicitly sized constant strings.
If all you want to do is print two strings out
printf("%s%s",str1,str2);
Would do.
You could do something like
char *str1 = calloc(sizeof("SSSS")+sizeof("KKKK")+1,sizeof *str1);
strcpy(str1,"SSSS");
strcat(str1,str2);
to create a concatenated string; however strongly consider using strncat/strncpy instead. And read the man pages carefully for the above. (oh and don't forget to free str1 at the end).

Related

How does strcat() fucntion actually works and its alternate

Let's take an example.
#include <stdio.h>
#include <string.h>
int main() {
char str1[7] = "hello ";
printf("Initial size of str1 is: %d\n", strlen(str1));
char str2[] = "buddy";
printf("%s\n", strcat(str1, str2));
printf("Final size: %d\n", strlen(str1));
}
The output of the above program will be
Initial size of str1 is: 6
hello buddy
Final size: 11
--------------------------------
Process exited after 0.835 seconds with return value 0
Press any key to continue . . .
See? how the size of str1 changed from 7 to 11 (including null variable), regarding that what I think would have happened is :
Some function I do not know may have reallocated contiguous memory for str1 starting from same address as before i.e str1 with size strlen(str1)+strlen(str2)+1 +1 for null value, and then redefined it to get hello buddy.
If I am wrong please tell, if not then, what function is it and how does it work?
One more question: how can I write a code to do the above task without the use of strcat function.
I tried doing it using realloc() but didn't quite succeed may be that's because realloc() can only reallocate dynamically allocated memory, is it so?
Buffer overflow
OP's code fails as strcat(str1,str2) attempts to write past the end of str1[] - result: undefined behavior (UB). #dimich
Instead use a larger destination buffer.
// char str1[7]="hello ";
char str1[7 + 5]="hello ";
char str2[]="buddy";
printf("%s\n",strcat(str1,str2));
Use correct print specifier
strlen() returns a size_t, not an int.
// printf("Initial size of str1 is: %d\n",strlen(str1));
printf("Initial size of str1 is: %zu\n",strlen(str1));
Tip: enable all warnings.
Alternative
One of many alternatives: copy str2 to the end of str1.
// printf("%s\n",strcat(str1,str2));
strcpy(str1 + strlen(str1), strt2);
printf("%s\n",str1);
realloc()
realloc() can only reallocate dynamically allocated memory, is it so?
realloc() should not be used on pointers to non-allocated, non-NULL pointers.
In addition to re-allocating dynamically allocated memory, realloc() can start with no prior allocation.
char *p = realloc(NULL, size);
// just like
char *p = malloc(size);
Moral of the story
Be mindful of memory usage with string functions.
Enable all warnings.
You can only reallocate the memory you have dynamically allocated (ie using malloc family functions).
ee? how the size of str1 changed from 7 to 11 (including null
variable), regarding that what I think would have happened is : A
function idk which one, but it may have reallocated contiguous memory
for str1 starting from same address as before i.e str1 with size
strlen(str1)+strlen(str2)+1 +1 for null value, and then redefined it
to get hello buddy. If i am wrong please tell, if not then , what
function is it and how does it work?
You are wrong. It is an example of an Undefined Behaviour. You have written some data outside array memory. Undefined Behavior means that your program behaviour from now is unpredictable. strcat does not reallocate any memory.
At last, how can i write a code to do the above task without the use
of strcat function.
For example:
char *mystrcat(char *dest, const char *src, const int isDynamicMemory)
{
size_t dlen = strlen(dest);
size_t slen = strlen(src);
if(isDynamicMemory)
{
dest = realloc(dest, slen + dlen + 1);
if(!dest) return NULL;
}
memcpy(dest + dlen, src, slen + 1);
return dest;
}
If dest was dynamically allocated you can reallocate it to the correct size by passing 1 as isDynamicMemory parameter
Try to do not program in the main function. Use functions for such task like writing strcat like function.
The program has undefined behavior because in the call of strcat
printf("%s\n", strcat(str1, str2));
the memory beyond the character array str1 declared like
char str1[7] = "hello ";
is being overwritten.
There is no space in the array to accommodate the string "buddy" after the stored string "hello ".
The sizes of the array str1 and str2 themselves was not changed. The function strlen does not return the size of a character array. It returns the length of a string: a sequence of characters terminated by the zero-terminating character '\0'. To get the size of a character array you should use the operator sizeof.
Pay attention to that the return type of the function strlen is size_t. To output a value of this type you have to use the conversion specifier zu instead of d.
printf("Initial size of str1 is: %zu\n", strlen(str1));
^^^
To make the program correct you have to enlarge the character array str1. Here is a demonstration program.
#include <stdio.h>
#include <string.h>
int main( void )
{
char str1[12] = "hello ";
printf( "The size of str1 is: %zu\n", sizeof( str1 ) );
printf( "The length of the stored string in str1 is: %zu\n", strlen( str1 ) );
char str2[] = "buddy";
printf("%s\n", strcat(str1, str2));
printf( "The size of str1 is: %zu\n", sizeof( str1 ) );
printf( "The length of the stored string in str1 is: %zu\n", strlen( str1 ) );
}
The program output is
The size of str1 is: 12
The length of the stored string in str1 is: 6
hello buddy
The size of str1 is: 12
The length of the stored string in str1 is: 11
As you can see from the output the size of the array str1 stays unchanged. What was changed is the length of the stored string in the array str1.
Pay attention to that the function strcat does not allocate or reallocate memory for arrays passed to the function as arguments. So if the destination array does not have enough memory to accommodate the appended string then the behavior is undefined because in this case the memory after the destination array will be overwritten.
As other answers (1, 2) mentioned, your code has a buffer overflow, a kind of undefined behaviour.
One more question: how can I write a code to do the above task without the use of strcat function.
Either:
Use snprintf()
Use strlcpy()
Implement your own version of strcat() (with some potential improvements)
Option 1
char str1[] = "hello ";
char str2[] = "buddy";
size_t total_size = sizeof(str1) + sizeof(str2) - 1; // sizeof counts \0 at the end
char res[total_size];
snprintf(res, total_size, "%s%s", str1, str2);
printf("sizeof(str1) = %zu\n", sizeof(str1));
printf("sizeof(str2) = %zu\n", sizeof(str2));
printf("total_size = %zu\n", total_size);
printf("res = %s\n", res);
sizeof(str1) = 7
sizeof(str2) = 6
total_size = 12
res = hello buddy
snprintf() lets you to control how many characters at most you want to print. This is comes handy in preventing a buffer overflow. For example, if you use sprintf(res, "%s%sxxx", str1, str2) in the above code, you'll get a BO. This is not the case with snprintf(res, total_size, "%s%sxxx", str1, str2).
Option 2
strlcpy() lets you to control how many characters at most you want to copy, and guarantees null-termination (unlike strncpy()). Possible implementations: 1, 2, 3.
Option 3 (credit: Back to Basics)
char *concatenate(char *dest, char *src)
{
while (*dest) dest++;
while ((*dest++ = *src++));
return --dest;
}
Or:
char *concatenate_n(char *dest, char *src, int n)
{
while (*dest) dest++;
for (int i = 0; i < n && (*dest++ = *src++); ++i) {}
return --dest;
}
Example:
char str1[12] = "hello ";
char str2[] = "buddy";
concatenate(str1, str2);
// concatenate_n(str1, str2, sizeof(str1) - 1 - strlen(str1)); // Remaining space in str1
printf("str1 = %s\n", str1);
printf("p = %s\n", p);
As i mentioned in the comment, overflow of str1 occures. strcat() doesn't know where and how strings are allocated. It searches end of destination string and appends source string overwriting null terminator.
If you want dynamic allocation, it could be:
char str1[]="hello ";
printf("Initial size of str1 is: %zu\n", strlen(str1));
char str2[]="buddy";
char *str3 = malloc(strlen(str1) + strlen(str2) + 1);
if (!str3)
return 1;
strcpy(str3, str1);
strcat(str3,str2);
printf("%s\n",str3);
printf("Final size: %zu\n", strlen(str3));
free(str3);
This may be optimized little bit. strlen() calculates length of string at runtime and you have strings known at compile time. So we can use it:
char str1[]="hello ";
printf("Initial size of str1 is: %zu\n", strlen(str1));
char str2[]="buddy";
char *str3 = malloc(sizeof(str1) + sizeof(str2) - 1);
if (!str3)
return 1;
strcpy(str3, str1);
strcpy(str3 + sizeof(str1) - 1, str2);
printf("%s\n",str3);
printf("Final size: %zu\n", strlen(str3));
free(str3);
Also pay attention to strlen() return type: it is size_t. We should either cast it to int for printing with %d format or print with %zu.
EDIT: fixed length calculation, fixed printf formatting modifier.

strcat function not working with pointers

int main(int argc , int *argv[]){
char str[7] = "Mobile";
char str2[11] = "Samsung4g";
char *str3 = 0;
str3 = ( char* )(malloc(30));
str3 = "Carrier";
strcat(str3, str);//Problem facing here, dunno why
Like what others have mentioned in the comments, the statement:
str3 = "Carrier";
overwrites the value of str3 with the address of the string literal "Carrier" causing the address returned by malloc() to be lost.
Using str3 then in strcat() as a first argument attempts to modify a string literal which results in undefined behaviour.
Use strcpy() or equivalent functions to copy strings in C.

String concatenation. C

All of the code below on C.
Both the code snippet below are compiled, but the difference is that the second program crashes at startup.
One:
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char *str[80];;
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
}
Two:
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char *str="";
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
}
The difference is that in the first case, said the size of the str string, while the second is not. How to make string concatenation without a direct indication of the size of the string str?
The difference is that in the first case, said the size of the str
string, while the second is not.
No. In the first program, the following statement
char *str[80];
defines str to be an array of 80 pointers to characters. What you need is a character array -
char str[80];
In the second program,
char *str="";
defines str to be a pointer to the string literal "", not an array. Arrays and pointers are different types.
Now, the second program crashes because
char *str="";
defines str to be a pointer to a string literal. The first argument of strcpy should be a pointer to a buffer which is large enough for the string to be copied which is pointed to by its second argument.
However, str points to the string literal "" which is allocated in read-only memory. By passing str to strcpy, it invoked undefined behaviour because strcpy tries to modify it which is illegal. Undefined behaviour means the behaviour is unpredictable and anything can happen from program crash to due to segfault (illegal memory access) or your hard drive getting formatted. You should always avoid code which invoked undefined behaviour.
How to make string concatenation without a direct indication of the
size of the string str?
The destination string must be large enough to store the source string else strcpy will overrun the buffer pointed to by its first argument and invoke undefined behaviour due to illegal memory access. Again, the destination string must have enough space for the source string to be appended to it else strcat will overrun the buffer and again cause undefined behaviour. You should ensure against this by specifying the correct size of the string str in this case.
Change to:
One:
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
}
Two:
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char str[80]="";
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
}
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char *str=NULL;
size_t strSize = strlen(foo)+strlen(bar)+strlen("TEXT ")+1;
str=malloc(strSize);
if(NULL==str)
{
fprintf(stderr, "malloc() failed.\n");
goto CLEANUP;
}
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
CLEANUP
if(str)
free(str);
}
size_t len1 = strlen(first);
size_t len2 = strlen(second);
char * s = malloc(len1 + len2 + 2);
memcpy(s, first, len1);
s[len1] = ' ';
memcpy(s + len1 + 1, second, len2 + 1); // includes terminating null
Did I do good?
In the second version you have set char *str=""; this is equivalent to allocating an empty string on the stack with 1 byte which contains null for end of string. Had you written char*str="0123456789", you would have allocated 11 bytes on the stack the first 10 of which would have been "0123456789" and the 11th byte would have been null. If you try to copy more than allocated bytes to the str, your program might crash. So either allocate dynamically enough memory, or statically.
Both programs are wrong, the first provokes undefined behavior exactly as the second one.
char *str[80]; is array of pointers which you pass to functions ( strcpy, strcat) as first argument, while the first argument for those functions should be char *. Possible solution for this issue to define str as char str[80];
The issue with the second program is that char *str=""; is a pointer to read only piece of memory, which can't be changed.In this case one of possible solutions can be :
char* str = malloc(80);
strcpy(str,"");
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
You'll have to allocate memory before copying. The first defines the size so as 80
char *str = new char[10]; could also be a method of allocation. malloc function could also be used to allocate memory.
Here are some references that might help you
http://www.cplusplus.com/reference/cstdlib/malloc/
http://www.cplusplus.com/reference/cstdlib/calloc/

Can I copy a string in an empty string?

Suppose I do like this to copy the string.
char str[] = "";
char *str2 = "abc";
strcpy(str, str2);
printf("%s", str); // "abc"
printf("%d", strlen(str)); // 3
Then, why it doesn't give me undefined behaviour or causing the program to fail. What are the disadvantages of doing like that ?
You are writing past the memory space allocated to str on the stack. You need to make sure you have the correct amount of space for str. In the example you mentioned, you need space for a, b, and c plus a null character to end the string, so this code should work:
char str[4];
char *str2 = "abc";
strcpy(str, str2);
printf("%s", str); // "abc"
printf("%d", strlen(str)); // 3
This code is definitely causing a stack problem, though with such a small string, you are not seeing the issue. Take, for example, the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char str[] = "";
char *str2 = "A really, really, really, really, really, really loooooooooooooooonnnnnnnnnnnnnnnnng string.";
strcpy(str, str2);
printf("%s\n", str);
printf("%d\n", strlen(str));
return 0;
}
A contrived example, yes, but the result of running this is:
A really, really, really, really, really, really loooooooooooooooonnnnnnnnnnnnnnnnng string.
92
Segmentation fault
This is one of the reasons why the strcpy function is discouraged, and usage of copy and concatenate functions that require specifying the sizes of the strings involved are recommended.
It actually gives you undefined behavior, but your program doesn't have to fail because of that. That's how undefined behavior works.

Runtime error while doing string concatenation

What is the problem with the below program?
main( )
{
char *str1 = "United" ;
char *str2 = "Front" ;
char *str3 ;
str3 = strcat ( str1, str2 ) ;
printf ( "\n%s", str3 ) ;
}
I am not able to compile the above program and it always give me runtime error. I am trying to concatenate the two string. Is there any error in the above program?
Thanks.
Make your char *str1 = "United" as
char str1[<required memory for concatenated resultant string>] = "United".
You need to allocate memory for the destination buffer which is str1. str3 will also receive address of str1 in the result. 'strcat' will not check for space availability in destination buffer (str1). Programmer has to take care of it.
You are trying to modify a string literal, but your compiler (and runtime support) won't let you. When you do so, you are invoking 'undefined behaviour', which is a Bad Thing!™ Anything could happen; it is legitimate for the program to crash. Avoid undefined behaviour.
You need to allocate enough (writable) memory for the strings, maybe like this:
#include <stdio.h>
#include <string.h>
int main(void)
{
char *str1 = "United";
char *str2 = "Front";
char str3[64];
strcpy(str3, str1);
strcat(str3, str2);
printf("%s\n", str3);
return(0);
}
When you declare char *str = "someText", basically, you initialize a pointer to a string constant which can't be changed, and is located somewhere in your computer's memory.
After that by using the function strcat() you are trying to change that string constant, which we said is constant -
Such behavior compiles with no errors, but will cause your program to crash during runtime since const (constant) works during runtime and is not precompiled like #define.
A different solution for you might be,
#include<stdio.h>
#include<string.h>
int main(void) {
char* str1 = "Hello,";
char* str2 = " World";
char str3[30];
strcpy(str3, str1);
strcat(str3, str2);
printf("%s\n", str3);
printf("\n\n\n");
return 0;
}
Hope that helps!
Best of luck in the future!

Resources