-2

My code is to check if a given word is a palindrome or not. But when I run it, I am not getting correct results. Please help me find my mistakes as I am still in the process of learning C.

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



int main ()
{
    
    char a[40];
    
    printf("Enter the word - ") ; 
    scanf("%s" , &a);
    printf("Reversed  - %s \n " , strrev(a)) ; 

    if(a == strrev(a)){
        
        printf("Yes");   
        
    }

    else{
        printf("No");
    }
    
    return 0;
    
}
    

The outputs are always random. Even it happened when I tried to do another project. Then I had to simply copy paste the code and it worked.

Anticipating favourable response.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Sahal
  • 17
  • 1
  • 2
    `a == strrev(a)` will compare two *pointers*, and those pointers will never be equal. If you want to compare strings use `strcmp` (as your learning material should have told you). – Some programmer dude Jun 28 '23 at 10:24
  • 2
    Also note that `scanf("%s" , &a)` is wrong. It should be either `scanf("%s" , &a[0])` or `scanf("%s" , a)`. As your learning material, the `%s` format expects a pointer to the first character of the array, with the type `char *`. Plain `a` will *decay* to `&a[0]` which is a pointer to the first character in the array, of type `char *`. With `&a` you get a pointer to the array, with the type `char (*)[40]`. Mismatching format specifier and argument type leads to *undefined behavior*. – Some programmer dude Jun 28 '23 at 10:26
  • 2
    @Someprogrammerdude Perhaps it's also worth to mention that `scanf(%s ....` is an absolute no-go – Support Ukraine Jun 28 '23 at 10:43
  • Does this answer your question? [How do I properly compare strings in C?](https://stackoverflow.com/questions/8004237/how-do-i-properly-compare-strings-in-c) – phuclv Jun 28 '23 at 11:51

4 Answers4

3

strrev() is a non-standard C library function. If implemented, it usually returns its argument, so a == strrev(a) will always be true. It compares two pointers to the same buffer.

Regardless, this doesn’t do what you want. As pointed out, you want to compare the original string and the reversed string, using strcmp() or similar. But strrev() reverses a string in place, so you have to keep a copy of the original input buffer for comparison to the reversed string.

Paul Lynch
  • 241
  • 1
  • 5
1
  • strrev is a non-standard C function that only exists in some C libraries as an extension. It may be implemented like this:
    char *strrev(char *str) {
        size_t len = strlen(str);
        // create a pointer to the first character and a pointer to the last
        // (since the last is `\0` we'll decrease that pointer by one before use)
    
        // loop until the two pointers meet:
        for(char *f = str, *l = str + len; f < l--; ++f) {
            // swap characters
            char tmp = *f;
            *f = *l;
            *l = tmp;
        }
        return str; // returns the same pointer you sent in
    }
    
  • Regarding a == strrev(a): You can't compare strings by comparing their pointers - and since strrev returns a pointer with the same value as you sent in, the comparison will always be true. You need strcmp for comparing strings so you'd need to copy the original string and use strcmp(a, reversed_copy);
  • Instead of copying the sting, using strrev and then strcmp (which compares the whole string), you could just do what strrev does internally - but instead of swapping characters, you compare them. If *f != *l you return false. If the whole loop finishes without returning, you've got a palindrome and return true. This is a lot quicker since it doesn't require copying the string, reversing it and then comparing it with the original.

Also, pay attention to types: scanf("%s" , &a); gives scanf a char(*)[40] instead of the expected char*. Also, if a user enters more than 39 characters, scanf will write out of bounds and the program may crash or behave in any way it want. If(!) you use scanf for reading strings (instead of the recommended fgets), always supply the maximum number of characters that your array can hold - 1. The - 1 part is to leave room for the null terminator, \0. You should also check that scanf successfully extracted what you expected. It returns the number of successful extractions. It'll be 1 for each conversion specifier if successful. Since you only want to extract one word, it should return 1. Corrected:

if (scanf("%39s" , a) != 1) /* there was error */
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
0

First, you should know that whenever you call strrev(a), the variable a is modified to be the reversal. So when you compare that with a like you coded it it always displays "Yes" because it is effectively a==a.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ()
{   
    char a[40];   
    printf("Enter the word - ") ; 
    scanf("%s" , &a);
    printf("String  - %s \n " , a) ; 
    printf("Reversed  - %s \n " , strrev(a)) ; 
    printf("String  - %s \n " , a) ; 
}
//The result
Enter the word - hoangtran
String  - hoangtran 
Reversed  - nartgnaoh
String  - nartgnaoh

So you should consider your logic. Next, whenever you want to compare two strings, you have to consider using functions, because the "==" operator is usually used to compare numbers or in some languages like C, this will compare two locations in memory (pointers), hence in this example we will use the strcmp() built-in method. This will return 0 if 2 strings are equal. (You can find it in details on the internet). Below is the source code you can reference:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ()
{   
    char a[40];
    
    printf("Enter the word - "); 
    scanf("%s" , &a);
    char b[40];
    strcpy(b, a); // Copy content of a to b. 
    strrev(b); // This make b = reverse(a).
    printf("String  - %s \n " ,a) ; 
    printf("Reversed  - %s \n ",b ) ;

    int compare = strcmp(a, b);
    if(compare==0){
        printf("Yes");   
    }
    else{
        printf("No");
    }
    return 0;   
}

Good Luck!

UpAndAdam
  • 4,515
  • 3
  • 28
  • 46
  • 2
    The `scanf` call is incorrect. The `%s` format expects a `char *`, not a `char (*)[40]` as you're passing. It will probably "work" in most implementations, since the pointers refer to the same address, but it's a pointer type mismatch error which your compiler should have warned about. Hint: The correct second argument is `a`, not `&a`. OP's original code had this same bug. – Tom Karzes Jun 28 '23 at 11:38
  • I had been learnt this languages a long time ago and move to code in node so sometimes, I forgot some important syntaxes. Thank you so much about this – Irene Pain Jun 28 '23 at 18:57
  • @IrenePain Thanks a lot, I understood the reason too. – Sahal Jun 29 '23 at 06:06
0

For starters the second argument expression of this call of scanf

scanf("%s" , &a);

has an incorrect type relative to the converdsion specifier s. The expression &a has the type char ( * )[40] due to declaration of the character array a

char a[40];

while the conversion specifier s expects an argument of the type char *.

Also such a call is unsafe.

Instead you need to write

scanf("%39s" , a);

The function strrev is not a standard C function. It can be supported by C compilers conditionally.

In this if statement

if(a == strrev(a)){

there are compared the same addresses of the first character of the string stored in the array a. So this if statement always evaluates to logical true.

If you want to compare a source string and its reversed string you need to declare one more character array where the reversed string will be stored. And to compare the strings you need to use another standard C string function strcmp.

Also you call the function strrev twice in the program.

For example you could write

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

int main( void )
{
    char a[40];
    char b[40];
    
    printf( "Enter the word - " ); 
    scanf( "%39s" , a);

    strcpy( b, a );

    strrev( b );

    printf( "Reversed  - %s\n " , b ); 

    if ( strcmp( a, b ) == 0 )
    {
        puts( "Yes" );   
    }
    else
    {
        puts( "No" );
    }
    
    return 0;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335