RISOLTO [C] stringa palindrome

demda

Utente Attivo
352
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
5,144
2,023
CPU
Ryzen 7 2700X | i7-6700k@4.5 | i5-4460... altri
Dissipatore
wraith MAX | Scythe Katana2|Arctic Freezer 11LP
Scheda Madre
Asrock B450 Fatal1ty 4K | Asus Prime Z270P | Acer Veriton
HDD
Samsung 970evo m.2 | vari | Samsung 860 evo
RAM
16GB G.Skill TridentZ 3000 | 16GB CORSAIR 2133 | 8GB DDR3 1600
GPU
RadeonPro WX3100 4G | ZOTAC GTX 1070 8G | Quadro k620 2G
Monitor
DELL 2419P 2K + Benq 17" | LG Ultrawide 27''
Net
fibra 1000
OS
Windows10-pro64/OpenSUSE-QL15.1/Debian 10.3
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
Reazioni: Moffetta88

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,222
1,853
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
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
352
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
352
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
6,440
5,091
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
Reazioni: Moffetta88

rctimelines

Utente Èlite
5,144
2,023
CPU
Ryzen 7 2700X | i7-6700k@4.5 | i5-4460... altri
Dissipatore
wraith MAX | Scythe Katana2|Arctic Freezer 11LP
Scheda Madre
Asrock B450 Fatal1ty 4K | Asus Prime Z270P | Acer Veriton
HDD
Samsung 970evo m.2 | vari | Samsung 860 evo
RAM
16GB G.Skill TridentZ 3000 | 16GB CORSAIR 2133 | 8GB DDR3 1600
GPU
RadeonPro WX3100 4G | ZOTAC GTX 1070 8G | Quadro k620 2G
Monitor
DELL 2419P 2K + Benq 17" | LG Ultrawide 27''
Net
fibra 1000
OS
Windows10-pro64/OpenSUSE-QL15.1/Debian 10.3
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
Reazioni: Moffetta88

demda

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

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
5,144
2,023
CPU
Ryzen 7 2700X | i7-6700k@4.5 | i5-4460... altri
Dissipatore
wraith MAX | Scythe Katana2|Arctic Freezer 11LP
Scheda Madre
Asrock B450 Fatal1ty 4K | Asus Prime Z270P | Acer Veriton
HDD
Samsung 970evo m.2 | vari | Samsung 860 evo
RAM
16GB G.Skill TridentZ 3000 | 16GB CORSAIR 2133 | 8GB DDR3 1600
GPU
RadeonPro WX3100 4G | ZOTAC GTX 1070 8G | Quadro k620 2G
Monitor
DELL 2419P 2K + Benq 17" | LG Ultrawide 27''
Net
fibra 1000
OS
Windows10-pro64/OpenSUSE-QL15.1/Debian 10.3
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
352
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
5,144
2,023
CPU
Ryzen 7 2700X | i7-6700k@4.5 | i5-4460... altri
Dissipatore
wraith MAX | Scythe Katana2|Arctic Freezer 11LP
Scheda Madre
Asrock B450 Fatal1ty 4K | Asus Prime Z270P | Acer Veriton
HDD
Samsung 970evo m.2 | vari | Samsung 860 evo
RAM
16GB G.Skill TridentZ 3000 | 16GB CORSAIR 2133 | 8GB DDR3 1600
GPU
RadeonPro WX3100 4G | ZOTAC GTX 1070 8G | Quadro k620 2G
Monitor
DELL 2419P 2K + Benq 17" | LG Ultrawide 27''
Net
fibra 1000
OS
Windows10-pro64/OpenSUSE-QL15.1/Debian 10.3
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
Reazioni: Moffetta88

demda

Utente Attivo
352
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
352
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
5,144
2,023
CPU
Ryzen 7 2700X | i7-6700k@4.5 | i5-4460... altri
Dissipatore
wraith MAX | Scythe Katana2|Arctic Freezer 11LP
Scheda Madre
Asrock B450 Fatal1ty 4K | Asus Prime Z270P | Acer Veriton
HDD
Samsung 970evo m.2 | vari | Samsung 860 evo
RAM
16GB G.Skill TridentZ 3000 | 16GB CORSAIR 2133 | 8GB DDR3 1600
GPU
RadeonPro WX3100 4G | ZOTAC GTX 1070 8G | Quadro k620 2G
Monitor
DELL 2419P 2K + Benq 17" | LG Ultrawide 27''
Net
fibra 1000
OS
Windows10-pro64/OpenSUSE-QL15.1/Debian 10.3
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
 

Ci sono discussioni simili a riguardo, dai un'occhiata!

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili