I know that this strcpy function below is incorrect, but I cannot seem to figure out the one or two things I need to change to fix it. Any help would be greatly appreciated as I am completely stuck on this:
void strcpy(char *destString, char *sourceString)
{
char *marker, *t;
for(marker = sourceString, t = destString; *marker; marker++, t++)
*t = *marker;
}
Well it depends on your environment..
For example I see a few things I don't like:
You do not check for input parameters to be != NULL. This will cause a *0 access
I see you are not terminating your string with the '\0' character (or 0).. So, after the loop (please intent.) add *t = 0;
strcpy() is a predefined function and you are trying to create your own strcpy function. so, when you compile your program, you are getting conflicting types error. So, first rename your function name.
If you want to implement your own strcpy(), then i would suggest to implement strncpy(). It will copy at-most n-1 bytes from source null-terminated character array to destination character array and also add null character at the end of the destination character array.
void strcpy(char *dest, const char *src, size_t n)
{
if ((dest == NULL) || (src == NULL))
return;
int i;
for(i=0; i<(n-1) && src[i]; i++)
dest[i] = src[i];
dest[i]='\0';
}
It wouldn't let buffer overflow.
Note - My implementation is different from standard library strncpy() implementation. The standard library function strncpy() copies at most n bytes of src. If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.
I know that this strcpy function below is incorrect, but I cannot seem to figure out the one or two things I need to change to fix it.
You only need to add null character at the end of destination array.
void strcpy(char *destString, char *sourceString)
{
char *marker, *t;
for(marker = sourceString, t = destString; *marker; marker++, t++)
*t = *marker;
*t='\0';
}
This is a very simple aproach:
void copy(char * src, char * dst){
while(*src != '\0'){
*dst = *src;
src++;
dst++;
}
*dst = '\0';
}
int main(int argc, char** argv){
char src [] = "hello";
char dst [] = "----";
copy(src, dst);
printf("src: %s\n", src);
printf("dst: %s\n", dst );
}
It's more or less like wildplasser comment. First you iterate over the src pointer. In c, if you have '\0' (in a well formed string) then you can exit because it is the final character. Ok, you iterate over the src pointer and assign the value of src (*src) to the value of dst (*dst) and then you only have to increase both pointers...
It's all
A very easy strcpy function would be:
int strcpy(char *dest,char *source)
{
if (source==NULL)
{
printf("The source pointer is NULL");
return 0;
}
if (dest==NULL)
{
dest=(char*)malloc((strlen(source)+1)*sizeof(char));
}
int i;
for (i=0;source[i]!='\0';i++)
{
dest[i]=source[i];
}
dest[i]='\0';
return 1;
}
You should have no problem copying strings this way. Always use indexes instead of pointer operations, it's easier imo.
If you use an IDE, you should learn to use the debug function to discover the errors and problems, usually when you deal with strings one of the most common RUNTIME problems is the lack of a '\0', which automatically make your string functions go to memory zones where they shouldn`t be.
Related
EDIT: I think I've understood how this concept works, this is my code
void delete_duplicate(char* str) {
if (str == NULL) {
exit(1);
}
for (size_t i = 0; str[i] != 0; i++) {
if (str[i] == str[i + 1]) {
str[i] = '\0';
}
}
}
int main(void) {
char str[] = "hhhhhhhheeeeeeeeyyyyyyyyyyy";
delete_duplicate(str);
return 0;
}
the output string is "00...0h0...000e0...000y" (with lots of zeros). if the string is "abbbb", the string becomes "a" and not "ab".
I was thinking about an algorithm for this exercise:
given a string, for example "ssttringg" the output must be "string". the function has to remove one character if and only if the current character and the next character are the same.
the exercise expects a function declared like this:
extern void delete_consecutive(char* str);
this is my algorithm:
loop: if the current character is equal to the next character, increment length by 1, and repeat until zero terminator is reached.
critical part: dynamic memory allocation.
allocate enough memory to store the output. Why did I say this is the critical part? because I have to do it in a void function, therefore I can't create a second string, allocate enough memory with malloc, and then return it at the end. I need to edit the original string instead. I think I can do it by means of a realloc, and by decrementing the size of the string. But I don't know how to do it, and more important: I don't know if it's legit to do it, without losing data. I think I'm overcomplicating the homework, but it's a void function, therefore I can't simply create a new string and copying characters in it, because I can't return it.
if it's not clear, I'll edit the question.
This pattern is called a retention scan (also a reduction scan, depending on your perspective), and is very common in algorithms that dictate discarding characters whilst keeping others, based on some condition. Often, the condition can change, and sometimes even the methods for starting the scan are somewhat altered
In it's simplest form, it looks something like this, as an example: An algorithm used to discard all but numeric (digit) characters:
Start with reader r and writer w pointers at the head of the string.
Iterate over the string from beginning to terminator using r. The r pointer will always be incremented exactly once per iteration.
For each iteration, check to see if the current character at r satisfies the condition for retention (in this case, is the character a digit char?). If it does, write it at w and advance w one slot.
When finished. w will point to the location where your terminator should reside.
#include <ctype.h>
void delete_nondigits(char *s)
{
if (s && *s)
{
char *w = s;
for (char *r = s; *r; ++r)
{
if (isdigit((unsigned char)*r))
*w++ = *r;
}
*w = 0;
}
}
Pretty simple.
Now, the algorithm for in-place consecutive-run compaction is more complicated, but has a highly similar model. Because retention is based on a prior-value already-retained you need to remember that last-kept value. You could just use *w, but the algorithm is actually easier to understand (and advance w) if you keep it in a separate memo char as you're about to see:
Start with reader r and writer w pointers as we had before, but starting at second slot of the string, and a single memo char variable c initialized to the first character of the string.
Iterate over the string using r until termination encounter. The r pointer will always be incremented exactly once per iteration.
For each iteration, check to see if the current character at *r is the same as the memo character c If it is, do nothing and continue to the next iteration.
Otherwise, if the character at *r is different than the memo character c, save it as the new value for c, write it to *w, and advance w one slot.
When finished, terminate the string by setting a terminator at *w.
The only hitch to this algorithm is supporting a zero-length string on inception, which is easily circumvented by checking that single condition first. I leave actually implementing it as an exercise for you. (hint: only do the above if (s && *s) is true).
You can modify the string passed as a parameter if it is modifiable.
Example:
void deleteFirstChar(char *str)
{
if(str && *str)
{
memmove(str, str + 1, strlen(str));
}
}
//illegal call
//string literals cannot be changed
void foo(void)
{
char *str = "Hello";
deleteFirstChar(str);
}
//legal call
void bar(void)
{
char str[] = "Hello";
deleteFirstChar(str);
}
This isn't an answer, but consider this code:
char str[] = "strunqg";
printf("before: %s\n", str);
modifystring(str);
printf("after: %s\n", str);
where the "modifystring" function looks like this:
void modifystring(char *p)
{
p[3] = 'i';
p[5] = p[6];
p[6] = '\0';
}
This is totally "legit". It would not work, however, to call
char *str = "strunqg";
modifystring(str); /* WRONG */
or
modifystring("strunqg"); /* WRONG */
Either of these second two would attempt to modify a string literal, and that's not copacetic.
void delete_duplicate(char* str)
{
if(str && *str)
{
char *writeTo = str, *readFrom = str;
char prev = 0;
while(*readFrom)
{
if(prev != *readFrom)
{
prev = *readFrom++;
*writeTo++ = prev;
}
else
{
readFrom++;
}
}
*writeTo = 0;
}
}
int main(void)
{
char str[] = "hhhhhhhheeeeeeeeyyyyyyyyyyy";
delete_duplicate(str);
printf("`%s`\n", str);
return 0;
}
Like a question below, i have to use the pointer concept to copy array from one to another in mystrcpy2 function, unlike mystrcpy function that does not use the pointer concept. Anyway, I typed my answer, " dest = src;" which seemed to be overly simple but right answer for me. But when I type in the input, like "Hello World", it shows like "Hello World ???" like strange letters in the back. But when I type short words like "abc", the result is exactly "abc."
Is it simply a matter of computer or did I do something wrong?
I"m also wondering if "while (*src) *dest++=*src++;" works as well?
/*Complete the mystrcpy2() function that copies the null-terminated string pointed by src to the string pointed by dest.
The mystrcpy2() should give the same result with the mystrcpy() that uses an index based array traversal approach.
Note that adding local variables are not allowed in implementing the mystrcpy2().
Write and submit the source code of your "mystrcpy2()" function.
*/
#include <stdio.h>
void mystrcpy(char dest[], char src[])
{
int i=0,j=0;
while (src[i])
dest[j++] = src[i++];
}
void mystrcpy2(char *dest, char *src)
{
dest = src;
}
int main(void)
{
char mystr1[256];
char mystr2[256];
gets(mystr1);
mystrcpy(mystr2, mystr1);
puts(mystr2);
mystrcpy2(mystr2, mystr1);
puts(mystr2);
return 0;
}
Your implementation of mystrcpy2 does not copy anything. In fact, it does nothing at all. When you execute dest = src, you are copying the memory location pointed to by the src variable, not the data at that location. To actually copy the data, you need to deference the pointer, using '*'. So you would do
*dest = *src;
This copies the data from src to dest. But it only copies one character. You need to increment src and dest and then do this again to copy the next character, and you need to keep doing this until you hit the string terminator i.e. until *src == 0. Here's the full implementation.
void mystrcpy2(char *dest, char *src)
{
while (*src != 0) {
*dest = *src;
dest++;
src++;
}
// don't forget to add a terminator
// to the copied string
*dest = 0;
}
And here's the exact same thing in a shorter version.
void mystrcpy2(char *dest, char *src)
{
while (*(dest++) = *(src++));
}
I have to create a copy of some elements of the standard library in C and I have to create a copy of strcat. So I have to create a function that concatenate two strings in C. I know arrays in C can't change the allocated size. The only fonction i'm allowed to use is copies i made of strlen, strstr, and write() ... My code looks like this :
char *my_strcat(char *dest, char *src)
{
int dest_size;
int src_size;
int current_pos;
int free_space;
int pos_in_src;
src_size = my_strlen(src);
dest_size = my_strlen(dest);
while (dest[current_pos] != '\0')
current_pos = current_pos + 1;
free_space = dest_size - current_pos;
if (free_space < src_size)
return (0);
while (src[pos_in_src] != '\0')
{
dest[current_pos] = src[pos_in_src];
pos_in_src = pos_in_src + 1;
current_pos = current_pos + 1;
}
return (dest);
}
But I don't know how to declare my dest and src in the main.
I don't know how to create an array with a big size, declare it as a string like dest = "Hello\0" but this array has to still contains more than 6 characters.
Can you help me please ?
char dest[19] = "epite";
char *src = "chor42spotted";
my_strcat(dest, src);
Also, read the man for strcat(3)
the dest string must have enough space for the result.
https://linux.die.net/man/3/strcat
So your function is behaving incorrectly, you do not need to check that you have enough free space in dest
You want a function mystrcat which behaves exactly like stdlib strcat.
So the prototype is
/*
concatenate src to dest
dest [in / out] - the string to add to (buffer must be large enough)
src [in] - the string to concatenate.
Returns: dest (useless little detail for historical reasons).
*/
char *mystrcat(char *dest, const char *src);
Now we call it like this
int main(void)
{
char buff[1024]; // nice big buffer */
strcpy(buff, "Hello ");
mystrcat(buff, "world");
/* print the output to test it */
printf("%s\n", buff);
return 0;
}
But I'm not going to write mystrcat for you. That would make your homework exercise pointless.
The 1st parameter of the array simply has to be large enough to contain both strings + one null terminator. So if you for example have "hello" and "world", you need 5 + 5 +1 = 11 characters. Example:
#define LARGE_ENOUGH 11
int main (void)
{
char str[LARGE_ENOUGH] = "hello";
my_strcat(str, "world");
puts(str); // gives "helloworld"
}
In real world applications, you would typically allocate space for the array to either be same large number (couple of hundred bytes) or with a length based on strlen calls.
As for the implementation itself, your solution is needlessly complicated. Please note that the real strcat leaves all error checking to the caller. It is most likely implemented like this:
char* strcat (char* restrict s1, const char* restrict s2)
{
return strcpy(&s1[strlen(s1)], s2);
}
The most important part here is to note the const-correctness of the s2 parameter.
The restrict keywords are just micro-optimizations from the C standard, that tells the compiler that it can assume that the pointers point at different memory areas.
If you wish to roll out your own version with no library function calls just for fun, it is still rather easy, you just need two loops. Something like this perhaps:
char* lolcat (char* restrict s1, const char* restrict s2)
{
char* s1_end = s1;
while(*s1_end != '\0') // find the end of s1
{
s1_end++;
}
do // overwrite the end of s1 including null terminator
{
*s1_end = *s2;
s1_end++;
s2++;
} while(*s1_end != '\0'); // loop until the null term from s2 is copied
return s1;
}
Recently I attended an interview where they asked me to write a C program to concatenate two strings without using strcat(), strlen() and strcmp() and that function should not exceed two (2) lines.
I know how to concatenate two strings without using strcat(). But my method has nearly 15 lines. I dont know how to write it in two lines.
I expect they wanted something like this:
void mystrcat(char * dest, const char * src)
{
//advance dest until we find the terminating null
while (*dest) ++dest;
//copy src to dest including terminating null, until we hit the end of src
//Edit: originally this:
//for (; *dest = *src, *src; ++dest, ++src);
//...which is the same as this
for (; *dest = *src; ++dest, ++src);
}
It doesn't return the end of the concatenated string like the real strcat, but that doesn't seem to be required.
I don't necessarily know if this sort of thing is a good interview question - it shows that you can code tersely, and that you know what strcat does, but that's about it.
Edit: as aib writes, the statement
while (*dest++ = *src++);
...is perhaps a more conventional way of writing the second loop (instead of using for).
Given that the task was to concatenate two strings, not to create a duplicate of strcat, I'd go with the simple option of creating a completely new string that is a combination of the two.
char buffer[REASONABLE_MAX] = {0};
snprintf(buffer, REASONABLE_MAX - 1, "%s%s", string1, string2);
The proper answer to that question is that the question would demonstrate a skill that it is bad to have. They are wanting you to demonstrate the ability to write hacker code. They are wanting you to invent your own implementation of things provided already by every C compiler, which is waste of time. They are wanting you to write streamlined code which, by definition, is not readable. The 15 line implementation is probably better if it is more readable. Most projects do not fail because the developers wasted 150 clock cycles. Some do fail because someone wrote unmaintainable code. If you did have to write that, it would need a 15 line comment. So my answer to that would be, show me the performance metrics that defend needing to not use the standard libraries and requiring the most optimal solution. Time is much better spent on design and gathering those performance metrics.
Never forget - you are also interviewing them.
//assuming szA contains "first string" and szB contains "second string"
//and both are null terminated
// iterate over A until you get to null, then iterate over B and add to the end of A
// and then add null termination to A
// WARNING: memory corruption likely if either string is not NULL terminated
// WARNING: memory corruption likely if the storage buffer for A was not allocated large
// enough for A to store all of B's data
// Justification: Performance metric XXX has shown this optimization is needed
for(int i=0; szA[i]!='\0'; i++);
for(int j=0; (j==0)||(szB[j-1]!='\0'); j++) szA[i+j] = szB[j];
*edit, 9/27/2010
After reading some other solutions to this, I think the following is probably the best code answer:
//Posted by Doug in answer below this one
void my_strcat(char * dest, const char * src)
{
while (*dest) ++dest;
while (*dest++ = *src++);
}
But I would follow that up with a safe version of that:
void my_safe_strcat(char * dest, const unsigned int max_size, const char * src)
{
int characters_used=0;
while (*dest) { ++dest; characters_used++; }
while ( (characters_used < (max_size-1) ) && (*dest++ = *src++) ) characters_used++;
*dest = 0; //ensure we end with a null
}
And follow that up with (full answer, which compiler will optimize to be the same as above, along with application which was the real question):
void my_readable_safe_strcat(char * dest, const unsigned int max_size, const char * src)
{
unsigned int characters_used = 0;
while (*dest != '\0')
{
++dest;
characters_used++;
}
while ( (characters_used < (max_size-1) ) && (*dest = *src) )
{
dest++;
src++;
characters_used++;
}
*dest = 0; //ensure we end with a null
}
int _tmain(int argc, _TCHAR* argv[])
{
char szTooShort[15] = "First String";
char szLongEnough[50] = "First String";
char szClean[] = "Second String";
char szDirty[5] = {'f','g','h','i','j'};
my_readable_safe_strcat(szTooShort,15,szClean);
printf("This string should be cut off:\n%s\n\n",szTooShort);
my_readable_safe_strcat(szLongEnough,50,szClean);
printf("This string should be complete:\n%s\n\n",szLongEnough);
my_readable_safe_strcat(szLongEnough,50,szDirty);
printf("This string probably has junk data in it, but shouldn't crash the app:\n%s\n\n",szLongEnough);
}
Two lines? Bwah...
void another_strcat(char* str1, const char* str2)
{
strcpy(strchr(str1, '\0'), str2);
}
EDIT: I'm very upset that people are so against strcpy and strchr. Waah! So, I thought I'd play by the spirit of the rules:
char thing(char* p, const char* s)
{
return *p ? thing(&p[1], s) : *s ? (*p++ = *s++, thing(p, s)) : *p = '\0';
}
I still can't understand how anyone would take 2 whole lines ;-P.
I tested this bit in VS2008, and it worked fine.
void NewStrCat(char* dest, const char* src)
{
while (*dest) ++dest;
while (*dest++ = *src++);
}
Any function can be made to fit in a single line by simply removing all the \n.
However, I think you're looking for this answer:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char string1[32] = "Hello";
char string2[] = ", World!";
char *dst = string1 + strlen(string1);
char *src = string2;
while (*dst++ = *src++); //single statement
printf("\"%s\"\n", string1);
return EXIT_SUCCESS;
}
The explanation is rather simple:
src++ returns a pointer to the current character being copied before incrementing to point to the next one. * dereferences this pointer, and a similar expression on the LHS copies it to dst. Result of the whole = expression is the character that was copied, hence a simple while loops it until a \0 is encountered and copied.
However:
strcat() is easier to read and possibly much faster. Any other solution is feasible only when strcat() is not available. (Or when you're in an interview, apparently.)
And replace strcat() above with strncat() unless you're really really sure the destination string is big enough.
Edit: I missed the part about strlen() being disallowed. Here's the two-statement function:
void my_strcat(char * restrict dst, const char * restrict src)
{
while (*dst) ++dst; //move dst to the end of the string
while (*dst++ = *src++); //copy src to dst
}
Note that the standard strcat() function returns the original value of dst.
One line:
sprintf(string1, "%s%s", string1, string2);
(Note that this might possibly invoke undefined behavior.)
Addendum
The ISO C99 standard states that:
If copying takes place between objects that overlap, the behavior is undefined.
That being said, the code above will still probably work correctly. It works with MS VC 2010.
I have a feeling such questions are meant to be elimination questions rather than selection. It is easier to eliminate candidates for them based on such convoluted questions rather than select candidates by asking them more real world questions.
Just a rant from me, since I am also looking for a job and facing such questions and answered quite a few of them thanks to SO!
void StringCatenation(char *str1,char *str2)
{
int len1,i=0;
for(len1=0;*(str1+len1);len1++);
do{
str1[len1+i]=str2[i];
i++;
}
while(*(str2+i);
}
void my_strcat(char* dest, const char* src)
{
while (*dest) ++dest;
while (*dest++ = *src++);
*dest = '\0';
}
Destination string must end with NULL terminated.
I'm trying to learn C programming and spent some time practicing with pointers this morning, by writing a little function to replace the lowercase characters in a string to their uppercase counterparts. This is what I got:
#include <stdio.h>
#include <string.h>
char *to_upper(char *src);
int main(void) {
char *a = "hello world";
printf("String at %p is \"%s\"\n", a, a);
printf("Uppercase becomes \"%s\"\n", to_upper(a));
printf("Uppercase becomes \"%s\"\n", to_upper(a));
return 0;
}
char *to_upper(char *src) {
char *dest;
int i;
for (i=0;i<strlen(src);i++) {
if ( 71 < *(src + i) && 123 > *(src + i)){
*(dest+i) = *(src + i) ^ 32;
} else {
*(dest+i) = *(src + i);
}
}
return dest;
}
This runs fine and prints exactly what it should (including the repetition of the "HELLO WORLD" line), but afterwards ends in a Segmentation fault. What I can't understand is that the function is clearly compiling, executing and returning successfully, and the flow in main continues. So is the Segmentation fault happening at return 0?
dest is uninitialised in your to_upper() function. So, you're overwriting some random part of memory when you do that, and evidently that causes your program to crash as you try to return from main().
If you want to modify the value in place, initialise dest:
char *dest = src;
If you want to make a copy of the value, try:
char *dest = strdup(src);
If you do this, you will need to make sure somebody calls free() on the pointer returned by to_upper() (unless you don't care about memory leaks).
Like everyone else has pointed out, the problem is that dest hasn't been initialized and is pointing to a random location that contains something important. You have several choices of how to deal with this:
Allocate the dest buffer dynamically and return that pointer value, which the caller is responsible for freeing;
Assign dest to point to src and modify the value in place (in which case you'll have to change the declaration of a in main() from char *a = "hello world"; to char a[] = "hello world";, otherwise you'll be trying to modify the contents of a string literal, which is undefined);
Pass the destination buffer as a separate argument.
Option 1 -- allocate the target buffer dynamically:
char *to_upper(char *src)
{
char *dest = malloc(strlen(src) + 1);
...
}
Option 2 -- have dest point to src and modify the string in place:
int main(void)
{
char a[] = "hello world";
...
}
char *to_upper(char *src)
{
char *dest = src;
...
}
Option 3 -- have main() pass the target buffer as an argument:
int main(void)
{
char *a = "hello world";
char *b = malloc(strlen(a) + 1); // or char b[12];
...
printf("Uppercase becomes %s\n", to_upper(a,b));
...
free(b); // omit if b is statically allocated
return 0;
}
char *to_upper(char *src, char *dest)
{
...
return dest;
}
Of the three, I prefer the third option; you're not modifying the input (so it doesn't matter whether a is an array of char or a pointer to a string literal) and you're not splitting memory management responsibilities between functions (i.e., main() is solely responsible for allocating and freeing the destination buffer).
I realize you're trying to familiarize yourself with how pointers work and some other low-level details, but bear in mind that a[i] is easier to read and follow than *(a+i). Also, there are number of functions in the standard library such as islower() and toupper() that don't rely on specific encodings (such as ASCII):
#include <ctype.h>
...
if (islower(src[i])
dest[i] = toupper(src[i]);
As others have said, your problem is not allocating enough space for dest. There is another, more subtle problem with your code.
To convert to uppercase, you are testing a given char to see if it lies between 71 ans 123, and if it does, you xor the value with 32. This assumes ASCII encoding of characters. ASCII is the most widely used encoding, but it is not the only one.
It is better to write code that works for every type of encoding. If we were sure that 'a', 'b', ..., 'z', and 'A', 'B', ..., 'Z', are contiguous, then we could calculate the offset from the lowercase letters to the uppercase ones and use that to change case:
/* WARNING: WRONG CODE */
if (c >= 'a' && c <= 'z') c = c + 'A' - 'a';
But unfortunately, there is no such guarantee given by the C standard. In fact EBCDIC encoding is an example.
So, to convert to uppercase, you can either do it the easy way:
#include <ctype.h>
int d = toupper(c);
or, roll your own:
/* Untested, modifies it in-place */
char *to_upper(char *src)
{
static const char *lower = "abcdefghijklmnopqrstuvwxyz";
static const char *upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static size_t n = strlen(lower);
size_t i;
size_t m = strlen(src);
for (i=0; i < m; ++i) {
char *tmp;
while ((tmp = strchr(lower, src[i])) != NULL) {
src[i] = upper[tmp-lower];
}
}
}
The advantage of toupper() is that it checks the current locale to convert characters to upper case. This may make æ to Æ for example, which is usually the correct thing to do. Note: I use only English and Hindi characters myself, so I could be wrong about my particular example!
As noted by others, your problem is that char *dest is uninitialized. You can modify src's memory in place, as Greg Hewgill suggests, or you can use malloc to reserve some:
char *dest = (char *)malloc(strlen(src) + 1);
Note that the use of strdup suggested by Greg performs this call to malloc under the covers. The '+ 1' is to reserve space for the null terminator, '\0', which you should also be copying from src to dest. (Your current example only goes up to strlen, which does not include the null terminator.) Can I suggest that you add a line like this after your loop?
*(dest + i) = 0;
This will correctly terminate the string. Note that this only applies if you choose to go the malloc route. Modifying the memory in place or using strdup will take care of this problem for you. I'm just pointing it out because you mentioned you were trying to learn.
Hope this helps.