I am currently recoding srtcat() from the standard C library and I have set up some checks to avoid overlap problems. The problem is that my program still enters the error handling.
Here is the code:
char *my_strcat(char *restrict dest, const char *restrict src)
{
size_t dest_len = 0, src_len = 0;
char *p = dest;
src_len = my_strlen(src);
if (!dest || !src)
return NULL;
dest_len = my_strlen(dest);
if (src >= dest && src < dest + dest_len) {
return NULL;
}
if (dest >= src && dest < src + src_len) {
return NULL;
}
while (*p != '\0') p++, dest_len++;
if (dest_len + src_len + 1 > sizeof(dest))
return NULL;
p = dest + dest_len;
while (*src != '\0')
*p++ = *src++;
*p = '\0';
return dest;
}
size_t my_strlen(const char *s)
{
size_t count = 0;
if (s != NULL) {
while (*s != 0) {
count++;
s++;
}
}
return count;
}
I tested this way :
int main(int argc, char **argv)
{
const char *src = "Hello";
char dest[100] = " world!";
char *test = my_strcat(dest, src);
printf("Src : %s Dest : %s\n", src, dest);
printf("Return adress : %p, Value : %s\n", test, test);
return 0;
}
According to gdb :
if (src >= dest && src < dest + dest_len)
1: dest = 0x7fffffffda70 " world!"
2: src = 0x555555557004 "Hello"
3: dest_len = 0
4: src_len = 5
Output
Src : Hello Dest : world!
Return adress : (nil), Value : (null)
Do you see the problem?
Update
Following your suggestions I have modified the code like this:
char *my_strcat(char *restrict dest, const char *restrict src, size_t d_size)
{
size_t dest_len = 0, src_len = 0;
char *p = dest;
if (!dest || !src)
return NULL;
src_len = my_strlen(src);
dest_len = my_strlen(dest);
if (src >= dest && src < dest + dest_len) {
return NULL;
}
if (dest >= src && dest < src + src_len) {
return NULL;
}
while (*p != '\0') p++, dest_len++;
if (dest_len + src_len + 1 > d_size)
return NULL;
p = dest + dest_len;
while (*src != '\0')
*p++ = *src++;
*p = '\0';
return dest;
}
And in the main : char *test = my_strcat(dest, src, sizeof(dest));
But it still doesn't work :
Src : Hello Dest : world!
Return adress : 0x7fff74bc5650, Value : world!
Having tried to guide toward understanding this problem, it seems best to present what should be working code (for study.) Sometimes too many words merely muddle the situation:
char *my_strcat(char *restrict dest, const char *restrict src, size_t d_size) {
if( !dest || !src )
return NULL;
size_t src_len = strlen( src );
size_t dest_len = strlen( dest );
if( dest_len + src_len + 1 > d_size )
return NULL;
char *p = dest + dest_len;
while( (*p++ = *src++ ) != '\0' )
;
return dest;
}
int main() {
const char *src = "Hello";
char dest[100] = " world!";
printf("Src : %s Dest : %s\n", src, dest);
char *test = my_strcat( dest, src, sizeof dest );
if( test )
printf("Value : %s\n", test );
return 0;
}
Now, one can experiment by shrinking the size of dest to something larger than " world!" but smaller than " world!Hello"... Perhaps 9 bytes???
And, now that the concatenation should be working (into a big enough buffer), adding the code to ensure there is no overlap of the actual character arrays. Known is the size of dest, and the length of src is measured.
dest_len + src_len + 1 > sizeof(dest)
sizeof(dest) is the size of the pointer sizeof(char*). If you want to check if the dest will be overflowed, you have to pass the size as an argument. See strlcpy or strncpy.
src >= dest
Note that comparing pointers that do not point to the same array is technically invalid. To bring some breeze of validity, you can do (uintptr_t)stc >= (uintptr_t)dest. How does pointer comparison work in C? Is it ok to compare pointers that don't point to the same array? Is comparing two pointers with < undefined behavior if they are both cast to an integer type? Why does comparing pointers with undefined behavior still give correct results? etc.
Related
This is the requirement for my code:
This function appends the src string to the dest string, overwriting the terminating null byte ('\0') at the end of dest, and then adds a terminating null byte.
Returns a pointer to the resulting string dest.
This is the output I am getting:
Hello
World!
Hello World!
Hello
Here is my code:
char *_strcat(char *dest, char *src) {
int lengthd = 0;
int lengths = 0;
int i = 0;
int j = 0;
int k = 0;
char tmp[10];
while (dest[i] != '\0') {
lengthd++;
i++;
}
while (src[k] != '\0') {
tmp[lengths] = src[k];
lengths++;
k++;
}
for (; j < lengths - 1; j++) {
dest[lengthd + 1] = tmp[j];
}
dest[lengthd + 1] = '\0';
return (dest);
}
int main(void) {
char s1[98] = "Hello ";
char s2[] = "World!\n";
char *ptr;
printf("%s\\n", s1);
printf("%s", s2);
ptr = _strcat(s1, s2);
printf("%s", s1);
printf("%s", s2);
printf("%s", ptr);
return (0);
}
Your code fails for multiple reasons:
you use a temporary array to make a copy of the source string: this array tmp has a fixed length of 10 bytes, which is too small if the source string is longer than 10 bytes. Otherwise you will have undefined behavior when you write beyond the end of this array.
there is really no need for this temporary array anyway.
the final loop stops at lengths - 1, hence you stop before the last byte of the copy.
you copy all bytes to the same position dest[lengthd + 1].
you finally set the null terminator at the same position again.
you never changed the null terminator at dest[lengthd] so the function appears to have no effect on dest.
the tests in main() cannot produce the output you posted, probably because of a typo in "%s\\n".
avoid using identifiers starting with an _.
Here is a modified version:
#include <stdio.h>
#include <string.h>
char *my_strcat(char *dest, char *src) {
int i = 0;
int k = 0;
/* find the offset of the null terminator in dest */
while (dest[i] != '\0') {
i++;
}
/* copy the bytes from the src string there */
while (src[k] != '\0') {
dest[i] = src[k];
i++;
k++;
}
/* set the null terminator */
dest[i] = '\0';
/* return the pointer to the destination array */
return dest;
}
int main(void) {
char s1[98] = "Hello ";
char s2[] = "World!";
char *ptr;
printf("%s\n", s1);
printf("%s", s2);
ptr = my_strcat(s1, s2);
printf("%s", s1);
printf("%s", s2);
printf("%s", ptr);
return 0;
}
Note that the source string is not modified and the offsets should have type size_t and can be incremented as a side effect of the assignment:
char *my_strcat(char *dest, const char *src) {
size_t i = 0;
size_t k = 0;
/* find the offset of the null terminator in dest */
while (dest[i] != '\0') {
i++;
}
/* copy the bytes from the src string there */
while (src[k] != '\0') {
dest[i++] = src[k++];
}
/* set the null terminator */
dest[i] = '\0';
/* return the pointer to the destination array */
return dest;
}
You can also use pointers instead of offsets:
char *my_strcat(char *dest, const char *src) {
/* use a working pointer to preserve dest for the return value */
char *p = dest;
/* find the offset of the null terminator in dest */
while (*p != '\0') {
p++;
}
/* copy the bytes from the src string there */
while (*src != '\0') {
*p++ = *src++;
}
/* set the null terminator */
*p = '\0';
/* return the pointer to the destination array */
return dest;
}
One final change: you can combine reading the source byte, copying to the destination and testing for the null terminator, which will have been copied already:
char *my_strcat(char *dest, const char *src) {
/* use a working pointer to preserve dest for the return value */
char *p = dest;
/* find the offset of the null terminator in dest */
while (*p != '\0') {
p++;
}
/* copy the bytes from the src string there */
while ((p++ = *src++) != '\0') {
/* nothing */
}
/* the null terminator was copied from the source string */
/* return the pointer to the destination array */
return dest;
}
At least due to the declaration of the character array tmp with the magic number 10
char tmp[10];
the function does not make a sense.
Moreover in this while loop
while (src[k] != '\0')
{
lengths++;
k++;
tmp[lengths] = src[k];
}
the first element of the array tmp is skipped.
Also in this for loop
for (; j < lengths-1; j++)
{
dest[lengthd + 1] = tmp[j];
}
the condition of the loop is incorrect. Also the expression dest[lengthd + 1] skips the terminating zero character of the string pointed to by the pointer dest. And all characters are written at the same position lengthd + 1.
Apart from this the names s1, s2 and ptr used in main were not declared.
The function can be declared and defined the following way
char * my_strcat( char *dest, const char *src )
{
char *p = dest;
while ( *p ) ++p;
while ( ( *p++ = *src++ ) != '\0' );
return dest;
}
and can be called like
char s1[13] = "Hello ";
const char *s2 = "World!";
puts( my_strcat( s1, s2 ) );
Another way to define the function using an approach similar to yours is the following
char * my_strcat( char *dest, const char *src )
{
size_t i = 0;
while ( dest[i] != '\0' ) ++i;
for ( size_t j = 0; src[j] != '\0'; j++ )
{
dest[i++] = src[j];
}
dest[i] '\0';
return dest;
}
So, I'm trying to build a string_split function to split a c-style string based on a delimiter.
Here is the code for the function:
char** string_split(char* input, char delim)
{
char** split_strings = malloc(sizeof(char*));
char* charPtr;
size_t split_idx = 0;
int extend = 0;
for(charPtr = input; *charPtr != '\0'; ++charPtr)
{
if(*charPtr == delim || *(charPtr+1) == '\0')
{
if(*(charPtr+1) == '\0') extend = 1; //extend the range by one for the null byte at the end
char* string_element = calloc(1, sizeof(char));
for(size_t i = 0; input != charPtr+extend; ++input, ++i)
{
if(string_element[i] == '\0')
{
//allocate another char and add a null byte to the end
string_element = realloc(string_element, sizeof(char) * (sizeof(string_element)/sizeof(char) + 1));
string_element[i+1] = '\0';
}
string_element[i] = *input;
}
printf("string elem: %s\n", string_element);
split_strings[split_idx++] = string_element;
//allocate another c-string if we're not at the end of the input
split_strings = realloc(split_strings, sizeof(char*) *(sizeof(split_strings)/sizeof(char*) + 1));
//skip over the delimiter
input++;
extend = 0;
}
}
free(charPtr);
free(input);
return split_strings;
}
Essentially, the way it works is that there are two char*, input and charPtr. charPtr counts up from the start of the input string the the next instance of the delimiter, then input counts from the previous instance of the delimiter (or the start of the input string), and copies each char into a new char*. once the string is built it is added to a char** array.
There are also some twiddly bits for skipping over delimiters and dealing with the end points of the input string. the function is used as so:
int main()
{
char* str = "mon,tue,wed,thur,fri";
char delim = ',';
char** split = string_split(str, delim);
return 1;
}
Anyway, it works for the most part, except the first char* in the returned char** array is corrupted, and is just occupied by random junk.
For example printing the elements of split from main yields:
split: α↨▓
split: tue
split: wed
split: thur
split: fri
Whats odd is that the contents of split_strings[0], the array of char* which returns the desired tokens is mon, as it should be for this example, right up until the final loop of the main for-loop in the string_split function, specifically its the line:
split_strings[split_idx++] = string_element;
which turns its contents from mon to Junk. Any help is appreciated, thanks.
Your function is incorrect at least because it tries to free the passed string
char** string_split(char* input, char delim)
{
//...
free(charPtr);
free(input);
return split_strings;
}
that in the case of your program is a string literal
char* str = "mon,tue,wed,thur,fri";
char delim = ',';
char** split = string_split(str, delim);
You may not free a string literal.
And the first parameter shall have the qualifier const.
There are numerous other errors in your function.
For example the expression sizeof(string_element)/sizeof(char) used in this statement
string_element = realloc(string_element, sizeof(char) * (sizeof(string_element)/sizeof(char) + 1));
does not yield the number of characters early allocated to the array pointed to by the pointer string_element. And there is no great sense to reallocate the array for each new character.
The function can look for example the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char ** string_split( const char *s, char delim )
{
size_t n = 1;
char **a = calloc( n, sizeof( char * ) );
while ( *s )
{
const char *p = strchr( s, delim );
if ( p == NULL ) p = s + strlen( s );
if ( p != s )
{
char *t = malloc( p - s + 1 );
if ( t != NULL )
{
memcpy( t, s, p - s );
t[p-s] = '\0';
}
char **tmp = realloc( a, ( n + 1 ) * sizeof( char * ) );
if ( tmp == NULL )
{
free( t );
break;
}
a = tmp;
a[n-1] = t;
a[n] = NULL;
++n;
}
s = p + ( *p != '\0' );
}
return a;
}
int main(void)
{
char* str = "mon,tue,wed,thur,fri";
char delim = ',';
char **split = string_split( str, delim );
for ( char **p = split; *p != NULL; ++p )
{
puts( *p );
}
for ( char **p = split; *p != NULL; ++p ) free( *p );
free( split );
return 0;
}
The program output is
mon
tue
wed
thur
fri
The final function for anyone wonder, should be pretty fool proof.
char** string_split(char* input, char delim, bool skip_delim)
{
assert(*input != '\0');
char** split_strings = malloc(sizeof(char*));
char* charPtr;
size_t split_idx = 0;
size_t num_allocated_strings = 1;
size_t extend = 0;
for(charPtr = input; *charPtr != '\0'; ++charPtr)
{
if(*charPtr == delim || *(charPtr+1) == '\0')
{
if(*(charPtr+1) == '\0') extend = 1; //extend the range by one for the null byte at the end
char* string_element = calloc(1, sizeof(char));
for(size_t i = 0; input != charPtr+extend; ++input, ++i)
{
if(string_element[i] == '\0')
{
//allocate another char and add a null byte to the end
char* temp = realloc(string_element, sizeof(char) * (strlen(string_element) + 1));
if(temp == NULL)
{
free(string_element);
free(split_strings);
break;
}
string_element = temp;
string_element[i+1] = '\0';
}
string_element[i] = *input;
}
split_strings[split_idx++] = string_element;
num_allocated_strings++;
//allocate another c-string
char** temp = realloc(split_strings, sizeof(char*) * num_allocated_strings);
if(temp == NULL)
{
free(string_element);
free(split_strings);
break;
}
split_strings = temp;
//skip over the delimiter if required
if(skip_delim) input++;
extend = 0;
}
}
split_strings[num_allocated_strings-1] = NULL;
return split_strings;
}
Hello and sorry if this questions is already answered (in the way I want to :-) ) but I think I have a memory problem.
Assuming the following C function (yes, this one is very dirty and not optimized):
char *strreplace(char **str, char *dst, char *replace) {
int replacestart = stringcompare(*str, dst), replaceend = strlen(dst), replacelen = strlen(replace);
char *tmp1 = (char *)malloc(sizeof(char) * (replacestart + 1)), *tmp2 = (char *)malloc(sizeof(char) * ((strlen(*str) - replaceend) + 1));
memset(tmp1, 0, sizeof(char) * (replacestart + 1));
memset(tmp2, 0, sizeof(char) * ((strlen(*str) - replaceend) + 1));
strncpy(tmp1, *str, replacestart);
strncpy(tmp2, *str + replacestart + replaceend, (strlen(*str) - (replaceend + replacestart)));
*str = realloc(*str, strlen(tmp1) + replacelen + strlen(tmp2));
memset(*str, 0, strlen(tmp1) + replacelen + strlen(tmp2));
strncpy(*str, tmp1, strlen(tmp1));
strncpy(*str + strlen(tmp1), replace, replacelen);
strncpy(*str + strlen(tmp1) + replacelen, tmp2, strlen(tmp2));
return *str;
}
As seen, it should replace *dst with *replace whithin **str.
This works basically as expected. Here's the problem:
The output (*str) is not cleard out with zeros after memsetting it and has still the wrong length, even after reallocating.
Means, if the string is longer after replacing, the last chars are cutted of *str.
In turn, if the string is shorter, old chars are at the end of the char string are found.
What did I wrong. Mentioned that I don't want to use sprintf and no C++-STL, just want to do this with pointers in C.
Other words, what would be the right way to replace a string in an c char string with pointers.
Thanks alot.
EDIT after reqeuest for more information
I use this function as following:
...open a textfile via FILE type, determining file lengts (fseek)...
char *filecontent = (char *)malloc(sizeof(char) * filesize);
if(filesize != fread(filecontent, sizeof(char), filesize, fd)) {
free(filecontent);
return -1;
}
streplace(&filecontent, "[#TOBEREPLACED#]", "replaced");
...doing other stuff with filecontent...
EDIT 2, adding stringcompare()
int stringcompare(const char *string, const char *substr) {
int i, j, firstOcc;
i = 0, j = 0;
while(string[i] != '\0') {
while(string[i] != substr[0] && string[i] != '\0') {
i++;
}
if(string[i] == '\0') {
return -1;
}
firstOcc = i;
while(string[i] == substr[j] && string[i] != '\0' && substr[j] != '\0') {
i++;
j++;
}
if(substr[j] == '\0') {
return firstOcc;
}
if(string[i] == '\0') {
return -1;
}
i = firstOcc + 1;
j = 0;
}
}
The logic of the function is not simple as it seems at the first glance.
You should decide what action to execute 1) if the source string is empty and 2) if the destination string is empty.
For example if the destination string is empty then the standard function strstr will return the address of the first character of the source string. However logically if dst is an empty string then the source string should not be changed except the case when it is in turn an empty string. In this case the function should just create a new string equal to the string replace.
Take into account that as the strings dst and replace are not changed within the function they should be declared with the qualifier const.
char * strreplace( char **str, const char *dst, const char *replace );
Also the function should report whether a new memory allocation was successful within the function by returning a null pointer in case when the allocation failed.
Taking all this into account the function can look the following way as it is shown in the demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * strreplace( char **str, const char *dst, const char *replace )
{
char *result = *str;
if ( *str[0] == '\0' )
{
if ( dst[0] == '\0' && replace[0] != '\0' )
{
char *result = malloc( strlen( replace ) + 1 );
if ( result )
{
strcpy( result, replace );
free( *str );
*str = result;
}
}
}
else if ( dst[0] != '\0' )
{
char *pos = strstr( *str, dst );
if ( pos != NULL )
{
size_t dst_n = strlen( dst );
size_t replace_n = strlen( replace );
result = ( char * )malloc( strlen( *str ) - dst_n + replace_n + 1 );
if ( result )
{
size_t n = pos - *str;
strncpy( result, *str, n );
strcpy( result + n, replace );
strcpy( result + n + replace_n, *str + n + dst_n );
}
free( *str );
*str = result;
}
}
return result;
}
int main(void)
{
const char *hello = "Hello everybody here";
char *str = malloc( sizeof( char ) );
str[0] = '\0';
if ( strreplace( &str, "", hello ) )
{
puts( str );
}
if ( strreplace( &str, "everybody", "Eurobertics" ) )
{
puts( str );
}
if ( strreplace( &str, "Hello", "Bye" ) )
{
puts( str );
}
if ( strreplace( &str, " here", "" ) )
{
puts( str );
}
if ( strreplace( &str, "Bye ", "" ) )
{
puts( str );
}
free( str );
return 0;
}
The program output is
Hello everybody here
Hello Eurobertics here
Bye Eurobertics here
Bye Eurobertics
Eurobertics
Your function looks overly complex. Here is a simple, working version:
char *strreplace(char **str, char *dst, char *replace) char *strreplace(char **str, char *dst, char *replace)
{
char *start, *tmp;
int n;
if ((start=strstr(*str,dst))==0) return(0);
n= (start-*str) + strlen(start+strlen(dst)) + strlen(replace) + 1;
tmp=malloc(n);
strncpy(tmp,*str,start-*str);
strcpy(tmp+(start-*str),replace);
strcat(tmp,start+strlen(dst));
free(*str);
*str= tmp;
return(tmp);
}
With test function:
void reptest(void)
{
char *src;
char rep[]= "brave new world";
src=malloc(strlen("Hello world of wonders")+1);
strcpy(src,"Hello world of wonders");
strreplace(&src,"world",rep);
printf("%s\n", src);
free(src);
}
Edit: my previous version forgot to copy the remainder. Fixed.
I want to remove a particular substring from a string for example my main string is "ababccdabce" and I want to remove "abc" from it so it will become "abcde".
I just wanted to know if there is a predefined function in C to do that, and if not, how to do it?
There is no predefined function in C to remove a given substring from a C string, but you can write one using strstr and memmove. Note that if you remove the substring in place, you cannot use memcpy nor strcpy because these have undefined behavior if the source and destination arrays overlap.
Here is the code:
#include <string.h>
char *strremove(char *str, const char *sub) {
size_t len = strlen(sub);
if (len > 0) {
char *p = str;
while ((p = strstr(p, sub)) != NULL) {
memmove(p, p + len, strlen(p + len) + 1);
}
}
return str;
}
Note that the resulting string may contain the substring as is the case in your example.
Netherwire suggested an optimisation:
char *strremove(char *str, const char *sub) {
size_t len = strlen(sub);
if (len > 0) {
char *p = str;
size_t size = 0;
while ((p = strstr(p, sub)) != NULL) {
size = (size == 0) ? (p - str) + strlen(p + len) + 1 : size - len;
memmove(p, p + len, size - (p - str));
}
}
return str;
}
Further honing the code, I came up with an even more efficient version using the 2 finger-method: only copying the fragments between matches starting after the first match:
char *strremove(char *str, const char *sub) {
char *p, *q, *r;
if (*sub && (q = r = strstr(str, sub)) != NULL) {
size_t len = strlen(sub);
while ((r = strstr(p = r + len, sub)) != NULL) {
memmove(q, p, r - p);
q += r - p;
}
memmove(q, p, strlen(p) + 1);
}
return str;
}
Here is the same method without any calls to memmove:
char *strremove(char *str, const char *sub) {
char *p, *q, *r;
if (*sub && (q = r = strstr(str, sub)) != NULL) {
size_t len = strlen(sub);
while ((r = strstr(p = r + len, sub)) != NULL) {
while (p < r)
*q++ = *p++;
}
while ((*q++ = *p++) != '\0')
continue;
}
return str;
}
char *stringcopywithpointer( const char *source)
{
int ii = 0;
int len = strlen(source) +1;
char *dest = (char*)malloc(sizeof(char)*len);
while(*source != '\0')
{
// dest[ii++] = *source++;
*dest++ = *source++;
}
// dest[ii] = '\0';
*dest = '\0';
printf("\n copied string = %s", dest1);
return dest;
}
I want to copy source string to destination string.
The above api is returning null.
If I use array of character (this I have commented) then this api works to me.
Please help me to understand the difference between
dest[ii++] = *source++
and
*dest++ = *source++;
You're incrementing dest during the while loop. You need to keep hold of a pointer to the start of the buffer to return from the function.
char *stringcopywithpointer( const char *source)
{
int ii = 0;
int len = strlen(source);
char *copy = malloc(len+1);
char* dest = copy;
while(*source != '\0')
{
*dest++ = *source++;
}
*dest = '\0';
printf("\n copied string = %s", copy);
return copy;
}
Note that you could save some code by using strcpy
char *stringcopywithpointer( const char *source)
{
int len = strlen(source);
char *copy = malloc(len+1);
strcpy(copy, source);
return copy;
}
and you could reduce this to a single line if you have access to the non-standard strdup
char *stringcopywithpointer( const char *source)
{
return strdup(source);
}
My opinion:
Avoid allocate memory in called function, better allot memory before calling a function
char *dest = ( char* ) malloc( sizeof( char ) * len ); // doesn't looks great
Irrespective of the machine, sizeof( char ) is always 1 byte. Less redundant is sizeof( char ) * len. Optimal would be malloc( sizeof( source ) ).
Pointers and arrays are related
You can either use
dest[i] = src[i];
*dst++ = *src++;
or
// assuming dst memory allocate by caller
while ( *dst++ = *src++);
1)
printf("\n copied string = %s", dest1);
should be
printf("\n copied string = %s", dest);
This could be a typo
2)
You can change:
while(*source != '\0')
{
*dest++ = *source++;
}
by
while(*dest++ = *source++);
3)
Concerning difference between dest[ii++] = *source++ and *dest++ = *source++;
There is no difference and should work if dest is defined in this way
char *dest = (char*)malloc(sizeof(char)*len);
If your array is define in this way:
char dest[len];
Then there is difference
You should not return an allocated string. This can easily lead to a memory leak.
Instead you should consider passing allocated memory into your function to copy it.
You can use your return value to return an error if anything went wrong.
This would change your signature to.
int stringcopywithpointer( char * dest, const char *source)
to make your code a little bit more versitile you could implement vargs and your signature would be:
int stringcopywithpointerf( char * dest, const * format, ... );
This is actually the already existing function sprintf.
int sprintf( char * dest, const * format, ... );
There are also secure variants of the function available and premade. You may want to consider using one of those.
If this is homework related take a look at this function:
char * myscpy(const char * SRC){
size_t size = strlen( SRC ) + 1 ;
char * START;
char * DST = ( char * ) malloc( size );
START = DST;
do
{
*DST = *SRC;
DST++;
SRC++;
}while( *SRC != 0 );
*DST = *SRC;
return START;
}
You likely want to add errorchecks to it like you had them in place (malloc etc.) in your original post.
"Please help me to understand the difference between dest[i++] and *dest++"
dest[i++] does not increment the pointer but the index to the pointer.
*dest++ increments the pointer after its original contendt was accessed.
Add char *dest1 = dest; right after malloc and then return dest1 and that will work.
Other possible change: replace while loop with post-condition loop (i.e. copy the zero byte first, then check if it was the end).
may be you need to add this line
char *stringcopywithpointer( const char *source)
{
int ii = 0;
int len = strlen(source) +1;
char *ptr = NULL;
char *dest = (char*)malloc(sizeof(char)*len);
/** No Error Checking for malloc is a strict no no **/
if(dest == NULL)
return NULL;
/** hold the dest adress in ptr as we are incrementing dest **/
ptr = dest;
while(*source != '\0')
{
// dest[ii++] = *source++;
*dest++ = *source++;
}
// dest[ii] = '\0';
*dest = '\0';
//printf("\n copied string = %s", dest1); ??
printf("\n copied string = %s", ptr); // ptr will have our copied String
/** so return ptr not dest **/
return ptr;
}