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/
Related
What are the issues with the following code in C?
char* copyStr(const char* someStr)
{
char buf[100];
sprintf(buf, “%s”, someStr);
return buf;
}
There are 2 major problems in your code:
sprintf(buf, “%s”, someStr); will attempt to store more than 100 bytes to buf if the string pointed to by somStr is longer than 99 bytes plus the null terminator, causing undefined behavior. This call is equivalent to strcpy with the same issue. You should always use snprintf instead of sprintf, passing the length of the destination array, thus preventing a buffer overflow.
returning a pointer to a local array is incorrect as the object will go out of scope immediately upon exiting the function: the caller will invoke undefined behavior dereferencing this pointer.
For your purpose, you should allocate a block of memory, copy the string to it and return a pointer to it:
#include <stdlib.h>
#include <string.h>
char *copyStr(const char *someStr) {
size_t len = strlen(someStr);
char *p = malloc(len + 1);
if (p != NULL) {
memcpy(p, someStr, len + 1);
}
return p;
}
This is exactly the semantics of the function strdup defined in POSIX and standardized the upcoming C23 Standard:
char *strdup(const char *s);
I'm new with dynamic memory allocation and I tried to write a simple program to concatenate 2 strings (one initialized and one read from stdin) using realloc for the first string. But I receive this error:
cygwin_exception::open_stackdumpfile: Dumping stack trace to malloc.exe.stackdump
The code breaks at realloc and I do not know why, could you please help?
Input: man alive.
Expected output: The most beloved man alive.
I have tried replacing strlen with a number but with no avail.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *str = "The most beloved";
char str2[20];
scanf("%[^\n]%*c", str2);
//printf("%s %s\n", str, str2);
str = (char *)realloc(str, strlen(str) + strlen(str2));
strcat(str, str2);
printf("%s\n", str);
free(str);
}
You declared a pointer to a string literal
char *str = "The most beloved";
String literals have static storage duration. So they may not be reallocated dynamically.
Thus this statement
str = (char *)realloc(str, strlen(str) + strlen(str2));
invokes undefined behavior.
Pay attention to that you need to reserve memory for the terminating zero character '\0' of the result string.
What you need is the following
char *result = ( char * )malloc( strlen(str) + strlen(str2) + 1 );
strcpy( result, str );
strcat( result, str2 );
puts( result );
free( result );
Also it would be more safer to write
scanf("%19[^\n]", str2);
You are assigning a pointer to str which was not allocated using malloc. You may pass pointers to free or realloc only if they have been allocated using malloc.
Proper usage of realloc()
You could do
str = strdup("mystring");
Also here you need to account for the \0 at the end, so it should be:
str = (char *)realloc(str, strlen(str) + strlen(str2)+1);
I have the following simple program which creates a pointer to the first character of a string:
char str[] = "Hello world";
char *p = &str[0];
How can I then get this string back into a variable using only the pointer?
Dereferencing the pointer just gives the first character of the string - as somewhat expected - so I'm assuming that there is no 'simple' way to achieve this and it will instead require writing extra code.
The current way I would approach this would be as follows:
Iterate from the pointer until a null terminator is reached to find the length of the string
Create a new char array with this length
Iterate through again inserting characters into this array
Is there a library function to achieve this, or if not, a simpler way that doesn't involve iterating twice?
Yes you have to "do it by hand". Because there are no objects in C - you need to take care of all that happens in the code.
You can use malloc, strlen and memcpy:
char str[] = "Hello world";
char *p = malloc(strlen(str) + 1);
if (!p) { abort(); }
memcpy(p, str, strlen(str) + 1);
You can use strcpy and forget about one strlen:
char *p = malloc(strlen(str) + 1);
if (!p) { abort(); }
strcpy(p, str);
Or you can use strdup from POSIX or a C extension:
char *p = strdup(str);
if (!p) { abort(); }
...
Is there a library function to achieve this, or if not, a simpler way that doesn't involve iterating twice?
As said in comment, strdup() will do exactly what you want. But here there is another problem (by your point of view): strcpy() will iterate the string twice, because there is no other way to duplicate a string.
By definition, strings in C are a sequence of characters somewhere in memory, with the last one character being a NUL (with single L), the value 0 (in a char). References to strings are pointers to the first character in the sequence depicted above. Note that two different strings can point to the same memory (they are not so different then...), or a string can point into the middle of another. These two cases are somewhat particular but not uncommon. The memory for strings must be managed by the programmer, who is the only one to know where allocate and deallocate space for strings; functions like strcpy() do nothing special in this regard, they are (presumably) well written and optimized, so maybe to copy a string the behavior is not plain as I depicted it before, but the idea is the same.
try this code:
#include "stdio.h"
int main(){
char str[] = "Hello world";
int count = 12;
char (*p)[12] = &str;
printf("%c\n",(*p)[0]);
printf("%c\n",(*p)[1]);
printf("%c\n",(*p)[2]);
printf("%c\n",(*p)[3]);
printf("%s\n",(*p));
}
Here's how I would make a copy of a string using only the standard library functions:
#include <stdio.h> // printf
#include <stdlib.h> // malloc
#include <string.h> // strcpy
int main(void)
{
char str[] = "Hello world"; // your original string
char *p = (char *)malloc(strlen(str) + 1); // allocate enough space to hold the copy in p
if (!p) { // malloc returns a NULL pointer when it fails
puts("malloc failed.");
exit(-1);
}
strcpy(p, str); // now we can safely use strcpy to put a duplicate of str into p
printf("%s\n", p); // print out this duplicate to verify
return 0;
}
I'm doing simple c excercise using visual studio.
Using strcat_s function I receive a violation exception thru this code:
char *str1;
str1 = (char *)malloc(20);
*str1 = "Ciao ";
char *str2 = "Marco";
strcat_s(str1, sizeof(str1), str2);
printf("%s", str1);
Now, if I use a predefined array whith a fixed size, strcat_s works perfectly.
How can I use pointers to char instead of array to make it work?
Any other solution or tip will be very appreciated.
Thank you in advance.
You have to copy the strings firstly into the allocated memory. If you like to know the length of a string use strlen(). sizeof() returns the size of the datatype in byte. In your case it is a pointer (4 byte on 32bit, 8 byte on 64bit machines).
The following code should work properly:
char *str1 = (char *)malloc(20);
strcpy(str1,"Ciao ");
char *str2 = (char *)malloc(20);
strcpy(str2,"Marco ");
strcat(str1, str2);
printf("%s", str1);
There are some issues with your code, and there are some general notes on strcat_s.
Your code str1 = (char *)malloc(20); *str1 = "Ciao " does not copy Ciao; *str is a single character at the first position of str, and your expression converts string literal "Ciao " (which is a pointer to a sequence of characters) to some single character (T in this case; surprising, isn't it?). One would need to use strcpy instead. An array, like char buffer[20] = "Ciao ", in contrast, works, because this (special) case is not an assignment but an initialiser of an array.
Your code sizeof(str1) gives you the size of a pointer value, which is probably 4 or 8, and has nothing to do with the actual size of the content or the memory block reserved. One should use strlen instead.
Concerning strcat_s, one should consider that it is not available on all platforms and that you have to be aware of it's special behaviour. For example, if you call strcat_s(somebuffer, 3, "somestrlongerthan3"), which exceeds the maximum length of 3 as provided, somebuffer will be an "empty" string (i.e. the first character will be set to \0.
I'd suggest to use strncat or snprintf instead. See the following variants:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main () {
char c = "Ciao "; // Gives a compiler warning and yields 'T'
#define maxlen 20
// Variant 1: start with initialized buffer, yet no "pointer" and dynamic allocation
char resultBuffer[maxlen] = "Ciao ";
size_t charactersRemaining = maxlen-strlen(resultBuffer)-1;
strncat(resultBuffer, "Marco", charactersRemaining);
// Variant 2: use dynamically allocated buffer and snprintf, with constant "Ciao".
char *resultBuffer2 = malloc(maxlen);
const char* second2 = "Marco";
snprintf(resultBuffer2, maxlen, "Ciao %s", second2);
// Variant 3: use dynamically allocated buffer and snprintf, with probably variable "Ciao" and "Marco"
char *resultBuffer3 = malloc(maxlen);
const char* first3 = "Ciao";
const char* second3 = "Marco";
snprintf(resultBuffer3, maxlen, "%s %s", first3, second3);
return 0;
}
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!