strcpy using pointers - c

I'm trying to write strcpy on my own using pointers and I get an error during runtime.
void str_cpy(char **destination, const char *source) {
// char *s1 = *destination;
while (*source != '\0') {
**destination++ = *source++; //Get an error here
}
**destination = '\0';
}
I call the function as follows:
char *str = NULL;
str_cpy(&str, "String");
Is it not OK?
Thanks!

No, it's not okay. Why? Because str is a NULL pointer. It's pointing to nothing. When you try to write values into it, where will they go? It's not pointing to any allocated memory!
You first have to allocate memory for str. You can do:
char *str = malloc(strlen("String") + 1); // + 1 for the '\0' character at the end of C-style strings
Or you can do:
char str[256]; // make str large enough to hold 256 chars. Note that this is not as safe as the above version!
Also, destination should be a single pointer, not a double pointer. Well, it's not technically wrong to use a double pointer, it's just unnecessary.
Optionally, you can allocate the memory in the str_cpy function, like so:
void str_cpy(char **destination, const char *source) {
*destination = malloc(strlen(source) + 1);
// ... continue as normal

For simplicity's sake, this can be done in one line in a function.
void mystrcpy(char *dest, const char *src) {
while (*dest++ = *src++);
}
This being said, you do need to allocate memory for dest beforehand using malloc or just simply by having a character array like char dest[256].

I don't see any need to pass a pointer-to-pointer:
void str_cpy(char *dst, const char *src) {
while (*src != '\0') {
*dst++ = *src++;
}
*dst = '\0';
}
And you need to allocate memory for dst before passing:
const char *src = "String";
char *str = malloc(strlen(src)+1); //plus one for null byte
str_cpy(dst, src);

You should likely allocate some memory for that pointer before passing it off to a function that fills what it points to (which in this case, is NULL).
Example:
char *str = malloc(128);
if (str)
{
str_cpy(&str, "String");
free(str);
str = NULL;
}
I advise not doing this without also providing target-buffer size information (i.e. if you're writing your own, then boundary-check the target buffer, otherwise your version has the same security flaws as strcpy() which are bad enough as it is).
Note: Unless you're planning on changing the address held by the pointer passed as the target, you need not use a double pointer either. The double pointer usage you have prevents the traditional strcpy() usage pattern of:
char str[128];
str_cpy(&str, "Hello"); // error.
An array address cannot be passed as a pointer-to-pointer, so your code cannot fill a static array without an intermediate pointer:
char str[128];
char *p = str;
str_cpy(&p, "Hello"); //ok. passing address of pointer.
If this is not intentional (and I don't see why it could be unless you have ideas of internally emulating strdup() on a NULL pointer passage) You should address this.

Here is a complete implementation.
Good article from here. Describes timing and performance. I did not measure myself though.
http://www.howstuffworks.com/c35.htm
char* mystrcpy(char *dst, const char *src) {
char *ptr = dst;
while ((*dst++ = *src++) ) ;
return ptr;
}
int main(int argc, char *argv[]) {
const char *src = "This is C.\0";
char *dst = malloc(sizeof(char)*(strlen(src)+1)); //+1 for the null character
dst = mystrcpy(dst, src);
printf("%s",dst);
return 1;
}

Recently I faced same problem of above one using double pointer strcpy implementation
It might helpful to others below code
void strcpy_i( char **dst, const char *src )
{
*dst=(char *)malloc((strlen(src)+1)*sizeof(char));
char *tmp=*dst;
if(tmp == NULL || src == NULL)
return ;
while((*tmp++=*src++)!='\0');
}
int main()
{
char v[]="Vinay Hunachyal";
char *d=NULL;
strcpy_i(&d,v);
printf("%s",d);
return 0;
}

#include<stdio.h>
void main()
{
void mystrcpy(char *,char *);
char s1[100],s2[100];
char *p1;
char *p2;
p1=s1;
p2=s2;
printf("Enter the string to copy to s2...?\n");
scanf("%s",p1);
mystrcpy(p2,p1);
printf("S2 after copying = %s",p2);
}
void mystrcpy(char *p2,char *p1)
{
while(*p1!='\0')
{
*p2=*p1;
p2++;
p1++;
}
*p2='\0';
}
Its my solution..Simple to understand..

Related

How to copy char array in C without inner function

This is my code
char function(char *dst)
{
int i;
char *arr;
i = 0;
while(dst[i] != '\0')
{
arr[i] = dst[i];
i++;
}
dst[i] != '\0'
return(arr);
}
int main(void)
{
char a[] ="asdf"
printf("%s", function(a);
}
I want to copy *dst to empty *arr but my code didn't work.
I can't understand.
How can I copy array without inner function in C(ex_strcpy, memspy....)
Thank you
Apart from missing ; and making sure that the string being passed to the function is always a '\0' terminated one ( else the program will run into side effects strcpy causes ). and returning char* instead of char, you missed allocating memory for arr
// return char * instead of char
char* function(char *dst)
{
// Note - sizeof(dst) wont work
// Neither does sizeof(dst)/sizeof(char)
// allocate one extra for '\0'
size_t size_to_alloc = (strlen(dst) + 1) * (sizeof *arr);
char *arr = malloc( size_to_alloc );
char *p = arr;
for ( ; *dst ; p++, dst++)
*p = *dst;
*p = '\0';
return(arr);
}
If you want to dynamically copy an array, you'll need to allocate memory for the char array using malloc or other equivalent. Make sure you free the memory once you're done with it. I would suggest reading some posts on malloc and allocating memory in c.
This is probably a good place to start.
https://www.geeksforgeeks.org/dynamic-memory-allocation-in-c-using-malloc-calloc-free-and-realloc/
#include <stdio.h>
#include <stdlib.h>
char* function(char *dst, size_t length) {
int i;
// Allocating the memory needed for the char array.
char *arr = (char*) malloc (sizeof(char) * length);
i = 0;
while(dst[i] != '\0') {
arr[i] = dst[i];
i++;
}
arr[length - 1] = '\0';
return(arr);
}
int main(void) {
char a[] ="asdf";
// Getting length of the array
size_t length = sizeof(a) / sizeof(a[0]);
char* val = function(a, length);
printf("%s", val);
free(val);
}
You are missing the memory allocation and basically attempting to recode strdup. See below:
char *ft_strdup(const char *src)
{
char *dst;
int len;
len = 0;
while (src[len]) // no inner function
++len;
if (!(dst = malloc(sizeof(char) * (len + 1)))) // need 1 extra char to NULL terminate.
return NULL;
dst[len] = '\0';
while (--len > -1)
dst[len] = src[len];
return dst;
}
Note that it makes sense to code your own version of strdup and include it in your program library as this function is not part of the C Standard.
If there is a possibility of copying strings without using c functions, perhaps it can be done by doing what c functions do.
it may be interesting to see what strcpy does:
https://code.woboq.org/userspace/glibc/string/strcpy.c.html
char *
STRCPY (char *dest, const char *src)
{
return memcpy (dest, src, strlen (src) + 1);
}
infact it uses memcpy: https://code.woboq.org/gcc/libgcc/memcpy.c.html
and here the magic...
void *
memcpy (void *dest, const void *src, size_t len)
{
char *d = dest;
const char *s = src;
while (len--)
*d++ = *s++;
return dest;
}
and strlen: https://code.woboq.org/userspace/glibc/string/strlen.c.html
You can use memcpy() to copy memory directly, like in Memcpy, string and terminator and https://www.gnu.org/software/libc/manual/html_node/Copying-Strings-and-Arrays.html In C any string has to be terminated by \0 (sentinel value)
#include<stdio.h>
#include<string.h>
int main()
{
char source[] = "World";
char destination[] = "Hello ";
/* Printing destination string before memcpy */
printf("Original String: %s\n", destination);
/* Copies contents of source to destination */
memcpy (destination, source, sizeof(source));
/* Printing destination string after memcpy */
printf("Modified String: %s\n", destination);
return 0;
}
source : https://www.educative.io/edpresso/c-copying-data-using-the-memcpy-function-in-c

How can return the whole string, using only pointers

I can release this using arrays, but i want to make it working with pointers.
char *ft_strcpy(char *dest, char *src)
{
while (*src)
{
*dest = *src;
dest++;
src++;
// return dest; i want
}
*dest = '\0';
return (dest);
}
You are losing your string as you increment dest. At the end dest is pointing to a location which holds '\0'. You can use a temporary variable for modification while dest is still pointing to the beginning of the allocated memory.
char *temp = dest;
while (*src)
{
*temp = *src;
temp++;
src++;
}
*temp = '\0';
return (dest);
You miss the main C principles of pointer usage.
When you are using dest++; you have move the pointer to next byte.
In case you have return latest dest value - you will get pointer to end of your string instead first.
Another one - you don't need to return pointer, all pointer operations changing data into base string used like dest parameter in your example.
So when you will finish the function you can get pointer used as dest parameter in parent function and will see your changes complete.
In case you still want some construction of function with return pointer do next:
char *ft_strcpy(char *dest, char *src)
{
char * retValue = dest;
while (*src)
{
*dest = *src;
dest++;
src++;
// return dest; i want
}
*dest = '\0';
return (retValue);
}
Than you can get the pointer to first byte in the string as your return value.
As well answered by others concerning returning the original dest as below,
char *ft_strcpy(char *dest, char *src) {
char *original_dest = dest; // add
while (*src) {
*dest++ = *src++;
}
*dest = '\0';
// return dest;
return original_dest;
}
It is interesting to think about the impact of overlapping strings. The below will cause ft_strcpy() to loop on and on until code accesses outside buf[] leading to undefined behavior rather than a hoped for "hehello". The while (*src) { loop, in this case, over wrote the null character.
char buf[10] = "hello";
ft_strcpy(buf + 2, buf);
Such calls as above are pathological, yet allowed.
The standard strcpy() disallows this type of call with restrict. Simplistically, this means s1,s2 shall not overlap.
char *strcpy(char * restrict s1, const char * restrict s2);
How could code be written to handle overlapping strings?
Determine the length before copying.
Copy with memmove() which handles overlapping buffers.
char *ft_strcpy2(char *dest, const char *src) {
size_t sz = strlen(src) + 1;
memmove(dest, src, sz);
return dest;
}
int main(void) {
char buf[10] = "hello";
puts(ft_strcpy2(buf + 2, buf));
puts(buf);
}
Output
hello
hehello

Passing a C string and using it with a local pointer

Looking at this code from The Evils of Arduino Strings
void PrintString(const char *str) {
const char *p;
p = str;
while (*p) {
Serial.print(*p);
p++;
}
}
I was looking at reducing/compacting it. Firstly, this seems to be equivalent:
void PrintString(const char *str) {
const char *p;
p = str;
while (*p)
Serial.print(*p++);
}
Now, looking at the first two lines, how can I combine the following two lines, is it possible?
const char *p;
p = str;
Can I do this?
const char *p = str;
This would seem likely but looks unbalanced, in that there is a lack of an asterisk on the right hand side. I tried it and it seems to work but I was wondering whether it was correct, and worried that I would end up with some hard-to-track-down run-time error later on, further down the line.
However, this line below is clearly wrong (as it would change the pointer p to point to a location given by the value of the first character of the C string str):
const char *p = *str;
This is obfuscation. The original code is perfectly clear, there is no need to change anything. Your changes make it less readable.
What you can do to increase readability slightly, and this is a cosmetic change, is to use a for loop instead:
void PrintString (const char *str)
{
for(const char* p=str; *p != '\0'; p++)
{
Serial.print(*p);
}
}
Alternatively:
void PrintString (const char *str)
{
for(size_t i=0; str[i] != '\0'; i++)
{
Serial.print(str[i]);
}
}
const char *p = str;
This would seem likely but looks unbalanced, in that there is a lack of an asterisk on the right hand side.
If you separated the elements of the above snippet correctly it would not look "unbalanced" at all:
const char* is the type (a pointer to const characters)
p and str are the variables, both pointer (to const char)
You could write the above using some unconventional layout like this:
const char * /* Note the lack of a semicolon */
p = str;
The above code ends up with p being defined as a pointer to char and carrying the value of str.
You get same "result" for the below code
const char *p;
p = str;
Note that the former is called "initialisation", whereas the latter is called "assignment".
You can omit the use of the p pointer, use directly the str pointer argument, since it is a copy of the pointer to the constant content.
The changes made on str pointer don't affect the pointer used when calling the function, since the pointer is passed by value.
void PrintString(const char *str) {
while (*str) Serial.print(*str++);
}
How about replacing the while with for. Here's my take:
void PrintString(const char *str)
{
for(const char* p = str; *p; p++)
Serial.print(*p);
}
I think this could work, too:
void PrintString(const char *str) {
for(const char* p = str; *p; Serial.print(*(++p)))
;
}
As others have pointed out, we can replace p with str, since str is a local copy, just like any other variable passed as function argument.
void PrintString(const char* str) {
for( ; *str; Serial.print(*(++str)))
;
}

Strcpy implementation in C

So, I have seen this strcpy implementation in C:
void strcpy1(char dest[], const char source[])
{
int i = 0;
while (1)
{
dest[i] = source[i];
if (dest[i] == '\0')
{
break;
}
i++;
}
}
Which to me, it even copies the \0 from source to destination.
And I have also seen this version:
// Move the assignment into the test
void strcpy2(char dest[], const char source[])
{
int i = 0;
while ((dest[i] = source[i]) != '\0')
{
i++;
}
}
Which to me, it will break when trying to assign \0 from source to dest.
What would be the correct option, copying \0 or not?
The code should look like as follows:
char * strcpy(char *strDest, const char *strSrc)
{
assert(strDest!=NULL && strSrc!=NULL);
char *temp = strDest;
while(*strDest++ = *strSrc++); // or while((*strDest++=*strSrc++) != '\0');
return temp;
}
You can NOT delete the second line char *temp = strDest; and directly return strDest. This will cause error for the returned content. For example, it will not return correct value (should be 22) will checking the length of returned char *.
char src_str[] = "C programming language";
char dst_str[100];
printf("dst_str: %d\n", strlen(strcpy(dst_str, src_str)));
Both copy the terminator, thus both are correct.
Note that strcpy2() does the assignment (the copying) first, then the comparison. So it will copy the terminator before realizing it did, and stopping.
Also, note that functions whose names start with str are reserved, so neither of these are actually valid as "user-level" code.
You're wrong. Both copy the \0 (NUL terminator) character. You have to copy the NUL terminator character always or your string will be broken: you'll never know when/where it ends.
Both copy the terminator, thus both are correct.
strcpy2() does the copying first, then the compares. Thus it will copy the terminator and stops.
The functions whose names start with str are reserved, so use any other variables or naming types
It is recommended not to advance the input pointers to the source and destination memory spaces, since the pointers will be used in main right away.
I've mentioned alternate methodical syntax, where in case someone might wonder the code output.
void strcpy1(char * s, char * p)
{
char * temp1 = s;
char * temp2 = p;
while(*temp1 != '\0')
{
*temp2 = *temp1;
temp1++;
temp2++;
}
*temp2 = '\0';
}
void main()
{
char * a = "Hello";
char b[10];
strcpy1(a,b);
printf("%s", b);
return 0;
}
Both strcpy1() and strcpy2() does the same. Both copy the NUL character to the end of the destination array.
Here is full implementation. You do not have to consider the \0 at the end in the first string, it will be copied automatically from the second string as per logic
//str copy function self made
char *strcpynew(char *d, char *s){
char *saved = d;
while ((*d++ = *s++) != '\0');
return saved; //returning starting address of s1
}
//default function that is run by C everytime
int main(){
//FOR STRCPY
char s1[] = "rahul"; //initializing strings
char s2[] = "arora"; //initializing strings
strcpynew(s1, s2);
printf("strcpy: %s\n", s1); //updated string after strcpy
}
You can use this code, the simpler the better !
Inside while() we copy char by char and moving pointer to the next. When the last char \0 will pass and copy while receive 0 and stop.
void StrCopy( char* _dst, const char* _src )
{
while((*_dst++ = *_src++));
}
char * strcpy(char *strDest, const char *strSrc)
{
assert(strDest!=NULL && strSrc!=NULL);
assert(strSrc + strlen(strSrc) < d || strSrc > strDest); // see note
char *temp = strDest;
while(*strDest++ = *strSrc++)
;
return temp;
}
// without the check on line 4, the new string overwrites the old including the null deliminator, causing the copy unable to stop.
Both copy the '\0'. That's what you have to do if you want to fully emulate the original strcpy

How to allocate memory using double pointers in a function in C?

I want to know how to alloacte memory for a char pointer in a function using double pointer and write into the pointer.
I tried to write the following code but it crashes. What is the bug in this?
#include <stdio.h>
void myfunc(const char* src, char** dest)
{
*dest = (char*)malloc(200);
while(*(*dest++) = (*src++ != '\0'));
*(*(++dest)) = '\0';
}
void main()
{
char* src = "hello";
char* dest = null;
myfunc(src, &dest);
printf("%s\n",dest);
}
You've written a compare loop instead of a copy loop ('==' vs '='), and you are incrementing the wrong pointer when you write:
while(*(*dest++) == *src++);
(The additional line:
*(*(++dest)) = '\0';
is a late-breaking addition to the question. I'm not sure I want to try parsing that at all. It is not a part of the solution to the problem. See the discussion below.)
The easiest way to get that correct is probably:
char *tgt = *dest;
while ((*tgt++ = *src++) != '\0')
;
We can correct your code in phases (and I did so like this):
static void myfunc(const char* src, char** dest)
{
*dest = (char *)malloc(200);
char *tgt = *dest;
while ((*(tgt++) = *(src++)) != '\0')
;
}
This parenthesises the expressions in the loop fully. We can now substitute *dest for tgt:
static void myfunc(const char* src, char** dest)
{
*dest = (char *)malloc(200);
char *tgt = *dest;
while ((*((*dest)++) = *(src++)) != '\0')
;
printf("1: %s\n", tgt);
}
And this prints 1: hello, but the main program prints an empty line because you've modified *dest so it points to the NUL '\0' at the end of the copied string. So, you'd need to do:
static void myfunc(const char* src, char** dest)
{
*dest = (char *)malloc(200);
char *tgt = *dest;
while ((*((*dest)++) = *(src++)) != '\0')
;
printf("1: %s\n", tgt);
*dest = tgt;
}
And then main() will print the correct answer. But, if you're doing that dinking with tgt (an abbreviation for 'target'; I usually use dst for destination, but that is too close to your dest), you may as well avoid the complexity of incrementing *dest in the first place.
In fact, you should consider using:
#include <string.h>
...
strcpy(*dest, src);
to copy the string. Using strcpy() is probably better, as in 'faster' and 'simpler' and unequivocally correct.
Also, you should have:
#include <stdlib.h>
to declare malloc().
And the correct return type for main() is int:
int main()
{
...
return(0);
}
In C99, the return is (regrettably) optional and zero (success) will be assumed if it is missing; this matches the behaviour of C++98. In earlier versions of C, the return was not optional.
There are so many problems in that little snippet, I don't know where to start... To sum it up, you have made the code needlessly complex and therefore it ended up full of bugs.
Things to fix to make this code compile:
Unless this is code for an embedded system, or unless you are writing an operative
system, main must return int.
NULL is an upper-case constant in C. It is found in the library stddef.h.
The malloc function is found in stdlib.h, which must be included.
Serious bugs:
Never typecast the result of malloc. More info in the C FAQ and on this SO post.
Always free the memory allocated by malloc.
You assign the boolean result (true/false) of *src++ != '\0' to a character.
Widely-recognized bad & dangerous practice that leads to bugs:
Always declare pointers to string literals as const.
Never use assignment inside conditions. (MISRA-C:2004 13.1).
Never use ++ operators inside complex expressions (MISRA-C:2004 12.13).
Never put a semicolon at the end of a row containing a loop statement. (MISRA-C:2004 14.9)
Never use any statement without braces {} (MISRA-C:2004 14.8).
Poor style:
main() should always return.
Avoid "magic numbers", particularly when passing parameters to malloc.
Always check the result of malloc().
Useful hints:
calloc sets all of the allocated memory to zero, unlike malloc. If you use calloc you don't have to set them to zero manually.
Fixed code:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#define DYNAMIC_BUF_SIZE 200
void make_string (const char* src, char** dest)
{
*dest = calloc(DYNAMIC_BUF_SIZE, sizeof(char));
if(*dest == NULL)
{
/* error handling here */
}
char* dst = *dest;
*dst = *src;
while(*src != '\0')
{
dst++;
src++;
*dst = *src;
}
}
void delete_string (char* str)
{
free(str);
}
int main()
{
const char* src = "hello";
char* dest = NULL;
make_string (src, &dest);
printf("%s\n",dest);
delete_string(dest);
return 0;
}
EDIT: New version without strcpy(), as requested by OP.
//It seems that you don't understand the nature of char* and char**.
char *str = "hello! I am from China and i want to make friends with foreigners";
char **ptr = {"hello!","i want to learn spoken English","sinalym#163.com"};
//Allocate memory for a char** variable. Two steps as follows:
int length[3] = {6,31,16};
char **ptr2 = new char*[3];
for(int i = 0;i < length[i];i++)
*(ptr2 + i) = new char [length[i]];
//delete according to a reverse order.

Resources