simple string copy, but memcpy doesn't work [duplicate] - c

This question already has answers here:
Different answers from strlen and sizeof for Pointer & Array based init of String [duplicate]
(4 answers)
Closed 3 years ago.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main()
{
unsigned char str[] = "abcdefg";
unsigned char *str1 = (unsigned char*)malloc(sizeof(str) -1);
memcpy(str1, str, (sizeof(str)-1) );
for(int i = 0; i<(sizeof(str1)); i++)
printf("%c", str1[i]);
free(str1);
}
I want copy the string str to str1 but the output is
abcd
It means that only pointer byte(4byte) is copied.
And i try
printf("%d", sizeof(str)-1 );
it's output is 7
What is my mistake?

it mean that only pointer byte(4byte) is copied.
No, it does not. You're assuming that your printout is correct, which it is not. You can use sizeof on arrays but not on pointers. Well, you can, but it means something different.
Everything is copied. You're just printing the first four characters. Change to:
for(int i = 0; i<(sizeof(str) - 1); i++)
Also, don't cast malloc. Here is why: Do I cast the result of malloc?

First the mistakes and then the correct code:
Mistakes:
Don't ever use sizeof(str) to get the length of the string. It doesn't work with pointers. Instead, use strlen(str) + 1.
You are subtracting 1 from the size of the string on malloc call. Why? You are not making space for the ending NULL character.
When copying strings, if you know that the destination string is large enough to store the source, use strcpy instead of memcpy. If you only want an additional size parameter like in memcpy, use strncpy. memcpy is not meant to deal with strings, but with plain arrays.
The correct type to use for strings is char, not unsigned char.
Not really a mistake, but to print a string you can use printf("%s", str) or puts(str). Why bother with a for loop?
void main() is prohibited by the C standard.
Correct code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char str[] = "abcdefg";
char str1* = malloc(strlen(str) + 1);
strcpy(str1, str);
puts(str1);
free(str1);
//return 0; - default in C99 and later
}

str1 is a pointer whereas str is a character array. When you say sizeof(str1) in your for loop, it iterates 4 times because sizeof(str1) must have evaluated to 4(a 32 bit compiler) whereas sizeof(str) evaluates to the correct length.
You should read What is the size of a pointer? once to know more about size of pointers.
Fixed code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main()
{
unsigned char str[] = "abcdefg";
unsigned char *str1 = (unsigned char*)malloc(sizeof(str) -1);
memcpy(str1, str, (sizeof(str)-1) );
for(int i = 0; i<(sizeof(str) - 1); i++)
printf("%c", str1[i]);
free(str1);
}

Related

Cannot use strcpy with 2 string (segmentation fault) [duplicate]

This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed last year.
What's wrong with this code?:
int main(int argc, char ** argv) {
char strs[] = "What will be printed?";
char *str1;
char *str2;
strs[5] = '\0';
str1 = strs;
strcpy(str2, str1);
printf("%s\n", str2);
return 1;
}
I want it to print "What", instead i get segmentation fault.
I believe it has something to do with the strcpy(str2, str1);, but what is the explanation for that? The signature of strcpy is char* strcpy(char* destination, const char* source); and that's exactly what i did.
Could you explain that to me?
Your destination string is not initialized - it has no memory reserved for itself. An attempt to write to it causes invalid memory access (you're trying to overwrite something completely random and unplanned) and is followed by a segmentation fault.
One clean way to initialize a string is to define a global macro variable that just sets the largest size of strings you plan on using in your code,
#define MAXBUF 100
Then in your main you can simply write:
char str2[MAXBUF];
And your program will work. Alternative is to use dynamic memory allocation which you will likely learn about soon.
#include <stdio.h>
#include <string.h>
int main() {
char *src = "What will be printed?";
char dest[100];
int START = 0; // start of copy
int LENGTH = 5; // length of copy
// copies up to LENGTH characters from the string pointed to, by src to dest. In a case where the length of src is less than that of LENGTH, the remainder of dest will be padded with null bytes.
strncpy(dest, &src[START], LENGTH);
printf("%s\n", dest);
return 0;
}

String operations cause segfault C [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 1 year ago.
I'm trying to 'deep copy' a string so that I can perform operations on one copy, while retaining the original copy. This is the base example that I've got and for some reason the strncpy call causes a segfault. Please help
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main() {
char* stringA = "someVeryinTeresTingString";
char* stringB = malloc(sizeof(char) * strlen(stringA));
printf("A: %s, B: %s\n", stringA, stringB);
for (int i = 0; i < strlen(stringA); i++) {
stringB[i] = tolower(stringA[i]);
}
printf("A: %s, B: %s\n", stringA, stringB);
strncpy(stringA, stringB, strlen(stringA) - 1);
printf("A: %s, B: %s\n", stringA, stringB);
}
Easiest fix is to make a local copy of that string literal:
char stringA[] = "someVeryinTeresTingString";
Everything else works just the same.
Note that in the original code you have a pointer to immutable memory, while in this version you have a local (stack) array that is initialized with a copy of that string.
Another thing to note is if you're copying and manipulating C strings, do things like this:
char* stringB = strdup(stringA);
for (int i = 0; i < strlen(stringB); ++i) {
stringB[i] = tolower(stringB[i]);
}
Or even more efficiently by avoiding all these expensive strlen() calls:
char* stringB = strdup(stringA);
for (char* p = stringB; *p; ++p) {
*p = tolower(*p);
}
This line:
char* stringB = malloc(sizeof(char) * strlen(stringA));
shuld be like this:
char* stringB = malloc(sizeof(char) * (strlen(stringA) + 1));
then you will able to copy the \0 in the end of stringA
also, you want to copy to literal string - that is segmentation fault
char *strncpy(char *dest, const char *src, size_t n)
I'll try to comment and correct in your own code the mistakes I've seen:
(I will not correct things that can be eliminated or better done in another way, but are correct or not harmful, so you'll see only what must be corrected because of programming errors, and not questions about style or programming uses)
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main() {
char* stringA = "someVeryinTeresTingString";
/* you need to consider the space for the final null character in the malloc() call */
char* stringB = malloc(sizeof(char) * (strlen(stringA) + 1));
/* you don't need to use sizeof(char) as it is always equal to one.
* Multiplying by one is not necessary, but you'll probably know.
* char is warranteed by C standard that its sizeof is one. */
/* you need to copy the string *before* printing, or you will print an
* uninitialized string. Or at least initialize stringB to zeros, so you can
* use it with printf like functions (I do initialize the first char position to
* zero to make it appear as a length zero "" string)
* You will incurr in undefined behaviour if you don't do this. */
stringB[0] = '\0';
printf("A: %s, B: %s\n", stringA, stringB);
/* you need to copy the strings, so you can do it better if you test when
* stringA[i] == '\0', so you don't calculate the length of a string that is
* not going to change at every loop iteration. I will not change your
* code, because this is not an error. But strlen() searches from the
* beginning of the string for the '\0' char, character by character,
* and this test is done at every loop iteration. With the expression
* stringA[i] == 0 you do only a test per loop iteration to see if
* the char at position i in stringA is the null character. */
int i;
for (i = 0; i < strlen(stringA); i++) {
stringB[i] = tolower(stringA[i]);
}
/* you have not copied the final '\0', so I do it now. I need to move the
* declaration of i outside of the loop to be able to use it's value. */
stringB[i] = 0; /* you can use 0 or '\0' interchangeably */
printf("A: %s, B: %s\n", stringA, stringB);
/* nope. you need to copy the strings with a normal strcpy() as you know that
* both are the same length (better, you know that the space in stringB
* is the same as the length of stringA plus one). If you do this, you will not copy the last '\0' char, so wee need to append it.
* well, I don't know if that is what you want, so I don't actually touch anything here. */
strncpy(stringA, stringB, strlen(stringA) - 1);
/* stringB should be one char shorter than stringA */
printf("A: %s, B: %s\n", stringA, stringB);
}
by the way, you have been recommended to use strdup(3). This is a good idea, you don't need to be thinking on final nulls in this case, because strdup() takes care of it. Just remember that strdup(3) is not included in many C standard revisions, so you can get in trouble if you
move your program to a place lacking it (that should be very strange, anyway)

Why strlen() can get the length of string and sizeof cannot in C?

I want to calculate the length of a string in C in VS Ccode, but when I use sizeof function, the time of compiling didn't stop and get any result; on the other hand, I can get the length by strlen function: why?
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char greeting[] = "hello";
int len = strlen(greeting);
//int len = sizeof(greeting);
printf("length is:%d",len);
return 0;
}
I know the difference between them: strlen() is used to get the length of an array of chars/string, while
sizeof() is used to get the actual size of any type of data in bytes. However, I don't know why there is no answer when I run sizeof.
You've invoked undefined behaviour: you're printing a value of type size_t with the format for an int. This is not guaranteed to work. Cast the value:
printf("length is: %d\n, (int)sizeof(greeting));
The result will be one larger than the result from strlen() because strlen() does not count the terminating null byte and sizeof() does.

How to assign an array of characters to a string literal

I have an array of char and I'm trying to have a string literal with the same chars in the array.
I tried strcpy, and try =, and I tried what I did in the following code. But it doesn't seem to work or I'm understanding something.
char s1[10]="Youssef";
char *s2
while(*s2!='\0')
*s2++=*s1++;
printf("%s",s2);
Process doesn't return.
String literals are read only.
In any case, what you are trying to do seems you are confused.
A string literal: char *sl = "string literal";
An uninitialized char pointer: char *s2;
In order to do the copy you like, you first need to allocate memory for the string.
Moreover, you cannot do pointer arithmetics with an array. Arrays and pointers are not the same thing!
Furthermore, you should remember the origin of s2 pointer, since after incrementing it until the copy is complete, you would then need to reset the pointer.. Exercise: Think what would happen if you did the copy in a function (preferably named mystrcpy`)...
Complete example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char s1[10]="Youssef";
char *s2 = malloc(sizeof(char) * (strlen(s1) + 1)); // +1 for the NULL-terminator
int i = 0;
char *origin_s2 = s2;
while(s1[i] != '\0')
*s2++ = s1[i++];
*s2 = '\0';
s2 = origin_s2;
printf("%s\n", s2);
return 0;
}
Output:
Youssef
PS: It is highly recommended to check if the dynamic allocation of the memory was successful (check if return value of malloc() is not NULL).

How to copy array value to another array

I have two arrays:
char roundNames1[16][25], roundNames2[16 / 2][25];
I then want to copy a result from the first array to the second. I have tried this:
where roundNames1[5] = "hello"
#include <string.h>
printf("First array: %s", roundNames1[5]);
strcpy(roundNames1[5], roundNames2[6]);
printf("Second array: %s", roundNames2[6]);
But this just returns
First array: hello
Second array:
Why is it not working?
You need to exchange arguments of function strcpy
strcpy( roundNames2[8], roundNames1[5] );
Here is a part pf the function description from the C Standard
7.23.2.3 The strcpy function
Synopsis
1
#include <string.h>
char *strcpy(char * restrict s1, const char * restrict s2);
Description
2 The strcpy function copies the string pointed to by s2 (including
the terminating null character) into the array pointed to by s1. If
copying takes place between objects that overlap, the behavior is
undefined.
strcpy - arguments other way around.
http://www.cplusplus.com/reference/cstring/strcpy/
Copy arrays/strings with memcpy
void * memcpy (void * destination, void * source, size_t size)
The memcpy function copies an certain amount of bytes from a source memory location and writes them to a destinaction location. (Documentation)
Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char some_array[] = "stackoverflow";
int memory_amount = sizeof(some_array);
char *pointer = malloc(memory_amount);
memcpy(pointer, &some_array, memory_amount);
printf("%s\n", pointer);
free(pointer);
return 0;
}
Output
$ ./a.out
stackoverflow

Resources