问题
I want to get a file name from a user via stdin, open the file with open() and assign it to a file descriptor, then print the contents of that file to stdout. This is my code, and it's not working properly.
Problems:
- the printf("enter filename"); statement is never showing up
- it never opens the file; instead whatever the user inputs is printed to the screen and then the "no such file or directory" error message is printed and the program exits
- after the program exists i see "enter filename" printed before the prompt in terminal
CODE:
{
printf("Enter the filename: ");
read(STDIN_FILENO, userInput, sizeof(userInput));
if((input_file1 = open(userInput, O_RDONLY)) < 0)
{
perror(userInput);
exit(1);
}
while((n = read(input_file1, buffer, sizeof(buffer))) > 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...?
回答1:
<stdio.h>
input/output routines are buffered (see stdio(3) & setbuf(3). You need to call fflush(3) (on recent libc, it is implicitly called for stdout
if you read with fgets
or scanf
). And you really should avoid mixing file descriptors and FILE
handles on the same output or input (see fileno(3) but always call fflush
....).
So replace
printf("Enter the filename: ");
read(STDIN_FILENO, userInput, sizeof(userInput));
with
printf("Enter the filename: \n");
fflush(NULL);
if (!fgets(userInput,sizeof(userInput),stdin))
{ perror("fgets"); exit(EXIT_FAILURE); };
Actually here the fflush
could be avoided if you keep the very important terminating \n
(newline). If you don't want any newline you should better call fflush
(but some libc are calling it for you).
Calling fflush
too much or too often is much less harmful (because on all already flushed stream it is a no-op) than calling it too little or not enough.
But you should learn about getline(3) (to avoid fixed-length lines). On Linux and GNU systems readline is worth using: it enables you to give a sexy prompt, and your user to edit the typed line.
回答2:
Your prompt never appears because you use read()
instead of one of the Standard I/O functions (scanf()
, fgets()
, etc) to get the input. Either change the input function or use fflush(stdout)
or fflush(0)
before calling read()
.
Your read includes the newline, so the open tries to open the file with a newline at the end of the name. That file doesn't exist, so the open fails.
{
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);
}
来源:https://stackoverflow.com/questions/19714338/c-low-level-standard-in-to-accept-filename-then-printing-file-contents-to-stdout