Thread: Can not copy a string from index to index?

  1. #1
    Registered User
    Join Date
    Sep 2014
    Posts
    121

    Can not copy a string from index to index?

    Hello, I have this piece of code, which does not actually work, it does not copy the desired symbols to the needed destination:
    Code:
    static char* aux_cutStringFromTo(const char* src, int from, int to)
    {
        if ( from > to ) return 0;
        if ( aux_strlen(src) < 0) return 0;
        int chars = to - from;
        printf("SIZE IS: [%d] \n", chars);
        char* str = (char*) malloc( sizeof(char)* chars+1);
        if ( !str ) return 0;
        char* begin = &src[from];
        while ( from++ < to )
        {
            printf("[%c] >> [%c] \n", *begin, *str);
            *str++ = *begin++;
        }
        *str++ = 0 ;
        puts("\n\n");
        return str;
    }
    Assuming that while [from] is less than [to] a simple strcpy is performed with no 0 check.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    How does it not work? For example, show the test input, expected output and actual output.
    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
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    The print message shows that str is empty, no chars are assigned to it.
    Code:
    [1] >> [] 
    [2] >> [] 
    [3] >> [] 
    [4] >> [] 
    [5] >> [] 
    [6] >> [] 
    [7] >> [] 
    [8] >> [] 
    [9] >> [] 
    [1] >> [] 
    [0] >> []

  4. #4
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    Even if the print is below the assignment, it`s the same. And the returned [str] is empty.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Ah. Let's look closely at what the function does:
    Code:
    char* str = (char*) malloc( sizeof(char)* chars+1);
    if ( !str ) return 0;
    So, memory was (hopefully) allocated, and str points to the first character of that block of memory. Well and good. Later, we see:
    Code:
    while ( from++ < to )
    {
        printf("[%c] >> [%c] \n", *begin, *str);
        *str++ = *begin++;
    }
    *str++ = 0 ;
    Okay, the values were assigned in a loop, then you took care to null terminate the string. Great!

    Unfortunately, at this point str points one past the null character. But it really should point to the start of the copied string!

    There are two ways to fix this:
    • Create another pointer that is a copy of str before the loop, then return this second pointer.
    • Subtract the copied string length (including the null character) from str, thereby getting a pointer to the start of the copied string that is then returned.

    Personally I think the first way is less error-prone.

    By the way, since src is a const char*, this:
    Code:
    char* begin = &src[from];
    should be:
    Code:
    const char* begin = &src[from];
    EDIT:
    Incidentally, you have a problem with one of your debugging outputs:
    Code:
    printf("[%c] >> [%c] \n", *begin, *str);
    *str++ = *begin++;
    You print *begin, and begin does indeed point to where you want to copy. However, until the next statement, *str does not yet contain the value that is to be copied, so printing it is wrong.
    Last edited by laserlight; 01-06-2016 at 03:01 AM.
    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

  6. #6
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    The function could be written without any assistance from other functions, while allowing for really long strings:
    Code:
    #include <stdlib.h>
    #include <errno.h>
    
    /* Return a dynamically allocated duplicate of src[first .. limit-1],
     * or NULL if nothing to copy (never returns an empty string).
    */
    char *dup_substr(const char *const src,
                     const size_t first, const size_t limit)
    {
        if (src != NULL && limit > first) {
            const char *const s0 = src + first;
            const char *const s1 = src + limit;
            const char *s = src;
            char *dst, *d;
    
            /* Verify src is at least first characters long. */
            while (s < s0 && *s != '\0')
                s++;
    
            /* Premature end of string? */
            if (s < s0 || *s == '\0') {
                errno = 0;
                return NULL;
            }
    
            /* Allocate a dynamic string large enough
             * to hold (limit - first) characters, plus a '\0'. */
            dst = malloc(limit - first + 1);
            if (dst == NULL) {
                errno = ENOMEM;
                return NULL;
            }
            d = dst;
    
            /* Copy s to d, until s reaches end of string or
             * limit, whichever occurs first. */
            while (s < s1 && *s != '\0')
                *(d++) = *(s++);
    
    #ifdef WISH_TO_BE_CAREFUL
            /* Clear the rest of the allocated buffer,
             * also adding the end-of-string '\0'. */
            {
                char *const dend = dst + limit - first;
                while (d <= dend)
                    *(d++) = '\0';
            }
    #else
            /* Add the end-of-string mark. */
            *d = '\0';
    #endif        
    
            errno = 0;
            return dst;
    
        } else {
            errno = EINVAL;
            return NULL;
        }
    }
    The above always sets errno: To zero if success, to an error code otherwise. It never returns an empty string; in that case, it returns NULL with errno==0.

  7. #7
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    Oh, I`ve completely forgot the begin ptr. My mistake . . . Thanks for hinging.

  8. #8
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Quote Originally Posted by heatblazer View Post
    Thanks for hinging.
    I definitely did not!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 04-04-2012, 09:03 PM
  2. Replies: 1
    Last Post: 08-12-2011, 03:07 AM
  3. short index vs. int index
    By ardavirus in forum C Programming
    Replies: 3
    Last Post: 06-13-2011, 05:09 AM
  4. Insert into string at specified index?
    By RedZone in forum C Programming
    Replies: 2
    Last Post: 07-24-2006, 07:01 PM
  5. ? about this> index::index () : type_intex()
    By bobk544 in forum C++ Programming
    Replies: 5
    Last Post: 09-30-2005, 02:59 PM

Tags for this Thread