RISOLTO [C] stringa palindrome

Programmazione

demda

Ciao a tutti, sto scrivendo un programma in C che verifica se una stringa è palindroma oppure no.
Sorgente:
C:
#include <stdio.h>
#include<string.h>
#define DIM 256

#define DEBUG

int main (int argc, char *argv[]){
    char str1[ DIM ];
    char str2[ DIM ];
    
    printf("Inserire stringa -> ");
    fgets(str1, DIM, stdin);
    
    for (int i = (strlen(str1) - 2), k = 0; i >= 0; i --, k ++ ){
    
        #ifdef DEBUG
            printf("\ni = %d, k = %d\n",i,k);
        #endif
        
        str2[k] = str1[i];
        
        #ifdef DEBUG
            printf("\nstr2[k]: %c\nstr1[i]: %c\n",str2[k], str1[i]);
        #endif
    }
    
    #ifdef DEBUG
        printf("\nStampo lunghezza str1: %d compreso il carattere terminatore\n",strlen(str1));
    #endif
    
    if (strcmp(str1, str2) == 0){
        printf("La stringa è palindrome\n");
    }else{
        printf("La stringa non è palindrome\n");
    }
    
    return 0;
}

Putroppo quando eseguo, anche se inserisco una stringa palindrome (es: "otto") l'output che ottengo è " La stringa non è palindrome ". Sono certo quasi al 100% che l'errore sia nel for, ma non riesco ad individuarlo.
Spero possiate aiutarmi.
 
#1

rctimelines

Utente Èlite
Scusa, ma è un codice illeggibile. E quel ciclo for, non è che riesci a scriverlo in maniera un po' più ortodossa?? Secondo me dovresti lasciar stare il codice e concentrarti sulla struttura dell'algoritmo: poi il codice viene da solo.

Come intendi effettuare la verifica che la stringa sia palindroma?!?

Inviato dal mio Nexus 6P utilizzando Tapatalk
 
Mi Piace: Moffetta88
#2

DispatchCode

Staff Forum
Utente Èlite
Esiste un modo più semplice per questo tipo di verifica: prova a pensarci, se hai una stringa (rappresentata da un array, in C), come puoi verificare che il primo carattere sia uguale all'ultimo, il secondo sia uguale al penultimo etc etc?
Sarebbe sufficiente utilizzare due variabili per contare: con una parti dall'inizio, con l'altra dalla fine. Se gli indici sono uguali, allora sei giunto a metà stringa, e di conseguenza questa sarà palindroma (eg. cicli sino a che i due indici sono diversi).

Comunque verifica le stringhe prima del confronto... la seconda stringa non è proprio quella che ti aspetti (guardala tramite debugger prima del confronto).
 
#3

demda

rctimelines ha detto:
Scusa, ma è un codice illeggibile. E quel ciclo for, non è che riesci a scriverlo in maniera un po' più ortodossa?? Secondo me dovresti lasciar stare il codice e concentrarti sulla struttura dell'algoritmo: poi il codice viene da solo.

Come intendi effettuare la verifica che la stringa sia palindroma?!?

Inviato dal mio Nexus 6P utilizzando Tapatalk
1) leggo la stringa inserita dall' utente

2) con il ciclo for scorro la stringa appena inserita e la copio al "contrario" in un altro vettore di caratteri

3) verifico se entrambe le stringhe sono uguali, se lo sono allora la stringa inserita 3 palindroma

Inviato da Mi A2 Lite tramite App ufficiale di Tom\'s Hardware Italia Forum
 
#4

demda

DispatchCode ha detto:
Esiste un modo più semplice per questo tipo di verifica: prova a pensarci, se hai una stringa (rappresentata da un array, in C), come puoi verificare che il primo carattere sia uguale all'ultimo, il secondo sia uguale al penultimo etc etc?
Sarebbe sufficiente utilizzare due variabili per contare: con una parti dall'inizio, con l'altra dalla fine. Se gli indici sono uguali, allora sei giunto a metà stringa, e di conseguenza questa sarà palindroma (eg. cicli sino a che i due indici sono diversi).

Comunque verifica le stringhe prima del confronto... la seconda stringa non è proprio quella che ti aspetti (guardala tramite debugger prima del confronto).
Sul fatto che ci siano metodi migliori non ci piove. Il mio scopo è realizzare questo programma con questo metodo, poiché è l'unico con cui ancora non ho provato.

Comunque seguirò il tuo consiglio, ti aggiorno.

Inviato da Mi A2 Lite tramite App ufficiale di Tom\'s Hardware Italia Forum
 
#5

Andretti60

Utente Èlite
L'algoritmo e' giusto, almeno l'idea. Di fatto copi la stringa in modo sbagliato. Perche' parti da strlen(str1)-2 ?
Stampa le due stringhe prima di fare il confronto e dovresti renderti conto dell'errore.
 
Mi Piace: Moffetta88
#6

rctimelines

Utente Èlite
Infatti: str2, non solo sarà sempre diversa da str1, ma anche di due caratteri più corta!

Poi, per chiarezza metterei il contatore k fuori dal ciclo for.
Perché stampi la lunghezza solo della prima stringa inserita? Se avessi stampato anche quella della stringa ricostruita avresti rilevato già l'errore. In ogni caso, come detto sopra, avresti potuto visualizzare le due stringhe per vedere perchéi non ottieni mai il risultato corretto.


Inviato dal mio Nexus 6P utilizzando Tapatalk
 
Ultima modifica:
Mi Piace: Moffetta88
#7

demda

