Il programma non attende l’input dell’utente con scanf (“% c”, & yn);

Questo è il codice di base per un programma che sto scrivendo per esercitarmi usando i file in C. Sto cercando di rilevare se il file di output esiste già e se esiste esiste voglio chiedere all’utente se vorrebbe sovrascriverlo o meno. Questo è il motivo per cui ho prima aperto il file outfilename con fopen (outfilename, “r”); al contrario di fopen (outfilename, “w”) ;.

Rileva il caso del file non esistente, tuttavia, se esiste, esegue printf (“File di output già esistente, sovrascrittura (y / n):”); dichiarazione ma ignora completamente il scanf (“% c”, & yn); dichiarazione!

Il printf alla fine del programma legge “yn = 0” se il file non esiste e solo “yn =” se esiste. Qualcuno può aiutarmi?

#include  #include  #include  #include  int main(void) { FILE *inf; FILE *outf; char filename[21],outfilename[21]; char yn='0'; printf("Please enter an input filename: "); scanf("%s",&filename); printf("Please enter an output filename: "); scanf("%s",&outfilename); /* Open file for reading */ inf=fopen (filename,"r"); outf=fopen(outfilename,"r"); /*check that input file exists*/ if (inf!=NULL) { /*check that the output file doesn't already exist*/ if (outf==NULL){ fclose(outf); /*if it doesn't already exist create file by opening in "write" mode*/ outf=fopen(outfilename,"w"); } else { /*If the file does exist, give the option to overwrite or not*/ printf("Output file already exists, overwrite (y/n):"); scanf("%c",&yn); } } printf("\n yn=%c \n",yn); return 0; } 

 printf("Please enter an output filename: "); scanf("%s",&outfilename); 

Quando si immette la seconda stringa e si preme il tasto INVIO, una stringa e un carattere vengono inseriti nel buffer di input, ovvero: la stringa immessa e il carattere di nuova riga. La stringa viene utilizzata dallo scanf ma la nuova riga rimane nell’input buffer.

Ulteriore,

 scanf("%c",&yn); 

La prossima scanf per leggere il personaggio legge / consuma la nuova riga e quindi non attende mai l’input dell’utente.

La soluzione è consumare la nuova riga extra usando:

 scanf(" %c", &yn); ^^^ <------------Note the space 

O usando getchar()

Si consiglia di controllare la mia risposta qui per una spiegazione dettagliata passo passo del problema.

Uso

 scanf("%20s",&filename); 

e ricorda che lo stdin è bufferato dalla linea e su Linux sta seguendo una disciplina tty

Potresti usare GNU readline o ncurses se vuoi un controllo più dettagliato.

scanf("%s", ...) lascia \ n terminando la linea nell’input. Non sta causando un problema per il prossimo mentre scanf (“% s”, …) inizia saltando i bianchi. scanf("%c", ...) non lo fa e quindi leggi \n .

BTW Probabilmente incontrerai altri problemi: hai inserito degli spazi nel nome del tuo file ( %s non li legge) e se inserisci dei nomi troppo lunghi (% s non ha limitazioni nella lunghezza dell’input).

Una soluzione per il problema lamentato (ma non l’altro) consiste nell’utilizzare scanf(" %c", ...) (vedere lo spazio prima che %c ? scanf sia difficile da usare) che inizia saltando gli spazi bianchi.

 scanf("%s",&filename); 

rimuovi anche il &

scanf.c: 13: avviso: il formato ‘% s’ si aspetta tipo ‘char ‘, ma l’argomento 2 ha tipo ‘char ( ) [20u]’

Il modo migliore per gestire questo problema che ho trovato è spiegato qui .

Si consiglia di utilizzare un modo alternativo di gestire l’input ed è spiegato molto bene.

Io uso sempre questa funzione per ottenere input da parte dell’utente.

 char * read_line (char * buf, size_t length) { /**** Copyright de home.datacomm.ch/t_wolf/tw/c/getting_input.html#skip Read at most 'length'-1 characters from the file 'f' into 'buf' and zero-terminate this character sequence. If the line contains more characters, discard the rest. */ char *p; if ((p = fgets (buf, length, stdin))) { size_t last = strlen (buf) - 1; if (buf[last] == '\n') { /**** Discard the trailing newline */ buf[last] = '\0'; } else { /**** There's no newline in the buffer, therefore there must be more characters on that line: discard them! */ fscanf (stdin, "%*[^\n]"); /**** And also discard the newline... */ (void) fgetc (stdin); } /* end if */ } /* end if */ return p; } /* end read_line */ 

Vecchia risposta

Ho risolto questo tipo di problemi con questa regola:

 // first I get what I want. c = getchar(); // but after any user input I clear the input buffer // until the \n character: while (getchar() != '\n'); // this also discard any extra (unexpected) character. 

Se lo fai dopo ogni input, non ci dovrebbero essere problemi.