Search code examples
carrayspointersc-stringspalindrome

Can C presume which array I want to store my characters?


I'm writing code which checks if an array is palindrome or not:

Write a program that reads a message, then checks whether it's a palindrome
(the letters in the message are the same from left to right as from right to left):

Enter a message: He lived as a devil, eh?
Palindrome

Enter a message: Madam, I am Adam.
Not a palindrome

When I have entered He lived as a devil, eh?,
it gives me the output Not a palindrome,
but the real output should be palindrome.

Below code is what I have tried so far.

#include <stdio.h>
#include <ctype.h> 

#define MAX_LEN 100

int main(void) {

    char message[MAX_LEN];
    char c, *p = message, *q;

    printf("Enter a message: ");

    while ((c = toupper(getchar())) != '\n' & p < message + MAX_LEN) {
        if (isalpha(c))
            *p++ = c;
    }
    p--;

    for (q = message; q < p; q++, p--) {
        if (*p != *q) {
            printf("Not a palindrome\n");
            return 0;
        }
    }
    printf("Palindrome\n");
    return 0;
}

Solution

  • For starters you should declare the variable c as having the type int. The user can interrupt the input process in which case the function getchar returns integer value EOF and you should check whether this occurred.

    char *p = message, *q;
    int c;
    

    There is a bug in the condition of the while statement

    while ((c = toupper(getchar())) != '\n' & p < message + MAX_LEN) {
    

    Instead of the bitwise operator & you have to use the logical AND operator &&.

    As I already have said you should check in the condition of the while statement whether the user interrupted the input. For example

    while (  p < message + MAX_LEN && ( c = toupper(getchar())) != EOF && c != '\n') {
        if (isalpha(c))
            *p++ = c;
    }
    

    The argument of a call of toupper or isalpha should be converted to the type unsigned char. Otherwise in general without the casting such a call can invoke undefined behavior.

    It is desirable not to exclude from an entered string numbers. SO it is better at least to call the function isalnum instead of the function isalpha.

    The user can enter an empty string in this case this decrement of the pointer

    p--;
    

    also can invoke undefined behavior.

    And it is better when a program has one point to exit.

    The program can look the following way

    #include <stdio.h>
    #include <ctype.h> 
    
    #define MAX_LEN 100
    
    int main(void) 
    {
        char message[MAX_LEN];
    
        printf( "Enter a message: " );
    
        char *p = message;
    
        for ( int c; p < message + MAX_LEN &&  ( c = getchar() ) != EOF && c != '\n';   )
        {
            if( isalnum( ( unsigned char )c ) )
            {
                *p++ = toupper( ( unsigned char )c );
            }           
        }
    
        int palindrome = 1;
    
        if ( p != message )
        {
            for ( char *q = message; palindrome && q < --p; ++q )
            {
                palindrome = *q == *p;
            }           
        }
    
        printf( "The entered message is %spalindrome\n", 
                palindrome ? "" : "not " );
    
        return 0;
    }
    

    Its output might look for example like

    Enter a message: He lived as a devil, eh?
    The entered message is palindrome
    

    or like

    Enter a message: Madam, I am Adam
    The entered message is not palindrome
    

    Pay attention to that instead of using a loop with numerous calls of the function getchar you could use only one call of the function fgets

    fgets( message, sizeof( message ), stdin );
    

    or

    if ( fgets( message, sizeof( message ), stdin ) != NULL )
    {
        // check whether the entered string is a palindrome
    }