Search code examples
csubstringdynamic-memory-allocationc-stringsfunction-definition

when printing a char* in C only the first character is being printed


I'm trying to write a function that will print out a substring of string however when printing it, only the first character in the array is printed.

As you can see in the code I've put a printf statement in the function after the substring is created and it displays properly. However when the function is passed into a printf function in the main function it only prints the first character.

Thanks for any help people are able to provide.

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

char *ft_substr (const char *s, unsigned int start, size_t len)
{
    char        *str;
    unsigned int    i;
    unsigned int    j;

    str = malloc(len * sizeof(char) + 1);
    i = start;
    j = 0;
    while (i < len + start)
    {
        str[j] = s[i];
        j++;
        i++;
    }
    str[j + 1] = '\0';
    printf("%s\n", str);
    free(str);
    return (str);
}

int main (void)
{
    char hello[] = "Hello World";
    char sub = *ft_substr(hello, 1, 4);

    printf("%s\n", &sub);
    return (0);

}

Solution

  • Before returning the pointer str from the function you freed all the allocated memory

    free(str);
    return (str);
    

    So the returned pointer is invalid.

    Remove the statement

    free(str);
    

    Another problem in the function is using an incorrect index in this statement

    str[j + 1] = '\0';
    

    Just write

    str[j] = '\0';
    

    Also this declaration is incorrect

    char sub = *ft_substr(hello, 1, 4);
    

    It declares a single character while you need to declare a pointer that will point to the dynamically allocated string in the function. So write

    char *sub = ft_substr(hello, 1, 4);
    

    and then write

    printf("%s\n", sub);
    
    free( sub );
    

    And if you are using the type size_t for the length of a string then use indices also of the type size_t.

    Here is a demonstrative program.

    #include <stdio.h>
    #include <stdlib.h>
    
    char * ft_substr( const char *s, size_t start, size_t len )
    {
        char *str = malloc( len + 1 );
        
        if ( str != NULL )
        {
            size_t i = 0;
            for ( ; i < len; i++ )
            {
                str[i] = s[start + i];
            }
            
            str[i] = '\0';
        }
        
        return str;
    }
    
    int main(void) 
    {
        const char *hello= "Hello World";
        
        char *sub = ft_substr( hello, 1, 4 );
    
        if ( sub != NULL ) puts( sub );
        
        free( sub );
        
        return 0;
    }
    

    Its output is

    ello
    

    The function will be more safer if it will check whether the starting index and the length are specified correctly. For example

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char * ft_substr( const char *s, size_t start, size_t len )
    {
        char *str = NULL;
        
        size_t n = strlen( s );
        
        if ( start < n )
        {
            if ( n - start < len ) len = n - start;
        
            str = malloc( len + 1 );
        
            if ( str )
            {
                memcpy( str, s + start, len );
                str[len] = '\0';
            }
        }
        
        return str;
    }
    
    int main(void) 
    {
        const char *hello= "Hello World";
        
        char *sub = ft_substr( hello, 1, 4 );
    
        if ( sub != NULL ) puts( sub );
        
        free( sub );
        
        return 0;
    }