Voglio ottenere un nome file da un utente tramite stdin, aprire il file con open () e assegnarlo a un descrittore di file, quindi stampare il contenuto di quel file su stdout. Questo è il mio codice e non funziona correttamente.
I problemi:
CODICE:
{ printf("Enter the filename: "); read(STDIN_FILENO, userInput, sizeof(userInput)); if((input_file1 = open(userInput, O_RDONLY)) 0) { if((write(STDOUT_FILENO, buffer, n)) < 0) { perror("failed to write to standard-out"); close(input_file1); exit(1); } } }
Console:
machine{user1}168: ls // to show that the file exists a.out backup file1 machine{user1}170: ./a.out file1 // this is user input file1 // this is printed for no reason : No such file or directory // ???? Enter the filename: machine{user1}171: // now the prompt is printed...?
routine di input / output sono bufferizzate (vedi stdio (3) & setbuf (3) . Devi chiamare fflush (3) (su libc recente, è implicitamente chiamato per stdout
se leggi con fgets
o scanf
) E dovresti davvero evitare di mescolare i descrittori di file e le maniglie FILE
sullo stesso output o input (vedi fileno (3) ma chiama sempre fflush
….). Sostituisci
printf("Enter the filename: "); read(STDIN_FILENO, userInput, sizeof(userInput));
con
printf("Enter the filename: \n"); fflush(NULL); if (!fgets(userInput,sizeof(userInput),stdin)) { perror("fgets"); exit(EXIT_FAILURE); };
In realtà qui la fflush
potrebbe essere evitata se si mantiene l’importantissimo terminando \n
(newline). Se non vuoi una nuova riga dovresti chiamare fflush
(ma alcuni libc lo chiamano per te).
Chiamare fflush
troppo o troppo spesso è molto meno dannoso (perché su tutto il stream già scaricato è un no-op) piuttosto che chiamarlo troppo piccolo o non abbastanza.
Ma dovresti sapere su getline (3) (per evitare linee a lunghezza fissa). Su sistemi Linux e GNU vale la pena usare readline : ti permette di dare un prompt sexy e il tuo utente a modificare la riga dattiloscritta.
Il prompt non viene mai visualizzato perché si utilizza read()
anziché una delle funzioni I / O standard ( scanf()
, fgets()
, ecc.) Per ottenere l’input. fflush(stdout)
funzione di input o usare fflush(stdout)
o fflush(0)
prima di chiamare read()
.
La tua lettura include la nuova riga, quindi l’open tenta di aprire il file con una nuova riga alla fine del nome. Quel file non esiste, quindi l’open fallisce.
{ printf("Enter the filename: "); if (fgets(userInput, sizeof(userInput), stdin) == 0) { fprintf(stderr, "Oops!\n"); exit(1); } userInput[strlen(userInput)-1] = '\0'; if ((input_file1 = open(userInput, O_RDONLY)) < 0) { perror(userInput); exit(1); } while ((n = read(input_file1, buffer, sizeof(buffer))) > 0) { if (printf("%.*s", n, buffer)) != n) { perror("failed to write to standard-out"); close(input_file1); exit(1); } } close(input_file1); }