-3

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;
}
Vlad from Moscow
  • 224,104
  • 15
  • 141
  • 268
  • 2
    You’re writing to `message` through `p`. Writing to `*p` is equivalent to writing to `message[i]`, where `i` is between 0 and `MAX_LEN - 1`. – John Bode Jan 25 '20 at 14:05
  • OK but i don't mention p++ in while loop. I only mentioned p++ in "if(isalpha(c))". Can you eleborate it answering the question, please? –  Jan 25 '20 at 14:23
  • 1
    You might want to consider asking whoever presumably wrote this code to explain it to you. `p` IS in fact incremented in the while loop. – Mark Benningfield Jan 25 '20 at 14:31
  • 2
    Before check the palindrome you have to remove white spaces and punctuation marks. For an example if you use `civic?`, it is not palindrome because of `?`. In the other hand if you use `civ ic`, it is not palindrome because of white space. **1.** Convert all letters to **uppercase or lowercase**. **2.** Remove white spaces. **3.** remove punctuation marks. **4.** Check palindrome or not. – Kalana Jan 25 '20 at 18:49
  • 1
    Regex is a great way to perform the tasks Kalana mentioned above. Regex is worth learning even if you don't choose to use it for this example. It will quickly solve a surprisingly number of programming issues, and is fairly consistent across languages. Whenever using regex, I recommend testing your expression on an online regex editor, before writing the necessary code your program needs, as it's easy to introduce a slight syntax error. It will save tremendous time. Regex is easy to learn, even if the syntax looks foreign. I often use [Regex101](https://regex101.com) - even has code generator. – SherylHohman Jan 26 '20 at 00:18
  • 1
    Some resources for learning regex, and how to use regex in C. [rexegg.com - regex dedicated site with tutorials](https://www.rexegg.com/regex-uses.html), [geeksforgeeks tut,orial](https://www.geeksforgeeks.org/write-regular-expressions/), [regex specific to C](https://www.educative.io/edpresso/how-to-write-regular-expressions-in-c), [SO regix in C examples](https://stackoverflow.com/questions/1085083/regular-expressions-in-c-examples), [SO regcomp - regex in C function](https://stackoverflow.com/questions/29182038/c-regular-expressions-regcomp), – SherylHohman Jan 26 '20 at 00:39
  • 1
    Here is a SO post on how to test for a Palindrome using regex: https://stackoverflow.com/questions/233243/how-to-check-that-a-string-is-a-palindrome-using-regular-expressions. Here is a post on how to solve the palindrome problem ***without*** using regex: https://stackoverflow.com/questions/52002/how-to-check-if-the-given-string-is-palindrome – SherylHohman Jan 26 '20 at 00:45
  • 1
    Here is an online regular expression checker specifically for C: https://www.regextester.com/96669. – SherylHohman Jan 26 '20 at 00:55
  • 1
    But really, you can easily solve this even without regular expressions, using a looping construct 0) create a new empty string or array 1) loop through the given string to examine each character, 2a) if the character is a letter, convert it to lower case and add it to to the new string/array 2b) if not, ignore the character 3) after the loop, reverse the new array/string 4) compare it to the original string: if it matches it's a palindrome, if not, it is not. The only trick here is that you need to compare the characters with letters of the alphabet to determine if it's relevant or not. – SherylHohman Jan 26 '20 at 00:56

2 Answers2

2

Before check the palindrome you have to remove white spaces and punctuation marks. For an example if you use civic?, it is not palindrome because of ?. In the other hand if you use civ ic, it is not palindrome because of white space. There for

  1. Convert all letters to uppercase or lowercase.
  2. Remove white spaces.
  3. remove punctuation marks.
  4. Check palindrome or not.

You can do it by using # include <string.h>

  1. First thing is you have to use scanf() which accept string with white space.
