RISOLTO [C] stringa palindrome

demda

Utente Attivo
351
49
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.
 

rctimelines

Utente Èlite
4,580
1,572
CPU
AMD Ryzen 7 2700X | INTEL i5-6600k | INTEL i5-4460... altri
Dissipatore
wraith MAX | Arctic Freezer 11LP | stock
Scheda Madre
Asrock Fatal1ty 4K | Asus Prime Z270P | Acer Veriton
Hard Disk
Samsung 970evo m.2 | vari | Samsung 860 evo
RAM
16GB G.Skill TridentZ 3000 | 16GB CORSAIR 2133 | 8GB DDR3 1600
Scheda Video
RadeonPro WX3100 4G | KFA2 GTX 970 4G | Quadro k620 2G
Monitor
DELL 2419P 2K + Benq 17" | Acer 24" FHD | Benq 19" FHD
Sistema Operativo
Windows10-pro64/OpenSUSE-QL42.3/Manjaro-17.0.2-KDE
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
Reactions: Moffetta88

DispatchCode

Utente Attivo
636
398
CPU
Intel i7 6700HQ, 2.60Ghz, 4 core 8 threads
Scheda Madre
Asustek
Hard Disk
Hitachi 7200 rpm, 1TB
RAM
16GB DDR4 (2 slot su 4)
Scheda Video
Nvidia Geforce GTX 960M, 4GB
Scheda Audio
Realtek
Internet
30Mbps/3Mbps con Eolo
Sistema Operativo
Windows 10 64bit
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).
 

demda

Utente Attivo
351
49
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
 

demda

Utente Attivo
351
49
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
 

Andretti60

Utente Èlite
3,812
2,565
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
Reactions: Moffetta88

rctimelines

Utente Èlite
4,580
1,572
CPU
AMD Ryzen 7 2700X | INTEL i5-6600k | INTEL i5-4460... altri
Dissipatore
wraith MAX | Arctic Freezer 11LP | stock
Scheda Madre
Asrock Fatal1ty 4K | Asus Prime Z270P | Acer Veriton
Hard Disk
Samsung 970evo m.2 | vari | Samsung 860 evo
RAM
16GB G.Skill TridentZ 3000 | 16GB CORSAIR 2133 | 8GB DDR3 1600
Scheda Video
RadeonPro WX3100 4G | KFA2 GTX 970 4G | Quadro k620 2G
Monitor
DELL 2419P 2K + Benq 17" | Acer 24" FHD | Benq 19" FHD
Sistema Operativo
Windows10-pro64/OpenSUSE-QL42.3/Manjaro-17.0.2-KDE
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
Reactions: Moffetta88

demda

Utente Attivo
351
49
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 automaticamente unito:

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
 

rctimelines

Utente Èlite
4,580
1,572
CPU
AMD Ryzen 7 2700X | INTEL i5-6600k | INTEL i5-4460... altri
Dissipatore
wraith MAX | Arctic Freezer 11LP | stock
Scheda Madre
Asrock Fatal1ty 4K | Asus Prime Z270P | Acer Veriton
Hard Disk
Samsung 970evo m.2 | vari | Samsung 860 evo
RAM
16GB G.Skill TridentZ 3000 | 16GB CORSAIR 2133 | 8GB DDR3 1600
Scheda Video
RadeonPro WX3100 4G | KFA2 GTX 970 4G | Quadro k620 2G
Monitor
DELL 2419P 2K + Benq 17" | Acer 24" FHD | Benq 19" FHD
Sistema Operativo
Windows10-pro64/OpenSUSE-QL42.3/Manjaro-17.0.2-KDE
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
 

demda

Utente Attivo
351
49
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
Schermata del 2020-01-09 22-03-51.png


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

rctimelines

Utente Èlite
4,580
1,572
CPU
AMD Ryzen 7 2700X | INTEL i5-6600k | INTEL i5-4460... altri
Dissipatore
wraith MAX | Arctic Freezer 11LP | stock
Scheda Madre
Asrock Fatal1ty 4K | Asus Prime Z270P | Acer Veriton
Hard Disk
Samsung 970evo m.2 | vari | Samsung 860 evo
RAM
16GB G.Skill TridentZ 3000 | 16GB CORSAIR 2133 | 8GB DDR3 1600
Scheda Video
RadeonPro WX3100 4G | KFA2 GTX 970 4G | Quadro k620 2G
Monitor
DELL 2419P 2K + Benq 17" | Acer 24" FHD | Benq 19" FHD
Sistema Operativo
Windows10-pro64/OpenSUSE-QL42.3/Manjaro-17.0.2-KDE
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
Reactions: Moffetta88

demda

Utente Attivo
351
49
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 ?
 

demda

Utente Attivo
351
49
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
 

rctimelines

Utente Èlite
4,580
1,572
CPU
AMD Ryzen 7 2700X | INTEL i5-6600k | INTEL i5-4460... altri
Dissipatore
wraith MAX | Arctic Freezer 11LP | stock
Scheda Madre
Asrock Fatal1ty 4K | Asus Prime Z270P | Acer Veriton
Hard Disk
Samsung 970evo m.2 | vari | Samsung 860 evo
RAM
16GB G.Skill TridentZ 3000 | 16GB CORSAIR 2133 | 8GB DDR3 1600
Scheda Video
RadeonPro WX3100 4G | KFA2 GTX 970 4G | Quadro k620 2G
Monitor
DELL 2419P 2K + Benq 17" | Acer 24" FHD | Benq 19" FHD
Sistema Operativo
Windows10-pro64/OpenSUSE-QL42.3/Manjaro-17.0.2-KDE
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
 

Entra

oppure Accedi utilizzando