RISOLTO [C] Programma che salva in una tabella solo lettere minuscole

Stato
Discussione chiusa ad ulteriori risposte.

Vito-

Utente Attivo
184
14
Ciao, devo creare un programma che salvi in una tabella solo lettere minuscole e il programma termina con '#'. Se si immette un carattere maiuscolo o un numero il programma non lo salva.
Io ho fatto questo. Dov'é l'errore? Perche quando lo avvio appena metto un carattere e premo invio parte un loop infinito con "Carattere non ammesso".



C:
#include <stdio.h>
#define N 100

int main()

{
    int i=0, arrayCaratteri[N];
    char carattere;

    printf("Inserire un carattere minuscolo per volta\n");
    scanf("%d", &carattere);

    while(carattere!='#')
    {
        if(carattere<'a' || carattere>'z')
            printf("Carattere non amesso.");

            else
            {
                arrayCaratteri[i]=carattere;
                i++;
                scanf("%d", &carattere);
            }
    }





    return(0);


}
 
Ultima modifica da un moderatore:

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
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
Ci sono tre errori nel tuo codice:

  1. leggi da tastiera usando %d, ma in realtà stai leggendo dei char, quindi devi utilizzare %c
  2. quando un carattere è sbagliato, non andrai mai a leggere il successivo: la scanf che legge il carattere devi spostarla fuori dall'if (sotto all'else)
  3. la condizione dell'if è sbagliata: tu vuoi che siano accettati solo i caratteri compresi tra a e z (compresi) quindi devi utilizzare una && e non un OR.
In merito al punto 3, facendo come hai fatto tu, se inserisci ad esempio f che è maggiore di 'a', questo provoca il messaggio di errore in quanto l'if viene valutato come "f è minore di a?" siccome la risposta è negativa (f > a) l'OR non viene nemmeno valutato e di conseguenza ti entra nell'if.

Ricorda che quando leghi le condizioni con l'OR è sufficiente che una sia sia soddisfatta; ecco perchè devi utilizzare una &&, perchè tu vuoi che il valore inserito sia maggiore o uguale ad 'a' E minore o uguale a 'z'.

PS: altra cosa, visto che hai un else più lungo di una sola istruzione e devi quindi usare le parentesi graffe, sarebbe meglio se utilizzassi anche le graffe sull'if. In questo modo oltre ad essere meglio leggibile eviti di cadere in qualche errore (del tipo che pensi di essere all'interno dell'if e invece non lo sei, visto che mancano le parentesi). ? A tal proposito fai anche attenzione a come l'hai indentato.
 

Vito-

Utente Attivo
184
14
Ci sono tre errori nel tuo codice:

  1. leggi da tastiera usando %d, ma in realtà stai leggendo dei char, quindi devi utilizzare %c
  2. quando un carattere è sbagliato, non andrai mai a leggere il successivo: la scanf che legge il carattere devi spostarla fuori dall'if (sotto all'else)
  3. la condizione dell'if è sbagliata: tu vuoi che siano accettati solo i caratteri compresi tra a e z (compresi) quindi devi utilizzare una && e non un OR.
In merito al punto 3, facendo come hai fatto tu, se inserisci ad esempio f che è maggiore di 'a', questo provoca il messaggio di errore in quanto l'if viene valutato come "f è minore di a?" siccome la risposta è negativa (f > a) l'OR non viene nemmeno valutato e di conseguenza ti entra nell'if.

Ricorda che quando leghi le condizioni con l'OR è sufficiente che una sia sia soddisfatta; ecco perchè devi utilizzare una &&, perchè tu vuoi che il valore inserito sia maggiore o uguale ad 'a' E minore o uguale a 'z'.

PS: altra cosa, visto che hai un else più lungo di una sola istruzione e devi quindi usare le parentesi graffe, sarebbe meglio se utilizzassi anche le graffe sull'if. In questo modo oltre ad essere meglio leggibile eviti di cadere in qualche errore (del tipo che pensi di essere all'interno dell'if e invece non lo sei, visto che mancano le parentesi). ? A tal proposito fai anche attenzione a come l'hai indentato.
Intanto grazie mille!
In che senso indentato?
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
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
In che senso indentato?

Il tuo codice è così:
C:
       if(carattere<'a' || carattere>'z')
            printf("Carattere non amesso.");

            else
            {
                arrayCaratteri[i]=carattere;
                i++;
                scanf("%d", &carattere);
            }

hai il printf che è giustamente indentato (cioè, è spaziato all'inizio, poichè è parte dell'if, del suo corpo); hai però lo stesso spazio sull'else, che è quindi indentato anche lui. Non è sbagliato formalmente eh, solo che potresti far confusione perchè, specie se hai costrutti diversi (come gli else-if ad esempio) rischi di non accorgerti che stai scrivendo in un blocco piuttosto che nell'altro.

Quindi insomma, è sufficiente che lo trasformi in:
C:
       if(carattere<'a' || carattere>'z')
            printf("Carattere non amesso.");

       else
       {
            arrayCaratteri[i]=carattere;
            i++;
            scanf("%d", &carattere);
        }

per questioni di leggibilità poi puoi anche usare le parentesi sull'if, come dicevo sopra:

C:
       if(carattere<'a' || carattere>'z')
       {
            printf("Carattere non amesso.");
       }
       else
       {
            arrayCaratteri[i]=carattere;
            i++;
            scanf("%d", &carattere);
        }

così in caso dovessi aggiungere qualcosa nell'if puoi aggiungerlo senza "ricordarti" che mancano le parentesi.

Ma è solo per evitare possibili errori (specie quando lavorerai, o su progetti più grandi ?), non perchè sia scorretto fatto in un altro modo.

Ps. non ho corretto il tuo codice, ricordati sempre quanto dicevo nel primo post, sulla scanf.
 

Vito-

Utente Attivo
184
14
Il tuo codice è così:
C:
       if(carattere<'a' || carattere>'z')
            printf("Carattere non amesso.");

            else
            {
                arrayCaratteri[i]=carattere;
                i++;
                scanf("%d", &carattere);
            }

hai il printf che è giustamente indentato (cioè, è spaziato all'inizio, poichè è parte dell'if, del suo corpo); hai però lo stesso spazio sull'else, che è quindi indentato anche lui. Non è sbagliato formalmente eh, solo che potresti far confusione perchè, specie se hai costrutti diversi (come gli else-if ad esempio) rischi di non accorgerti che stai scrivendo in un blocco piuttosto che nell'altro.

Quindi insomma, è sufficiente che lo trasformi in:
C:
       if(carattere<'a' || carattere>'z')
            printf("Carattere non amesso.");

       else
       {
            arrayCaratteri[i]=carattere;
            i++;
            scanf("%d", &carattere);
        }

per questioni di leggibilità poi puoi anche usare le parentesi sull'if, come dicevo sopra:

C:
       if(carattere<'a' || carattere>'z')
       {
            printf("Carattere non amesso.");
       }
       else
       {
            arrayCaratteri[i]=carattere;
            i++;
            scanf("%d", &carattere);
        }

così in caso dovessi aggiungere qualcosa nell'if puoi aggiungerlo senza "ricordarti" che mancano le parentesi.

Ma è solo per evitare possibili errori (specie quando lavorerai, o su progetti più grandi ?), non perchè sia scorretto fatto in un altro modo.

Ps. non ho corretto il tuo codice, ricordati sempre quanto dicevo nel primo post, sulla scanf.
ok grazie.

ps. E un problema se scrivo spesso, magari puo diventare noioso??
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
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
ok grazie.

ps. E un problema se scrivo spesso, magari puo diventare noioso??

Se apri molti topic intendi, o se fai molte domande?
A entrambe le domande la risposta è assolutamente no, tranquillo! Tutti noi siamo qui per contribuire e dare una mano - e riceverla quando ne necessitiamo. ?
 
  • Mi piace
Reazioni: Andretti60

Andretti60

Utente Èlite
6,440
5,091
@DispatchCode a me il if pare corretto, in quanto esclude caratteri al di fuori dell’intervallo valido, quindi va bene il OR. O stamattina ho preparato decaf per sbaglio :)

Un altro errore, parecchio grave. Termini il ciclo di lettura solo quando si digita #, ma devi fare anche il controllo di non memorizzare più caratteri di quello che la lunghezza del vettore ti permette (ossia appena il valore dell’indice i è uguale a N)
 
  • Mi piace
Reazioni: DispatchCode

Vito-

Utente Attivo
184
14
Se apri molti topic intendi, o se fai molte domande?
A entrambe le domande la risposta è assolutamente no, tranquillo! Tutti noi siamo qui per contribuire e dare una mano - e riceverla quando ne necessitiamo. ?
Grazie! :)
Post unito automaticamente:

@DispatchCode a me il if pare corretto, in quanto esclude caratteri al di fuori dell’intervallo valido, quindi va bene il OR. O stamattina ho preparato decaf per sbaglio :)

Un altro errore, parecchio grave. Termini il ciclo di lettura solo quando si digita #, ma devi fare anche il controllo di non memorizzare più caratteri di quello che la lunghezza del vettore ti permette (ossia appena il valore dell’indice i è uguale a N)
Quindi nella condizione dell'if dovrei aggiungere "&& carattere<N"?
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
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
@DispatchCode a me il if pare corretto, in quanto esclude caratteri al di fuori dell’intervallo valido, quindi va bene il OR. O stamattina ho preparato decaf per sbaglio :)

Un altro errore, parecchio grave. Termini il ciclo di lettura solo quando si digita #, ma devi fare anche il controllo di non memorizzare più caratteri di quello che la lunghezza del vettore ti permette (ossia appena il valore dell’indice i è uguale a N)

Magari sono stato io che ho preso un tè decaffeinato, vediamo...

Si, hai ragione ?
Mio errore, in effetti deve uscire se è minore di uno o maggiore dell'altro, sono stato io che ho "invertito" la condizione quando l'ho letto.

Tuttavia mi sa che si genera qualche problema dovuto al buffer di input (ovvero che rimanga il new line nel buffer). O sbaglio?

Quindi nella condizione dell'if dovrei aggiungere "&& carattere<N"?
No, devi usare come condizione i< N, questo perchè l'indice dell'array è la variabile i.
 
  • Mi piace
Reazioni: Andretti60

Vito-

Utente Attivo
184
14
Magari sono stato io che ho preso un tè decaffeinato, vediamo...

Si, hai ragione ?
Mio errore, in effetti deve uscire se è minore di uno o maggiore dell'altro, sono stato io che ho "invertito" la condizione quando l'ho letto.

Tuttavia mi sa che si genera qualche problema dovuto al buffer di input (ovvero che rimanga il new line nel buffer). O sbaglio?


No, devi usare come condizione i< N, questo perchè l'indice dell'array è la variabile i.
se metto OR va in loop
Post unito automaticamente:

se metto OR va in loop
Solo che provandolo anche se metto tipo un carattere maiuscolo e poi stampo Me lo da comunque anche se non dovrebbe memorizzarlo...
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
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
Pubblica tutto il codice, così vediamo come l'hai aggiornato.
 
  • Mi piace
Reazioni: Andretti60

Andretti60

Utente Èlite
6,440
5,091
Dispatch e io abbiamo usato il termine OR che in C corrisponde all’operatore || che è quello che hai usato tu, quindi non devi modificare il tuo if (se non per l’aggiunta dell’indice del vettore)
 

Vito-

Utente Attivo
184
14
Pubblica tutto il codice, così vediamo come l'hai aggiornato.
C:
#include <stdio.h>
#define N 100

int main()

{
    int i=0, arrayCaratteri[N];
    char carattere;

    printf("Inserire un carattere minuscolo per volta\n\n");
    scanf("%c", &carattere);

    while(carattere!='#')
    {
        if(carattere<'a' && carattere>'z')
        {
            continue;
        }

        else
        {
            arrayCaratteri[i]=carattere;
            i++;
            scanf("%c", &carattere);
        }
    }

    for(int n=0;n<i;n++)
        printf("%c", arrayCaratteri[n]);





    return(0);


}
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
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
C:
#include <stdio.h>
#define N 100

int main()

{
    int i=0, arrayCaratteri[N];
    char carattere;

    printf("Inserire un carattere minuscolo per volta\n\n");
    scanf("%c", &carattere);

    while(carattere!='#')
    {
        if(carattere<'a' && carattere>'z')
        {
            continue;
        }

        else
        {
            arrayCaratteri[i]=carattere;
            i++;
            scanf("%c", &carattere);
        }
    }

    for(int n=0;n<i;n++)
        printf("%c", arrayCaratteri[n]);





    return(0);


}

Frena frena...
Il tuo if è giusto come hai fatto prima, quindi dovrai usare || e non && come ti avevo suggerito inizialmente io (avevo letto la condizione invertita... quindi ti ho detto di cambiarla).

L'errore è che hai lasciato lo scanf nell'else, devi spostarlo al di fuori dell'else, sotto insomma (come dicevo nel primo intervento).

Poi devi solo aggiungere la condizione che giustamente diceva Andretti, ovvero && i < N nel while, altrimenti andresti avanti all'infinito (ok che difficilmente uno metterà più di 100 elementi... però fatto così è scorretto).
 
  • Mi piace
Reazioni: Vito-

Andretti60

Utente Èlite
6,440
5,091
No, il tuo codice è ancora sbagliato.
Il codice non va scritto a caso, provando finché funziona (o pare funzionare) bisogna pensarci su. Devi pensare cosa succede quando digiti un carattere giusto e uno sbagliato, e vedere cosa fa il tuo codice in quei casi, vedrai subito gli sbagli.
 
Stato
Discussione chiusa ad ulteriori risposte.

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

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili