I have two variables as stated below. How do I copy the contents of "varOrig" to "varDest" (no loops for ou while)?
const char* varDest = "";
char varOrig[34] = "12345";
If you want to copy the address of the array to the pointer, do this:
varDest = varOrig;
Otherwise, you will need to allocate memory and copy the string.
strdup is useful for this:
varDest = strdup(varOrig);
You need to free varDest after using this.
memcpy is the fastest library routine for memory-to-memory copy. It is usually more efficient than strcpy, which must scan the data it copies or memmove, which must take precautions to handle overlapping inputs.
// Defined in header <string.h>
void* memcpy( void *dest, const void *src, size_t count );
This code.
#include<string.h>
#include<stdlib.h>
...
char varOrig[34] = "12345";
// calculate length of the original string
int length = strlen(varOrig);
// allocate heap memory, length + 1 includes null terminate character
char* varDest = (char*)malloc((length+1) * sizeof(char));
// memcpy, perform copy, length + 1 includes null terminate character
memcpy(varDest, varOrig, length+1);
Related
I have the following code in C now
int length = 50
char *target_str = (char*) malloc(length);
char *source_str = read_string_from_somewhere() // read a string from somewhere
// with length, say 20
memcpy(target_str, source_str, length);
The scenario is that target_str is initialized with 50 bytes. source_str is a string of length 20.
If I want to copy the source_str to target_str i use memcpy() as above with length 50, which is the size of target_str. The reason I use length in memcpy is that, the source_str can have a max value of length but is usually less than that (in the above example its 20).
Now, if I want to copy till length of source_str based on its terminating character ('\0'), even if memcpy length is more than the index of terminating character, is the above code a right way to do it? or is there an alternative suggestion.
Thanks for any help.
The scenario is that target_str is initialized with 50 bytes. source_str is a string of length 20.
If I want to copy the source_str to target_str i use memcpy() as above with length 50, which is the size of target_str.
currently you ask for memcpy to read 30 characters after the end of the source string because it does not care of a possible null terminator on the source, this is an undefined behavior
because you copy a string you can use strcpy rather than memcpy
but the problem of size can be reversed, I mean the target can be smaller than the source, and without protection you will have again a undefined behavior
so you can use strncpy giving the length of the target, just take care of the necessity to add a final null character in case the target is smaller than the source :
int length = 50
char *target_str = (char*) malloc(length);
char *source_str = read_string_from_somewhere(); // length unknown
strncpy(target_str, source_str, length - 1); // -1 to let place for \0
target_str[length - 1] = 0; // force the presence of a null character at end in case
If I want to copy the source_str to target_str i use memcpy() as above
with length 50, which is the size of target_str. The reason I use
length in memcpy is that, the source_str can have a max value of
length but is usually less than that (in the above example its 20).
It is crucially important to distinguish between
the size of the array to which source_str points, and
the length of the string, if any, to which source_str points (+/- the terminator).
If source_str is certain to point to an array of length 50 or more then the memcpy() approach you present is ok. If not, then it produces undefined behavior when source_str in fact points to a shorter array. Any result within the power of your C implementation may occur.
If source_str is certain to point to a (properly-terminated) C string of no more than length - 1 characters, and if it is its string value that you want to copy, then strcpy() is more natural than memcpy(). It will copy all the string contents, up to and including the terminator. This presents no problem when source_str points to an array shorter than length, so long as it contains a string terminator.
If neither of those cases is certain to hold, then it's not clear what you want to do. The strncpy() function may cover some of those cases, but it does not cover all of them.
Now, if I want to copy till length of source_str based on its terminating character ('\0'), even if memcpy length is more than the index of terminating character, is the above code a right way to do it?
No; you'd be copying the entire content of source_str, even past the null-terminator if it occurs before the end of the allocated space for the string it is pointing to.
If your concern is minimizing the auxiliary space used by your program, what you could do is use strlen to determine the length of source_str, and allocate target_str based on that. Also, strcpy is similar to memcpy but is specifically intended for null-terminated strings (observe that it has no "size" or "length" parameter):
char *target_str = NULL;
char *source_str = read_string_from_somewhere();
size_t len = strlen(source_str);
target_str = malloc(len + 1);
strcpy(target_str, source_str);
// ...
free(target_str);
target_str = NULL;
memcpy is used to copy fixed blocks of memory, so if you want to copy something shorter that is terminated by '\n' you don't want to use memcpy.
There is other functions like strncpy or strlcpy that do similar things.
Best to check what the implementations do. I removed the optimized versions from the original source code for the sake of readability.
This is an example memcpy implementation: https://git.musl-libc.org/cgit/musl/tree/src/string/memcpy.c
void *memcpy(void *restrict dest, const void *restrict src, size_t n)
{
unsigned char *d = dest;
const unsigned char *s = src;
for (; n; n--) *d++ = *s++;
return dest;
}
It's clear that here, both pieces of memory are visited for n times. regardless of the size of source or destination string, which causes copying of memory past your string if it was shorter. Which is bad and can cause various unwanted behavior.
this is strlcpy from: https://git.musl-libc.org/cgit/musl/tree/src/string/strlcpy.c
size_t strlcpy(char *d, const char *s, size_t n)
{
char *d0 = d;
size_t *wd;
if (!n--) goto finish;
for (; n && (*d=*s); n--, s++, d++);
*d = 0;
finish:
return d-d0 + strlen(s);
}
The trick here is that n && (*d = 0) evaluates to false and will break the looping condition and exit early.
Hence this gives you the wanted behaviour.
Use strlen to determine the exact size of source_string and allocate accordingly, remembering to add an extra byte for the null terminator. Here's a full example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char *source_str = "string_read_from_somewhere";
int len = strlen(source_str);
char *target_str = malloc(len + 1);
if (!target_str) {
fprintf(stderr, "%s:%d: malloc failed", __FILE__, __LINE__);
return 1;
}
memcpy(target_str, source_str, len + 1);
puts(target_str);
free(target_str);
return 0;
}
Also, there's no need to cast the result of malloc. Don't forget to free the allocated memory.
As mentioned in the comments, you probably want to restrict the size of the malloced string to a sensible amount.
I know this code is sloppy, I'm trying to relearn string manipulation in C. If I have a string ABBCCCD and I want to store the separate letters in a struct, is there an efficient way to do so? I have some code down below to demonstrate the long way of what I'm trying to do. (Also, do I have to manually add the null-terminator when I'm doing a strncpy?)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct dst_struct {
char a[2];
char b[3];
char c[4];
char d[2];
} dst_struct_t;
int main(void) {
char* test = "ABBCCCD";
char* src = malloc(strlen(test)+1);
strncpy(src, test, strlen(test)+1);
printf("%s\n", src);
dst_struct_t dst;
strncpy(dst.a, src, 1);
strncpy(dst.b, src+1, 2);
strncpy(dst.c, src+3, 3);
strncpy(dst.d, src+6, 1);
printf("dst.a: %s\n", dst.a);
printf("dst.b: %s\n", dst.b);
printf("dst.c: %s\n", dst.c);
printf("dst.d: %s\n", dst.d);
free(src);
}
There isn't really any better way to do this, except that you don't need to copy test to src first.
You also need to add the null terminators to all the strings. It would probably be best to write a function that does both steps: strncpy() and adding the null terminator.
function copy_n(char *dest, char *src, size_t offset, size_t len) {
strncpy(src+offset, dest, len);
dest[len] = '\0';
}
int main(void) {
char* test = "ABBCCCD";
copy_n(dst.a, test, 0, 1);
copy_n(dst.b, test, 1, 2);
copy_n(dst.c, test, 3, 3);
copy_n(dst.d, test, 6, 1);
printf("dst.a: %s\n", dst.a);
printf("dst.b: %s\n", dst.b);
printf("dst.c: %s\n", dst.c);
printf("dst.d: %s\n", dst.d);
}
From the strcpy/strncpy man page:
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
The strcpy() function copies the string pointed to by src, including the terminating null byte ('\0'), to the buffer pointed to by dest. The strings may not overlap, and the destination string dest must be large enough to receive the copy. Beware of buffer overruns! (See BUGS.)
The strncpy() function is similar, except that at most n bytes of src are copied. Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.
The n argument of strncpy is generally meant to be the length of the destination buffer, as the point of the function is to be like strcpy but prevent overflowing the destination buffer if the source string is too long or not NULL-terminated. If used in that manner, your destination string will be NULL-terminated if the source string fits that length, otherwise the final byte of the buffer will contain the nth character of the source string.
However, the way you seem to be using strncpy is to set the exact number of characters you want to copy from the source buffer to place in the destination buffer. That is not really the intended purpose of strncpy. Instead, what you'd want to use is memcpy, since you are really not concerned with the zero-termination of the source string, but rather just copying a set number of characters from a set location. And yes, you will have to manually add the null-terminator if you use memcpy.
The following code doesnt copy the contents of matches 2 to keys[0].
Why is that so?
char **keys;
char matches[2000];
char *matches2;
matches2 =strtok(matches," ");
strncpy(keys[0],matches2, sizeof keys[0]);
You forgot to allocate space for keys to point to, as well as space for keys[#] to point to.
Also, are you really sure you want to use strncpy? It does not guarantee 0-termination, instead copying at most n byte of the ggiven string and 0-filling the rest of the buffer.
The size for a string is the number of elements including 0-terminator: strlen(s)+1
For creating a copy of a string, you might look into non-standard strdup, a possible implementation:
char* strdup(const char* s) {
size_t n = strlen(s)+1;
char* r = malloc(n);
if(r)
memcpy(r, s, n);
return r;
}
Try this assuming that you already have allocated space for keys[0]
strncpy(keys[0], matches2, /*your desired size*/);
or
strcpy(keys[0], matches2);
I'm very new to C, I'm getting stuck using the strncpy function.\
Here's an example of what I'm working with:
int main()
{
const char *s = "how";
struct test {
char *name;
};
struct test *t1 = malloc(sizeof(struct test));
strncpy(t1->name, s, sizeof(*s));
t1->name[NAMESIZE] = '\0';
printf("%s\n", t1->name);
}
I have a const char *, I need to set the "name" value of test to the const char. I'm having a really tough time figuring this out. Is this even the correct approach?
Thank you very much!
Well, you allocate the structure, but not the string inside the structure. You need to do that before you copy to it. Even when you do, you will probably overwrite unallocated memory when you attempt to set the string terminator.
And, due to a hight intake ow wine, I just noticed you actually only copy one character, but it's still undefined behavior.
Let's take this one step at a time:
struct test *t1 = malloc(sizeof(struct test));
this allocates space for a struct test; enough space for the pointer name, but not any memory for the pointer to point to. At a minimum, you'll want to do the following:
t1->name = malloc(strlen(s) + 1);
Having done that, you can proceed to copy the string. However, you already computed the length of the string once to allocate the memory; there's no sense in doing it again implicitly by calling strncpy. Instead, do the following:
const size_t len = strlen(s) + 1; // +1 accounts for terminating NUL
t1->name = malloc(len);
memcpy(t1->name, s, len);
In general, try to use this basic pattern; compute the length of strings once when they come into your code, but then use explicit-sized memory buffers and the mem* operations instead of implicit-length strings with str* operations. It is at least as safe (and often safer) and more efficient if done properly.
You might use strncpy if t1->name was a fixed-size array instead (though many people prefer to use strlcpy). That would look like the following:
struct test { char name[MAXSIZE]; };
struct test *t1 = malloc(sizeof *t1);
strncpy(t1->name, s, MAXSIZE - 1);
t1->name[MAXSIZE-1] = 0; // force NUL-termination
Note that the size argument to strncpy should always be the size of the destination, not the source, to avoid writing outside the bounds of the destination buffer.
Without any attempt at completeness or educational direction, here's a version of your code that should work. You can play "spot the difference" and search for an explanation for each one separately on this site.
int main()
{
const char s[] = "how"; // s is an array, const char[4]
struct test{ char name[NAMESIZE]; }; // test::name is an array
struct test * t1 = malloc(sizeof *t1); // DRY
strncpy(t1->name, s, NAMESIZE); // size of the destination
t1->name[NAMESIZE - 1] = '\0'; // because strncpy is evil
printf("%s\n", t1->name);
free(t1); // clean up
}
strncpy() is always wrong
if the result is too long, the target string will not be nul-terminated
if the target is too long (the third argument) , the trailing end will be completely padded with NULs. This will waste a lot of cycles if you have large buffers and short strings.
Instead, you cound use memcpy() or strcpy, (or in your case even strdup() )
int main()
{
const char *s = "how";
struct test {
char *name;
};
struct test *t1
size_t len;
t1 = malloc(sizeof *t1);
#if USE_STRDUP
t1->name = strdup(s);
#else
len = strlen(s);
t1->name = malloc (1+len);
memcpy(t1->name, s, len);
t1->name[len] = '\0';
#endif
printf("%s\n", t1->name);
return 0;
}
I have an exercise where I need to write a wrapper function for strcat. After it prints the string length (for debugging) it seg faults and I am not quite sure why. Any help would be greatly appreciated.
EDIT: I didn't specify that the wrapper function is supposed to guarantee that it never goes outside of the bounds of memory allocated for destination. This is why I allocated only enough memory for "string" in destination and reallocating more in the Strcat() wrapper.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* Strcat(char* destination, const char* source);
int main(void)
{
(void)printf("This strcat cannot fail!\n");
char* destination = (char*)malloc(sizeof(char)*7);
destination = "string";
(void)printf("%s\n", destination);
Strcat(destination, " concatination");
(void)printf("%s\n", destination);
(void)printf("It works!\n");
free(destination);
return 0;
}
char* Strcat(char* destination, const char* source)
{
(void)printf("%d\n", (strlen(destination)+strlen(source))*sizeof(char));
if((sizeof((strlen(destination)+strlen(source)))+1) > sizeof(destination))
destination = (char*)realloc(destination, sizeof((strlen(destination)+strlen(source)))+1);
return strcat(destination, source);
}
This line:
destination = "string";
overwrites the pointer returned from malloc(3) so you lose that memory forever. You probably meant to copy that string, so use strcpy(3) or something.
if((sizeof((strlen(destination)+strlen(source)))+1) > sizeof(destination))
That's wrong, sizeof doesn't give you anything comparable to the length of the string. Don't use it here.
Moreover, you can't really get the number of allocated bytes of the string. So if you know destination has been allocated with malloc[*], you should realloc unconditionally:
destination = (char*)realloc(destination, strlen(destination)+strlen(source)+1);
Again, no sizeof. And be prepared to handle allocation failures, which means saving the old value of destination and freeing it when realloc returns 0.
[*] Note that destination = "string" breaks this premise.
Try summat like
char *Strcat(char *d, const char *s) /* please put in the proper names - i am being lazy*
{
int dLen = strlen(d); /* ditto above */
int sLen = strlen(s);
d = (char *)realloc(d, dLen + sLen +1);
return strcat(d, s);
}