Operation Logica in C

Asked

Viewed 109 times

2

I’m trying to make a program to check if a certain word is a palindrome. I’m having trouble with a logical operation that isn’t returning what I expected.

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


#define bool    short
#define true    1
#define false   0
#define equals(a, b) (((strcmp(a, b) == 0 ) ? true : false))
#define NUMENTRADA 1000
#define TAMLINHA   1000


bool isFim (char* s){

    return (strlen(s) >= 3 && s[0] == 'F' && s[1] == 'I' && s[2] == 'M');

}


bool isPalindromo(char* s){

    int meio = strlen(s)/2;
    int indc = strlen(s) - 1;

    bool resp = true;    

//    printf("\nresp ==>> %d \n", resp);

    for (int i = 0 ; i < meio ; i++){

//        printf("\nresp2 ==>> %d \n", resp);       
//        printf("BOOL2  ======= >> %d \n", (resp && (s[i] == s[indc])));

        resp = resp && (s[i] == s[indc]);        
        indc--;

//        printf("VALOR  ======= >> %c \n", s[i]);
//        printf("VALOR 2  ======= >> %c \n", s[indc]);

//        printf("\nRESP  ======= >> %d \n", resp);
//        printf("BOOL  ======= >> %d \n", (resp && (s[i] == s[indc])));

    }

//        printf("\n---------------------------\n");
//        printf("BOOL  ======= >> %d \n", (s[i] == s[indc]));
//        printf("\n---------------------------\n");

    return resp;

}


int main (int argc, char** argv){

    char entrada [NUMENTRADA][TAMLINHA];
    int numEntrada = 0;

    do{

        fgets(entrada[numEntrada], TAMLINHA, stdin);

    } while (isFim(entrada[numEntrada++]) == false);

    numEntrada--;

    for (int i = 0; i < numEntrada ; i++){

        if(isPalindromo(entrada[i]) == true){

            printf("SIM\n");

        } else {

            printf("NAO\n");

        }

    }

}

Good operation:

resp = resp && (s[i] == s[indc]);

is always returning me false (0) and did not understand why.

The words are being entered into the program by incoming redirect. Here is a part of the.in input file:

aça
acaçá
Ada
afã
aia
ala
ama
Ana
anilina
ara
arara
asa
ata
aviva
ele
esse
mamam
mamam
matam
metem
oco
omissíssimo
Omo
osso
Oto
Otto
ovo
racificar

I made a similar code in Java and managed, but I’m not able to understand why the comparison is not working.

  • 2

    One thing I noticed in your entries is that you have uppercase/lowercase words and in this case the comparison will be different, which I do not know if it is something purposeful or not. Ex.: Omo. Idem for accented letters. The problem with your program is that the fgets function incorporates the final input ' n' to your string, so your ara input will have length 4 and will be: s[0]='a', s[1]='r', s[2]='a' and s[3]=' n'.

1 answer

2


Turns out when you do a reading with fgets for stdin, the enter you press is also stored as a \n inside the string.

See how it appears running in debug and inserting the word aça:

inserir a descrição da imagem aqui

That is, in the first comparison that exists in the for made with:

resp = resp && (s[i] == s[indc]);  

Go compare the lyrics a with the \n and will fail immediately.

To correct just delete the \n after reading with fgets. There are many ways to do this, but by doing as direct as possible you can use the function strcspn looking for a character in the string, in case the \n:

do{
    fgets(entrada[numEntrada], TAMLINHA, stdin);
    entrada[numEntrada][strcspn(entrada[numEntrada], "\n")] = '\0'; //eliminar \n
} while (isFim(entrada[numEntrada++]) == false);

With this already works, as you can see on Ideone. Note however that in words that have accentuated characters the check has become incorrect indicating that they are not palindromes. This has to do with the fact that these letters are stored in UTF-8 and therefore yours ç for example, it actually corresponds to 2 bytes and not 1:

inserir a descrição da imagem aqui

This situation is already more complicated to fix and I will not do it in this answer, but one solution is to choose to save the string as an array of wchar_t, which corresponds to a wide char and usually allows you to store characters with more than one byte in each position. In this scenario it is important to ensure that you have the locale correct, applied through the function setlocale defined in locale.h

I’d still like to make a few more comments about your code:

  • Utilise strlen twice in a row:

    int meio = strlen(s)/2;
    int indc = strlen(s) - 1;
    

    It is not ideal because it ends up doing repeated processing without any advantage. It would be better to save the size in a variable and use it twice.

  • You can include both variables i and indc in the same for, defining multiple starts and multiple increments, which give you a more compact syntax:

    for (int i = 0, indc = strlen(s) - 1; i < meio && resp ; i++, indc--){
        resp = resp && (s[i] == s[indc]);
    }
    

    I took advantage and includes the && resp in the condition that causes the for stop as soon as a letter is different, avoiding going through the rest of the string when you already know that it is not palindromo.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.