Errore scanf consecutivi

di il
10 risposte

Errore scanf consecutivi

Salve, sono nuovo e da pochi giorni sto studiando come primo linguaggio il C, quindi iniziando praticamente da 0.
Stavo seguendo il mio testo fino a quando non mi son imbattuto in un programma, copiato tale e quale dal libro, che però funzionava in modo errato.
Questo programma da la rappresentazione ascii di un carattere immesso e converte i caratteri minuscoli in maiuscoli.

int main() {
    char c, cm;
    printf("Inserire un carattere - # Termina il programma\n");
    scanf("%c",&c);
    while(c!='#')
    {
        printf("Il codice ASCII del carattere %c e' %d\n", c, c);
        if(c>='a' && c<='z') 
        {
            cm = c - ('a'-'A');
            printf("La lettera maiuscola per %c e' %c e il suo codice ASCII e' %d\n", c, cm, cm);
        }
        printf("Inserire un carattere - # Per terminate il programma\n");
        scanf("%c",&c);
    }
    return 0;
}
Provando ad eseguirlo, quel che succede è che l'ultimo scanf, quello nel while viene saltato a ogni iterazione e viene eseguito ogni 2 cicli.
Ho letto un po' su internet e ho letto che è dovuto allo standard input, buffering etc
(non ne ho capito tanto a dire il vero su cosa siano, il testo non ha mai menzionato questo funzionamento, a parte citare semplicemente che lo standard input può essere costituito dalla tastiera)
che lasciano uno \n nello standard input che, ragionandoci, sembra che venga poi eliminato dopo una seconda iterazione per qualche motivo..

Infatti il risultato del codice è:
Inserire un carattere - # Termina il programma
a
Il codice ASCII del carattere a e' 97
La lettera maiuscola per a e' A e il suo codice ASCII e' 65
Inserire un carattere - # Per terminate il programma
Il codice ASCII del carattere
 e' 10
Inserire un carattere - # Per terminate il programma
Ho anche letto che si può usare una funzione fflush(stdin); per pulire il buffer, e così ho provato a metterla prima dell'ultimo scanf e in effetti così funziona.
Tuttavia leggo anche che in molti sconsigliano di fare questo tipo di utilizzo per questa funzione..

Avere suggerimenti, idee, alternative? Grazie.

10 Risposte

  • Re: Errore scanf consecutivi

    Ma DEVI studiare il C o lo hai scelto tu?
    Se hai un prof e dei colleghi con cui confrontarti... vabbé.
    Ma se lo fai da autodidatta e da solo, scegli un linguaggio più semplice e più adatto ad un principiante: il C è MOLTO difficile, sotto tutti i punti di vista!
  • Re: Errore scanf consecutivi

    nicolap ha scritto:


    Ma DEVI studiare il C o lo hai scelto tu?
    Se hai un prof e dei colleghi con cui confrontarti... vabbé.
    Ma se lo fai da autodidatta e da solo, scegli un linguaggio più semplice e più adatto ad un principiante: il C è MOLTO difficile, sotto tutti i punti di vista!
    Devo studiarlo per ingegneria.
  • Re: Errore scanf consecutivi

    Scanf() "preleva" il char, ma lascia nello stream il carattere '\n' (viene aggiunto ad ogni "invio", e corrisponde al codice ASCII 10). Per questo, il primo carattere che viene rilevato dal secondo scanf() è '\n'. Puoi provare a togliertelo dai piedi facendo una cosa tipo:

    char c;
    scanf( "%c", &c );
    getchar();

    So che c'è anche un modo per configurare la stringa di controllo di scanf() (il primo parametro, per intendersi) per rendere inutile il getchar(), ma non ricordo più quale sia. Magari te lo suggerisce qualcun altro, o riesci a scoprirlo da te.

    Buon divertimento col C!
  • Re: Errore scanf consecutivi

    Basta utilizzare uno spazio prima di %c in ogni scanf

    scanf( " %c", &c );
  • Re: Errore scanf consecutivi

    Ottimo, grazie a tutti, avevo letto l'utilità dello spazio ma avevo frainteso il tipo di utilizzo.
    C'è qualche differenza nell'usare fflush(stdin) o lasciare lo spazio che tu sappia, o vantaggi e svantaggi vari?
  • Re: Errore scanf consecutivi

    Fflush non è standard quindi potrebbe non funzionare sempre.
  • Re: Errore scanf consecutivi

    Cosa intendi con "standard"?
    Ora ho anche notato qualche problema collegato a quello precedenti, che non sembra risolversi lasciando lo spazio vuoto negli scanf.

    Usando il codice
    #include <stdio.h>
    
    int main() {
        char a;
        printf("Inserisci a, b o c\n");
        scanf(" %c", &a);
        while(a!='a' && a!='b' && a!='c') {
            printf("Errato. Riprova.\n");
            scanf(" %c", &a);
        }
        printf("%c",a);
        return 0;
    }
    Se io do come input una sola lettera, allora non vi sono problemi.
    Tuttavia, se io do come input due o più lettere, possono succedere varie cose. Ho scritto (input) sugli input effettivi per rendere comprensibile quello che è stampato e quello che non lo è.

    In un primo caso
    Inserisci a, b o c
    d a (input)
    Errato. Riprova.
    a
    Process finished with exit code 0
    
    Se io do una lettera che non è valida, poi metto una lettera valida (anche preceduta da uno o più spazi), viene dato errore, ma in automatico va l'input di a (evidentemente gli spazi vengono eliminati e non considerati, che siano 0, uno o molteplici).
    Altro esempio:
    Inserisci a, b o c
    d    f   ga (input)
    Errato. Riprova.
    Errato. Riprova.
    Errato. Riprova.
    a
    Process finished with exit code 0
    
    Nel secondo caso
    Inserisci a, b o c
    bc (input)
    b
    Process finished with exit code 0
    Al posto di dare errore, viene letto comunque il primo carattere come valido.

    Come posso ovviare a questi problemi senza usare fflush(stdin)?
  • Re: Errore scanf consecutivi

    È giusto che non ti dia errore su "bc". Prova a usare direttamente a=getchar(): a quel punto la c di "bc" non riesci nemmeno a digitarla. In compenso avrai l'errore sugli spazi e quando premi invio.

    Se vuoi usare scanf per una stringa, devi mettere l'opzione %s e dovrai dichiarare a come un array di char.
  • Re: Errore scanf consecutivi

    Weierstrass ha scritto:


    a quel punto la c di "bc" non riesci nemmeno a digitarla.
    Ho studiato ora (il libro le mette molto dopo rispetto a printf e scanf..) queste funzioni riguardo i caratteri. Ho provato a scrivere un semplice programma per capire meglio il funzionamento dato che esistono varie versioni chiamate in modo simile di queste funzioni ma, usando la funzione 2, per immettere i file da tastiera:

    1. Mette una riga vuota prima del primo output.
    2. Va a capo verso dopo ogni output anche quando salva su file.
    3. Non mi ferma dall'inserire più caratteri senza prima premere invio. Anzi, se li immetto li stampa pure come una stringa..
    E non capisco i motivi di tutto ciò.
    #include <stdio.h>
    #include <stddef.h> //Per la definizione di NULL
    
    int main() {
        FILE *fp;
        char c;
        int scelta;
        char a;
        printf("Vuoi leggere testo da file o immetterlo manualmente?\n1: Da file\n2: Da tastiera\n");
        scanf("%d", &scelta);
        if (scelta==1) {
            if ((fp = fopen("D:\\directory\\in.txt","r")) != NULL)
            {
                while ((c = fgetc(fp)) != EOF) //Finche' non si finisce il testo,
                    // legge il carattere nel testo dalla posizione 0 (prima del primo carattere) avanzando di 1.
                    putchar(c); //Scrive ogni volta la lettera contenuta nella variabile c a video
                fclose(fp);
            }
            else
                printf("File impossibile da aprire\n.");
        }
        else if (scelta == 2)
        {
            if ((fp =fopen("D:\\directory\\out.txt","w")) != NULL) {
                printf("Inserire testo. # Per terminare");
                while ((c = getchar()) != '#') //Fa digitare una lettera a ogni ciclo e la assegna alla variabile c
                {
                    putchar(c); //Stampa a video la letta contenuta nella variabile c
                    fputc(c, fp); //Scrive la lettera nella variabile c nel file
                }
                fclose(fp);
            }
            else
                printf("File impossibile da aprire\n.");
        }
        else
            printf(("Scelta invalida\n"));
    
        return 0;
    }
  • Re: Errore scanf consecutivi

    XSlayer50 ha scritto:


    1. Mette una riga vuota prima del primo output.
    2. Va a capo verso dopo ogni output anche quando salva su file.
    3. Non mi ferma dall'inserire più caratteri senza prima premere invio. Anzi, se li immetto li stampa pure come una stringa.
    E non capisco i motivi di tutto ciò.
    Dipende dalle impostazioni del terminale.

    Quello che vuoi fare tu sotto Windows (Visual C++), senza toccare il terminale, si fa così:
    
    #include <conio.h>
    [...]
            if ((fp=fopen("d:\in.txt","w")) != NULL) {
                printf("Inserire testo. # Per terminare\n");
                do{
    		c = getch();
    		putchar(c);
    		fputc(c, fp);
    		if(c == '\r'){
    			putchar('\n');
    			fputc('\n', fp);
    			fflush(fp);
    		}
    	    }while(c != '#');
                fclose(fp);
            }
            else
                printf("File impossibile da aprire\n.");
    [...]
    
    Onestamente non mi ricordo sotto Linux (gcc). Mi pare che getch() sia in curses.h o qualcosa del genere
Devi accedere o registrarti per scrivere nel forum
10 risposte