2

stdin を介してユーザーからファイル名を取得し、open() でファイルを開き、それをファイル記述子に割り当ててから、そのファイルの内容を stdout に出力したいと考えています。これは私のコードで、正しく動作していません。

問題:

  1. printf("ファイル名を入力"); ステートメントは決して表示されません
  2. ファイルを開くことはありません。代わりに、ユーザーが入力したものはすべて画面に出力され、「そのようなファイルまたはディレクトリはありません」というエラーメッセージが出力され、プログラムが終了します
  3. プログラムが存在した後、ターミナルのプロンプトの前に「ファイル名を入力してください」と表示されます

コード:

    {
        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);
            }
        }
    }

コンソール:

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...? 
4

2 に答える 2

2

<stdio.h>入力/出力ルーチンはバッファリングされます ( stdio(3) & setbuf(3 )を参照してください。 fflush(3)を呼び出す必要があります(最近の libc では、 orstdoutで読み取ると暗黙的に呼び出されます)。同じ出力または入力の記述子とハンドル ( fileno(3)を参照してください。ただし、常に.... を呼び出します)。fgetsscanfFILEfflush

         printf("Enter the filename: ");
         read(STDIN_FILENO, userInput, sizeof(userInput));

         printf("Enter the filename: \n");
         fflush(NULL);
         if (!fgets(userInput,sizeof(userInput),stdin))
           { perror("fgets"); exit(EXIT_FAILURE); };

実際には、非常に重要な終了(改行)fflushを保持すれば回避できます。\n改行が必要ない場合は、呼び出したほうがよいでしょうfflush(ただし、一部の libc はそれを呼び出しています)。

呼び出しfflushが多すぎたり頻繁すぎたりしても、呼び出しが少なすぎたり少なすぎたりするよりも、(既にフラッシュされたすべてのストリームでノーオペレーションであるため) 害ははるかに少なくなります。

しかし、 (固定長の行を避けるために) getline(3)について学ぶ必要があります。Linux および GNU システムでは、 readlineを使用する価値があります。

于 2013-10-31T18:47:41.810 に答える
2

read()入力を取得するために標準 I/O 関数 ( 、 など) のいずれかの代わりにscanf()使用fgets()するため、プロンプトは表示されません。入力関数を変更するか、fflush(stdout)またはfflush(0)を呼び出す前に使用してread()ください。

読み取りには改行が含まれているため、open は名前の末尾に改行を付けてファイルを開こうとします。そのファイルは存在しないため、開くことはできません。

{
    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);
}
于 2013-10-31T18:51:09.510 に答える