Thread: strcpy()

  1. #1
    Registered User
    Join Date
    Apr 2015
    Posts
    42

    strcpy()

    Hi,

    I have a question about this function.

    Code:
    char a[4] = {"aaa"};
    strstr(a, "bb");
    When I do this after function copies bb to the array it puts '\0' ? I mean last for array would be 'b' 'b' 'a' '\0' or 'b' 'b' '\0' '\0'.

    I am trying to learn the basics of searching a string, finding and changing them with another string.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,271
    The string literal "aaa" comes with the null character, so yes, a will be initialised to be terminated with the null character. That said, it is simpler here to write:
    Code:
    char a[4] = "aaa";
    or:
    Code:
    char a[] = "aaa";
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    a_capitalist_story
    Join Date
    Dec 2007
    Posts
    2,671
    The answer is in the documentation:

    Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).
    Bolding added.

  4. #4
    Registered User
    Join Date
    Apr 2015
    Posts
    42
    I guess it adds \0 at the end too. Well let me change my question. I want user to enter 3 strings. 2nd string will be searched through out 1st string and if found will be changed to 3rd string.

    For example
    1st string: aaa ccc
    2nd string: ccc
    3rd string: bbb
    1st string: aaa bbb

    Note that ccc and bbb are same sizes (3 chars). I also want to be able to change the string with a different size of string.

    Example:
    1st string: aaabcd
    2nd string: aaa
    3rd string: a
    1st string: abcd

  5. #5
    Registered User
    Join Date
    Apr 2015
    Posts
    42
    Code:
    int main() {
        char str1[100];
        char str2[100];
        char str3[100];
    
    
        printf("Enter a sentence: ");
        fgets(str1, 100, stdin);
        printf("Enter a string you want to change: ");
        fgets(str2, 100, stdin);
        printf("New string: ");
        fgets(str3, 100, stdin);
        puts(str1);
    
    
        int i;
        for(i = 0; str2[i] != '\0'; i++) {
    
    
        }
        strncpy(strstr(str1, str2), str3, sizeof(str1));
        puts(str1);
        return 0;
    }
    I found strncpy which works the same way as strcpy but doesn't add the eol operator at after copy proccess. The thing is this code isn't working. After executing the program when it comes to strncpy line it stops working.

    As far as I know strstr(str1, str2) should return me the starting address of str2 in str1. I mean let's say str1 is aabbc starting with address of 100. If str2 is bb then it should return me the value of 102. Also I should be able to use that address inside strncpy. Why program stops working at that line?

  6. #6
    Registered User
    Join Date
    Jun 2011
    Posts
    4,509
    A development process

    Let's start small, by just verifying we find the substring.

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main() {
        char str1[100];
        char str2[100];
        char *p;
    
    
        printf("Enter a sentence: ");
        fgets(str1, 100, stdin);
        printf("Enter a string you want to change: ");
        fgets(str2, 100, stdin);
    
        p = strstr(str1,str2);
    
        if(p == NULL)
            printf("\nerror finding substring\n");
        else
            printf("\n%s\n",p);
    
        return 0;
    }
    Code:
    /*
    Enter a sentence: aabbcc
    Enter a string you want to change: bb
    
    error finding substring
    */
    Oh, we didn't find the substring in the string! The reason is because "fgets()" stores the newline if there is room. So, in the given example:

    str1 = "aabbcc\n"
    str2 = "bb\n"

    The string "bb\n" is not a substring of the first. (This is why error-checking is so important.)

    See the FAQ for how to get rid of the newline (if present) from an "fgets()" read -> FAQ > Get a line of text from the user/keyboard (C) - Cprogramming.com

    This won't solve all the problems, but will at least get you started.

  7. #7
    Registered User
    Join Date
    Apr 2015
    Posts
    42
    @Matticus

    yeah I forgot that. Well I fixed it.

    aaa bbb ccc
    aaa
    ddd

    gives me ddd. So even strncpy adds \0 after copy process. Well then what is the difference between strncpy and strcpy?

  8. #8
    Registered User
    Join Date
    Jun 2011
    Posts
    4,509
    From man strncpy:

    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.
    So yes, the '\0' is included if is part of the source string, within the number of bytes specified.

    Just to be clear ... can you tell us exactly what you want to do, and exactly what is really happening instead? I suspect I know the issue and how to correct it, but want to be sure.

  9. #9
    Registered User
    Join Date
    Jun 2011
    Posts
    4,509
    Oh, and be sure to provide your updated code, too

  10. #10
    Registered User
    Join Date
    Apr 2015
    Posts
    42
    Thanks for replies. Here is my last code
    Edit: Not my last code anymore I changed it and made another post below. Didn't deleted or edited this in case you wonder my process.

    Code:
    int main() {
        char str1[100];
        char str2[100];
        char str3[100];
    
    
        printf("Enter a sentence: ");
        fgets(str1, 100, stdin);
        printf("Enter a string you want to change: ");
        fgets(str2, 100, stdin);
        printf("New string: ");
        fgets(str3, 100, stdin);
        puts(str1);
        *(strchr(str1, '\n')) = '\0';
        *(strchr(str2, '\n')) = '\0';
        *(strchr(str3, '\n')) = '\0';
    
    
        int i;
        for(i = 0; str2[i] != '\0'; i++){}
        char *p = strstr(str1, str2);
        char tmp = *(p+i);
        strncpy(p, str3, 50);
        *(p+i) = tmp;
        puts(str1);
        return 0;
    }
    I want to explain what I want to do by an example. User will enter 3 strings and 1 string will be printed.

    For example entered these 3 strings:

    1st: aaa bbb ccc.
    2nd: aaa
    3rd: ddd

    printed string: ddd bbb ccc.

    With the code I gave above I get

    ddd

    That's because strncopy adds '\0' but as you can see I tried to change it in code. First I found out how many characters are there in the 2nd string. Then created a char named tmp and I saved the *(p+i) there.
    At this example 2nd string is aaa so i is 3. *(p+i) points out the blank at the 1st string after aaa because it will be changed into '\0' so I want to save what is there at tmp and then put it back after strncpy. Since what I get printed out is only "ddd" it obviously doesn't work.

    Edit: I solved the problem by changing "strncpy(p, str3, 50);" into "strncpy(p, str3, i);" but still it bothers me why my way didn't work. Also this is not the end of my problems I explained what I wanted to do further more below.

    --------------------------------

    This is only the first step. My objective is searching 2nd string in the 1st string (no need for checking if there is a 2nd string in the 1st string) then change it(them) with the 3rd string. In this example there is only one 2nd string in the 1st string which is aaa.

    My 2nd step is changing aaa in this string "aaa bbb aaa." into ddd so outcome should be "ddd bbb ddd."

    Last step is really bothering me. At this step I want 2nd and 3rd strings to have different sizes.

    For example:

    aaa bbb aaa.
    aaa
    x

    will print: x bbb x.

    A little help would be appreciated
    Last edited by Vsky; 04-02-2015 at 01:37 PM.

  11. #11
    Registered User
    Join Date
    Apr 2015
    Posts
    42
    Didn't want to mess up earlier post. This is my final code and I solved the 2nd step too.

    Code:
    int main() {    
        char str1[100];
        char str2[100];
        char str3[100];
    
    
        printf("Enter a sentence: ");
        fgets(str1, 100, stdin);
        printf("Enter a string you want to change: ");
        fgets(str2, 100, stdin);
        printf("New string: ");
        fgets(str3, 100, stdin);
        *(strchr(str1, '\n')) = '\0';
        *(strchr(str2, '\n')) = '\0';
        *(strchr(str3, '\n')) = '\0';
    
    
        int i;
        for(i = 0; str2[i] != '\0'; i++){}
        char *p = strstr(str1, str2);
        strncpy(p, str3, i);
        while( p != NULL ) {
            p = strstr(p+1, str2);
            if( p != NULL )
                strncpy(p, str3, i);
        }
        puts(str1);
        return 0;
    }
    Example:

    aaa bbb aaa.aaa.aaa.
    aaa
    xxx

    prints: xxx bbb xxx.xxx.xxx.

    Now we came to the last part. I explained this before this post. I want 2nd and 3rd string to have different number of characters.

    Example:

    aaa bbb aaa.aaa.aaa.
    aaa
    R

    prints: R bbb R.R.R.

    I cannot think a solution for this since it will change other characters' index as well as addresses. Need a hand here
    Last edited by Vsky; 04-02-2015 at 01:41 PM.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,271
    This is wrong because fgets will not store the newline character if it was not read:
    Code:
    *(strchr(str1, '\n')) = '\0';
    Rather, you should write:
    Code:
    char *p = strchr(str1, '\n');
    if (p)
    {
        *p = '\0';
    }
    alternatively:
    Code:
    str1[strcspn(str1, "\n")] = '\0';
    This:
    Code:
    for(i = 0; str2[i] != '\0'; i++){}
    should be replaced by a call to strlen:
    Code:
    i = strlen(str2);
    This is not safe since strstr could return a null pointer:
    Code:
    char *p = strstr(str1, str2);
    strncpy(p, str3, i);
    That is, you should check the value of p before proceeding with strncpy.

    Quote Originally Posted by Vsky
    I want 2nd and 3rd string to have different number of characters.
    (...)
    I cannot think a solution for this since it will change other characters' index as well as addresses.
    You could start with a basic solution of shifting the remaining portion of the source string each time you do a replacement.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    Apr 2015
    Posts
    42
    @laserlight

    This is wrong because fgets will not store the newline character if it was not read:
    Code:
    *(strchr(str1, '\n')) = '\0';
    This code works perfectly fine with me I don't know what looks wrong to you. fgets always stores the newline as far as I see. I think the reason it stores the newline character is that we are pressing enter after typing. Since there is no other way to enter a string there and go to next line in the code without pressing (as far as I know) it should always store the newline. So basicly I can find its address in the given array and change the character that address is pointing with that code.

    About strlen yes I can use it.

    About strstr returning a null pointer I forgot to add an if statement there. As you can see I used it in the while loop but forgot to add there :P

    You could start with a basic solution of shifting the remaining portion of the source string each time you do a replacement.


    Could you be more specific

    Thanks for the answers

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,271
    Quote Originally Posted by Vsky
    This code works perfectly fine with me I don't know what looks wrong to you. fgets always stores the newline as far as I see.
    Compile and run this program twice:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char line[7];
        if (fgets(line, sizeof(line), stdin))
        {
            char *p = strchr(line, '\n');
            if (p)
            {
                printf("Newline found\n");
            }
            else
            {
                printf("Newline not found\n");
            }
        }
        return 0;
    }
    On the first run of the program, enter "hello" as input. On the second run of the program, enter "hello!" as input. Observe the differing output.

    Quote Originally Posted by Vsky
    Could you be more specific
    Imagine you want to replace "aaa" with "bb" in "aaa ccc aaa ddd". You would start with:
    aaa ccc aaa ddd
    replace the first "aaa" with "bb":
    bba ccc aaa ddd
    Shift left by 1 to overwrite the "a" that was not replaced:
    bb ccc aaa ddd
    Then replace the next "aaa" with "bb":
    bb ccc bba ddd
    Shift left by 1 to overwrite the "a" that was not replaced:
    bb ccc bb ddd
    and you're done.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #15
    Registered User
    Join Date
    Apr 2015
    Posts
    42
    @laserlight

    Now I see what did you mean and I can understand that code is not proper in every condition but I made the array size 100 and I don't enter anything bigger than 100. Will use your code at my next projects.

    Code:
    str1[strcspn(str1, "\n")] = '\0';
    Also thanks for advice about 2nd part. I'll try to make it and turn back to you.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 06-19-2010, 07:42 AM
  2. strcpy
    By bobbelPoP in forum C++ Programming
    Replies: 4
    Last Post: 07-28-2008, 08:44 PM
  3. strcpy without new
    By sawer in forum C++ Programming
    Replies: 3
    Last Post: 05-05-2007, 04:34 AM
  4. strcpy
    By Unregistered in forum C++ Programming
    Replies: 6
    Last Post: 08-01-2002, 01:39 PM
  5. HELP!! strcpy
    By abbynormal87 in forum C++ Programming
    Replies: 3
    Last Post: 05-02-2002, 07:34 AM