Andretti60 ha detto:
L'algoritmo e' giusto, almeno l'idea. Di fatto copi la stringa in modo sbagliato. Perche' parti da strlen(str1)-2 ?
Stampa le due stringhe prima di fare il confronto e dovresti renderti conto dell'errore.
Il codice funziona ! ma solo se leggo l'input della stringa con la scanf() , la fgets() mi da problemi. Infatti: la funzione strlen() dovrebbe ritornare la lunghezza della stringa (quindi escluso il carattere di terminazione).
Ma non funziona !

Se inserisco la stringa "otto" utilizzando la fgets() e stampo la lunghezza della stringa, mi da in output 5 !
Invece se la leggo con la scanf() mi da in output 4 come lunghezza. Quindi il codice che ho scritto funziona se uso la scanf() (è per questo che avevo messo -2 nel for, poiché la lunghezza che la strlen() mi ritornava era errata )

Sai dirmi il perché ? proprio non capisco
Post unito automaticamente:

rctimelines ha detto:
Infatti: str2, non solo sarà sempre diversa da str1, ma anche di due caratteri più corta!

Poi, per chiarezza metterei il contatore k fuori dal ciclo for.
Perché stampi la lunghezza solo della prima stringa inserita? Se avessi stampato anche quella della stringa ricostruita avresti rilevato già l'errore. In ogni caso, come detto sopra, avresti potuto visualizzare le due stringhe per vedere perchéi non ottieni mai il risultato corretto.


Inviato dal mio Nexus 6P utilizzando Tapatalk
Il codice funziona ! ma solo se leggo l'input della stringa con la scanf() , la fgets() mi da problemi. Infatti: la funzione strlen() dovrebbe ritornare la lunghezza della stringa (quindi escluso il carattere di terminazione).
Ma non funziona !

Se inserisco la stringa "otto" utilizzando la fgets() e stampo la lunghezza della stringa, mi da in output 5 !
Invece se la leggo con la scanf() mi da in output 4 come lunghezza. Quindi il codice che ho scritto funziona se uso la scanf() (è per questo che avevo messo -2 nel for, poiché la lunghezza che la strlen() mi ritornava era errata )

Sai dirmi il perché ? proprio non capisco
 
#8

rctimelines

Utente Èlite
Ma stampare le stringhe risultanti ti dà proprio tanto fastidio?!?

E usa scanf().. probabilmente, fget() prende anche il carattere di invio (CR13)

Inviato dal mio Nexus 6P utilizzando Tapatalk
 
#9

demda

rctimelines ha detto:
Ma stampare le stringhe risultanti ti dà proprio tanto fastidio?!?

Inviato dal mio Nexus 6P utilizzando Tapatalk
Le ho stampate, se inserisco in input "otto" in entrambe la stampa mi da: "otto" ma la lunghezza è 5 invece di 4, deduco sia questo il problema, come ho detto anche nella risposta precedente


Quello che non riesco a capire è perché la fgets() fa i dispetti
 
#10

rctimelines

Utente Èlite
Con fgets prende anche il carattere di invio mio finale, che stampando non si vede a video. Scansiona i caratteri e scrivine il codice ASCII..

In ogni caso il codice è sbagliato perché partendo da -2 ricostruisci una stringa inversa che sarà sempre diversa da quella di origine.

E comunque, usare fgets evidentemente è sbagliato perché la stringa inserita non è mai palindromi avendo il carattere finale diverso.
Inviato dal mio Nexus 6P utilizzando Tapatalk
 
Ultima modifica:
Mi Piace: Moffetta88
#11

Andretti60

Utente Èlite
Devi appendere a str2 il carattere terminale (zero)
 
#12

demda

rctimelines ha detto:
Con fgets prende anche il carattere di invio mio finale, che stampando non si vede a video. Scansiona i caratteri e scrivine il codice ASCII..

In ogni caso il codice è sbagliato perché partendo da -2 ricostruisci una stringa inversa che sarà sempre diversa da quella di origine.

E comunque, usare fgets evidentemente è sbagliato perché la stringa inserita non è mai palindromi avendo il carattere finale diverso.
Inviato dal mio Nexus 6P utilizzando Tapatalk
Il primo carattere memorizzato è \n.
Ma non capisco come sia possibile, non dovrebbe al più essere memorizzato alla fine del vettore ?
 
#13

demda

Andretti60 ha detto:
Devi appendere a str2 il carattere terminale (zero)
1) Quindi se copio carattere per carattere, il carattere di fine riga
Codice:
\0
devo aggiungerlo manualmente ?

2) la
Codice:
fgets()
consuma quindi il buffer di memoria, ma non dovrebbe memorizzare il carattere
Codice:
\n
al più alla fine della stringa
Codice:
str1
, non capisco perché lo ritrovo all inizio

Inviato da Mi A2 Lite tramite App ufficiale di Tom\'s Hardware Italia Forum
 
#14

rctimelines

Utente Èlite
demda ha detto:
Il primo carattere memorizzato è \n.
Ma non capisco come sia possibile, non dovrebbe al più essere memorizzato alla fine del vettore ?
Infatti il carattere \n è proprio il carattere di andata a capo (CR = carriage return).. come dicevo sopra, la funzione fgets lo inserisce nella stringa.

Però, scusa, devi imparare (e sforzarti) a studiare le funzioni. Sei un po' troppo improvvisato e non puoi solo chiedere genericamente nel forum.. ti serve un po' di metodo.

Inviato dal mio Nexus 6P utilizzando Tapatalk
 
#15