printf("Enter a string = ");
scanf("%[^\n]%*c", word);
  1. Then you have to convert that string to Uppercase or Lowercase because a != A. We know civic is a palindrome but Civic is not a palindrome('Civic != civiC) because Uppercase letters have different ASCII values and Lowercase letters have different ASCII values.

    • (a - z) -: 97 - 122
    • (A - Z) -: 65 - 90

In my case I have converted lowercase to uppercase.

while(strlen(word) >= i)
    {
        if(word[i] >= 97 && word[i] <= 122) 
        {
            word[i] = word[i] - 32; 
        }

        i++;
    }
  1. Another case is your if you enter civ ic with white space, it's palindrome word is ci vic. You can see civ ic != ci vic. There for you have to remove white spaces in your program. And also you have to remove punctuation marks because if you use civic, it's reversed word is ,civic'. You can seecivic, != ,civic`.
int len = strlen(word);

    while(a < len)
    {
        for(i = 0; i < len; i++)
        {
            if(word[i] == ' ' || !(word[i] >= 'A' && word[i] <= 'Z'))
            {
                for(j = i; j < len; j++)
                {
                    word[j] = word[j+1];
                }
                len--;
            }
        }
        a++;
    }
  1. Final thing is we have to revers our string and need to check if our reversed string is equal to our original string. If it is true our String is palindrome. If it is false our String is not a palindrome.
for(i = 0; i < len; i++)
    {
        if(word[i] == word[len - 1])
        {
            len--;
        }
        else
        {
            printf("%s is not a palindrome\n", word);
            return 0;
        }
    }

    printf("%s is a palindroeme\n", word);

This the full code after you merging above parts

# include <stdio.h>
# include <string.h>

int main (void)
{
    char word[100];
    int i = 0;
    int j, x = 0;
    int a = 0;

    printf("Enter a string = ");
    scanf("%[^\n]%*c", word);

    while(strlen(word) >= i)
    {
        if(word[i] >= 97 && word[i] <= 122) 
        {
            word[i] = word[i] - 32; 
        }

        i++;
    }

    printf("After converting it to uppercase = %s\n", word);

    int len = strlen(word);

    while(a < len)
    {
        for(i = 0; i < len; i++)
        {
            if(word[i] == ' ' || !(word[i] >= 'A' && word[i] <= 'Z'))
            {
                for(j = i; j < len; j++)
                {
                    word[j] = word[j+1];
                }
                len--;
            }
        }
        a++;
    }

    printf("After removing spaces = %s\n", word);

    for(i = 0; i < len; i++)
    {
        if(word[i] == word[len - 1])
        {
            len--;
        }
        else
        {
            printf("%s is not a palindrome\n", word);
            return 0;
        }
    }

    printf("%s is a palindroeme\n", word);

    return 0;

}

First test Output -:

Enter a string = He lived as a devil, eh?
After converting it to uppercase = HE LIVED AS A DEVIL, EH?
After removing spaces = HELIVEDASADEVILEH
HELIVEDASADEVILEH is a palindroeme

Second test Output -:

Enter a string = Madam I am Adam.
After converting it to uppercase = MADAM I AM ADAM.
After removing spaces = MADAMIAMADAM
MADAMIAMADAM is not a palindrome
Kalana
  • 4,683
  • 6
  • 22
  • 46
  • 1
    I think you don't deserve this kind of down votes. Some users down voted your question because you didn't mention your problem clearly. I have understand your question and edited it to get clear for everyone. – Kalana Jan 26 '20 at 14:02
2

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
}
Vlad from Moscow
  • 224,104
  • 15
  • 141
  • 268
  • Wow, someone who really wants to help instead of downvoting to oblivion for being a beginner or saying"do this instead" at last. Thank you very much. I definetly will search it up the "unsigned char casting" thing. –  Jan 26 '20 at 11:35
  • 1
    @whysoserious I upvoted your question.:) But I can do this only once.:) – Vlad from Moscow Jan 26 '20 at 11:36