why does the following string concatenation does not work?
main()
{
char *str1 = "United";
char *str2= "Front";
char *str3;
str3 = strcat(str1, str2 ) ;
printf("\n%s",str3 );
}
I got this problem in exercise questions in one of a book on pointers. The question mentions
[Q] Is the code correct if not why and also correct the code.
See my answer to the question concatenation of character arrays in c
You may not change string literals.
This statement
str3 = strcat(str1, str2 ) ;
tries to change the string literal str1 and moreover tries to write beyond the string literal.
To make a concatenated string you have to allocate a memory large enough to contain the both strings.
What you need is the following
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
const char *str1 = "United";
const char *str2 = "Front";
char *str3 = malloc( strlen( str1 ) + strlen( str2 ) + 1 );
strcpy( str3, str1 );
puts( strcat( str3, str2 ) );
free( str3 );
return 0;
}
The program output is
UnitedFront
When you write char* s = "something" a piece of read-only memory is allocated. More on this here.
The declaration of strcat looks like this:
char *strcat( char *dest, const char *src );
Basically what it will do is append src to dest, but since your destination, str1 does not have enough memory to hold both strings.
So what I would do is, either use snprintf with a pre-allocated buffer or:
char *str1 = "United";
char *str2 = "Front";
char *buf = calloc(strlen(str1) + strlen(str2) + 1, sizeof(char));
strncpy(buf, str1, strlen(str1));
strncat(buf, str2, strlen(str2));
printf("%s", buf);
Or with snprintf:
char *str1 = "United";
char *str2 = "Front";
int buf_len = strlen(str1) + strlen(str2) + 1;
char *buf = calloc(buf_len, sizeof(char));
snprintf(buf, buf_len, "%s%s", str1, str2);
The first parameter of strcat (str1 in your case) needs to have enough allocated memory to hold the concatenated string.
You can either create it with malloc or declare it as an array with a big enough size.
Related
I am trying to concatenate 2 character arrays but when I try it does not work and my o/p console hangs and does not print anything.
char *str[2];
str[0] = "Hello ";
str[1] = "World";
strcat(str[0],str[1]);
printf("%s\n",str[0]);
I even tried the below code which fails as well
char *str1 = "Hello ";
char *str2 = "World";
strcat(str1,str2);
printf("%s\n",str1);
Can someone explain this?
TIA.
To concatenate two strings you either have to create a new one large enough tp contain the both source strings or the one of the strings shall be large enough to hold the second appended string.
Take into account that string literals are immutable in C (and C++). Any attempt to change a string literal results in undefined behaviour.
You could concatenate strings if one of them was stored in a character array.
For example
char str1[12] = "Hello ";
const char *str2 = "World";
strcat( str1, str2 );
puts( str1 );
Or you could create a third string.
const char *str[2];
str[0] = "Hello ";
str[1] = "World";
char *str1 = malloc( strlen( str[0] ) + strlen( str[1] ) + 1 );
strcpy( str1, str[0] );
strcat( str1, str[1] );
puts( str1 );
free( str1 );
This code illustrates the problem:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *str1 = "Hello ";
char *str2 = "World";
char *ptr1, *ptr2;
printf("Find the end of str1...\n");
ptr1 = str1;
while (ptr1[0] != '\0') {
ptr1++;
}
printf("Copy str2 to the end of str1...\n");
ptr2 = str2;
while (ptr2[0] != '\0') {
printf("Attempt to write to read-only memory...\n");
ptr1[0] = ptr2[0];
printf("We never get here.\n");
ptr1++;
ptr2++;
}
ptr2[0] = '\0';
printf("Done.\n");
return 0;
}
Output
Find the end of str1...
Copy str2 to the end of str1...
Attempt to write to read-only memory...
Bus error: 10
How can I add '.' to the char Array := "Hello World" in C, so I get a char Array: "Hello World." The Question seems simple but I'm struggling.
Tried the following:
char str[1024];
char tmp = '.';
strcat(str, tmp);
But it does not work. It shows me the error: "passing argument 2 of ‘strcat’ makes pointer from integer without a cast"
I know that in C a char can be cast as int aswell. Do I have to convert the tmp to an char array aswell or is there a better solution?
strcat has the declaration:
char *strcat(char *dest, const char *src)
It expects 2 strings. While this compiles:
char str[1024] = "Hello World";
char tmp = '.';
strcat(str, tmp);
It will cause bad memory issues because strcat is looking for a null terminated cstring. You can do this:
char str[1024] = "Hello World";
char tmp[2] = ".";
strcat(str, tmp);
Live example.
If you really want to append a char you will need to make your own function. Something like this:
void append(char* s, char c) {
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
append(str, tmp)
Of course you may also want to check your string size etc to make it memory safe.
The error is due the fact that you are passing a wrong to strcat(). Look at strcat()'s prototype:
char *strcat(char *dest, const char *src);
But you pass char as the second argument, which is obviously wrong.
Use snprintf() instead.
char str[1024] = "Hello World";
char tmp = '.';
size_t len = strlen(str);
snprintf(str + len, sizeof str - len, "%c", tmp);
As commented by OP:
That was just a example with Hello World to describe the Problem. It
must be empty as first in my real program. Program will fill it later.
The problem just contains to add a char/int to an char Array
In that case, snprintf() can handle it easily to "append" integer types to a char buffer too. The advantage of snprintf() is that it's more flexible to concatenate various types of data into a char buffer.
For example to concatenate a string, char and an int:
char str[1024];
ch tmp = '.';
int i = 5;
// Fill str here
snprintf(str + len, sizeof str - len, "%c%d", str, tmp, i);
In C/C++ a string is an array of char terminated with a NULL byte ('\0');
Your string str has not been initialized.
You must concatenate strings and you are trying to concatenate a single char (without the null byte so it's not a string) to a string.
The code should look like this:
char str[1024] = "Hello World"; //this will add all characters and a NULL byte to the array
char tmp[2] = "."; //this is a string with the dot
strcat(str, tmp); //here you concatenate the two strings
Note that you can assign a string literal to an array only during its declaration.
For example the following code is not permitted:
char str[1024];
str = "Hello World"; //FORBIDDEN
and should be replaced with
char str[1024];
strcpy(str, "Hello World"); //here you copy "Hello World" inside the src array
I think you've forgotten initialize your string "str": You need initialize the string before using strcat. And also you need that tmp were a string, not a single char. Try change this:
char str[1024]; // Only declares size
char tmp = '.';
for
char str[1024] = "Hello World"; //Now you have "Hello World" in str
char tmp[2] = ".";
Suggest replacing this:
char str[1024];
char tmp = '.';
strcat(str, tmp);
with this:
char str[1024] = {'\0'}; // set array to initial all NUL bytes
char tmp[] = "."; // create a string for the call to strcat()
strcat(str, tmp); //
This is purely for self-interest and is not a homework assignment.
#include <stdio.h>
int main(void)
{
char* str3;
char* str1 = "Hello";
char* str2 = "World!";
while(*str1) str1++;
while(*str1++ = *str2++);
return 0;
}
I am attempting to develop a better understanding of C pointers and in doing so I would like to concatenate two strings and place the result into a third string. The (incomplete) code above results in a segfault and I'm not sure why. Isn't it possible to loop over the value referenced by a pointer and copy the data to another address?
Edit:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char* str1 = "Hello";
char* str2 = "World!";
char *str3 = malloc(strlen(str1) + strlen(str2) + 1);
while(*str1) *str3++ = *str1++;
while(*str2) *str3++ = *str2++;
puts(str3);
return 0;
}
The new attempt is above, and while not functional, are there "obvious" items I need to fix?
while(*str1) str1++;
This advances str1 until it points to the terminating zero byte at the end of the string constant.
while(*str1 = *str2++);
This modifies the terminating zero byte at the end of the string, but the string is a constant and so can't be modified.
If you want to assemble a string in memory, you need to allocate some space to do that in or use functions that do so. You could do:
char *new_string = malloc(strlen(str1) + strlen(str2) + 1);
strcpy(new_string, str1);
strcat(new_string, str2);
The first line allocates enough space to hold str1's contents, str2's contents, and the terminating zero byte.
int main(void)
{
char* str1 = "Hello";
char* str2 = "World!";
// allocate one more byte for string terminate cher ('\n')
int size = strlen(str1) + strlen(str2);
char* str3 = (char*)malloc(size + 1);
char* str_mod = str3;
while( (*str_mod++ = *str1++) != '\0');
str_mod--;
while( (*str_mod++ = *str2++) != '\0');
printf ( "%s", str3);
free (str3);
return 0;
}
The constant strings are not modifyable. You are not modifying str3.
You need to
get the length of str1 and str2.
malloc length of str1 + length str2 + 1 and assign to str3
You can use while loops if you like for the copy, or you can use strcpy and strcat to copy the strings to str3.
Since you are trying to learn, I am trying not to write the code for you.
int main (void){
char* str1 = "Hello";
char* str2 = "World";
int size1 = strlen(str1);
int size2 = strlen(str2);
int i = 0;
char* out = malloc(sizeof(char)*(size1+size2)+1);
for (i = 0; i < size1; i++){
out[i] = str1[i];
}
for (i = 0; i < size2; i++){
out[i+size1] = str2[i];
}
out[strlen(out)-1] = \0;
//out is a string.
//dont forget to free when you are done. free(out);
}
Its been a few months since i did C, but this would work. my syntax might be slightly off.
2nd attempt in question misses putting string terminating null to end of str3. So puts reads beyond end of data, prints garbage and may even crash if there is no 0 byte before reading invalid address. Add *str3 ='\0'; after loops.
Additionally, you modify str3 and lose start of string. Add one more variable, keep the pointer returned by malloc, and pass that to puts. Current code will start printing at the end of the new string.
Then when you have pointers to string literals, make them pointers to const char, because usually string literals are in read only memory area:
const char* str1 = "Hello";
const char* str2 = "World!";
I have two strings, e.g.:
str1 = "aaabbbcccdddeee"
str2 = "aaabbbccc"
How to do something like str1 - str2 to get the dddeee substring?
If str2 is guaranteed to be a prefix of str1, then this will suffice:
const char *str3 = &str1[strlen(str2)];
which is equivalent to this: (as #James points out in the comments)
const char *str3 = str1 + strlen(str2);
Of course, str3 is just a pointer into one of the original strings. If the contents of the original string changes, then so will your result. So you may want to create a copy, using malloc() and strcpy() (and then free() at some point).
This will skip the common prefix of two strings:
char* suffix(const char* prefix, const char* str) {
while (*prefix && *str && *prefix == *str) {
prefix++;
str++;
}
return str;
}
For example, if you pass "AAB" and "AACC", this would return "CC".
str3 will contain a copy of the prefix:
str1 = "aaabbbcccdddeee"
str2 = "aaabbbccc"
size_t length = strlen1 - strlen2;
char* str3 = calloc(sizeof(char), length + 1);
memcpy(str3, str1+strlen(str2), length);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char a[] = "aaaabbbbbdddeee";
char b[] = "aaaabbbbb";
const char* start = strstr(a, b);
if (start)
{
printf("%s\n", a + strlen(b));
}
return 0;
}
Since you have clarified that str2 is a prefix of str1, you can get the pointer to the extra part in str2 simply with the operation:
str1 + strlen(2);
For example, to print the "dddeee" part of your string:
printf("%s\n", str1 + strlen(str2));
How this works is simple. str1 + strlen(str2) is a pointer that is strlen(str2) N characters away from the beginning of the string pointed to be str1. strlen(str2) returns the number of characters in the second string and you skip those many characters in the first string and reach the extra part.
char *str1 = malloc(256*sizeof(char));
char *str2 = "stack"
for (i=0;i<15;i++){
sprintf(str1,"%s%s",str1,str2);
}
printf("%s\n",str1);
I'm trying to concat str2 to str1 at each loop count. But this code segment works but vulnerable.
Whats the best way to concat them?
According to the CERT Secure Coding Guidelines, you need to use pointers to const when referring to string literals.
So, char *str2 = "stack" needs to be const char *str2 = "stack";.
This will make it immutable.
Additionally, you are using deprecated/obsolete functions. The secure function you should be using is strcat_s. For example,
Compliant Example
enum { BUFFERSIZE=256 };
void complain(const char *msg) {
static const char prefix[] = "Error: ";
static const char suffix[] = "\n";
char buf[BUFFERSIZE];
strcpy_s(buf, BUFFERSIZE, prefix);
strcat_s(buf, BUFFERSIZE, msg);
strcat_s(buf, BUFFERSIZE, suffix);
fputs(buf, stderr);
}
Read here about strcpy_s() and strcat_s().
If you want to use sprintf; something like this:
char *str1 = malloc(256*sizeof(char));
char *str2 = "stack";
*str1 = '\0';
for (i=0;i<15;i++){
snprintf(str1 + strlen(str1), 256 - strlen(str1), "%s", str2);
}
printf("%s\n",str1);
The standard C function for string concatenation is char * strncat ( char * destination, char * source, size_t num );.
Use strncat:
char *str1 = malloc(256*sizeof(char));
str1[0] = '\0';
char *str2 = "stack"
for (i=0;i<15;i++){
strncat(str1, str2, 256 - 1 - strlen(str2));
}
printf("%s\n",str1);