Search code examples
crecursionc-stringspalindromefunction-definition

C recursive function using pointer arthimatic updates values, but not pointer arthimatic values


I'm writing a C function to check if a string is a palindrome or not. It accepts a pointer to the string, and an int representing the length of the string. My idea is that I will check the chars at the beginning and end of the string, if they are the same, increment the pointer, decrement the length, and keeping checking until they are equal or the length becomes 0 (This may be the incorrect base case).

My concern is that when the function is recalled, the char pointer increments no problem, and I can see it looking at the correct chars. The length int decrements like it is supposed to. However, when I use the statement *(p_string + length - 1) it looks at the same char over and over again despite the pointer p_string and the length int both updating correctly with each call of the function. Even trying *(p_string + length) yields the same issue.

I don't understand why this statement would return the same char over and over again if both length and p_string and being updated correctly.

Code:

int is_palindrome(char* p_string, int length)
{
    //This is a test statement, the "length - 1" everywhere is to avoid looking at the '\0' character
    //during the first call
    printf("%c %c %d %p\n", *(p_string), *(p_string + length - 1), (length - 1), (p_string + length));
    if (length == 0)
    {
        return 1;
    }
    else if (*(p_string) != *(p_string + length - 1))
    {
        return 0;
    }
    else
    {
        return is_palindrome((p_string + 1), (length - 1));
    }

}

int main()
{
    char* p_string = "tacocat";
    printf("\n%d", is_palindrome(p_string, 7));

    return 0;
}

Solution

  • The main problem is that you are using an incorrect expression as the second argument in this call

    return is_palindrome((p_string + 1), (length - 1));
                                         ^^^^^^^^^^^^
    

    you need at least write

    return is_palindrome((p_string + 1), (length - 2));
                                         ^^^^^^^^^^^^
    

    Also instead of this check

    if (length == 0)
    {
        return 1;
    }
    

    you should use the check

    if (length < 2)
    {
        return 1;
    }
    

    The function should be declared the following way

    int is_palindrome( const char *s, size_t n )
    {
        return ( n < 2 ) || ( *s == *( s + n - 1 ) && is_palindrome( s + 1, n - 2 ) );
    } 
    

    Here is a demonstrative program.

    #include <stdio.h>
    #include <string.h>
    
    int is_palindrome( const char *s, size_t n )
    {
        return ( n < 2 ) || ( *s == *( s + n - 1 ) && is_palindrome( s + 1, n - 2 ) );
    } 
    
    int main(void) 
    {
        const char *s = "1";
        
        printf( "\"%s\" is a palindrome: %s\n", 
                s, is_palindrome( s, strlen( s ) ) ? "true" : "false" );
    
        s = "12";
        
        printf( "\"%s\" is a palindrome: %s\n", 
                s, is_palindrome( s, strlen( s ) ) ? "true" : "false" );
                
        s = "121";
        
        printf( "\"%s\" is a palindrome: %s\n", 
                s, is_palindrome( s, strlen( s ) ) ? "true" : "false" );
                
        s = "1221";
        
        printf( "\"%s\" is a palindrome: %s\n", 
                s, is_palindrome( s, strlen( s ) ) ? "true" : "false" );
                
        return 0;
    }
    

    The program output is

    "1" is a palindrome: true
    "12" is a palindrome: false
    "121" is a palindrome: true
    "1221" is a palindrome: true