4

このコードは、ユーザーにデータとそれに続く番号を要求します。

$ cat read.c
#include<stdio.h>
#include<stdlib.h>
#define MAX 10

int main() {
    char* c = (char*) malloc(MAX * sizeof(char));
    int num;

    printf("Enter data (max: %d chars):\n", MAX);
    fgets(c, MAX, stdin);
    // how do I discard all that is there on STDIN here?

    printf("Enter num:\n");
    scanf("%d", &num);

    printf("data: %s", c);
    printf("num: %d\n", num);
}
$

num問題は、文字の最大数を示す命令を除いて、ユーザーがそれ以上入力するのを妨げるものは何もないということです。これは、後でジャンクとして読み込まれます。

$ ./read
Enter data (max 10 chars):
lazer
Enter num:
5
data: lazer
num: 5
$ ./read
Enter data (max 10 chars):
lazerprofile
Enter num:
data: lazerprofnum: 134514043
$ 

通話STDIN後に残っているものをすべて破棄する方法はありますか?fgets

4

4 に答える 4

5

私の知る限り、ポータブルな解決策は自分でバッファを使い果たすことだけです。

while (getchar() != EOF);

それは答えfflush(stdin);ではないことに注意してください。

編集:次の改行まで文字を破棄したい場合は、次のことができます。

int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
于 2010-11-14T14:54:01.017 に答える
5

scanf()関数はユーザー入力にはひどいものであり、入力データが正しいことを何らかの方法で知らない限り、ファイル入力にはそれほど適していません(信頼できないでください)。さらに、fgets()の戻り値を常に確認する必要があります。 NULLはEOFまたはその他の例外を示しているためです。最初に最大値に達しない限り、fgets()データの最後にユーザーの改行文字が表示されることに注意してください。私は最初のパスとしてこのようにするかもしれません:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 10

void eat_extra(void) {
    int ch;

    // Eat characters until we get the newline
    while ((ch = getchar()) != '\n') {
        if (ch < 0)
            exit(EXIT_FAILURE); // EOF!
    }
}

int main() {
    char c[MAX+1]; // The +1 is for the null terminator
    char n[16]; // Arbitrary maximum number length is 15 plus null terminator
    int num;

    printf("Enter data (max: %d chars):\n", MAX);
    if (fgets(c, MAX, stdin)) { // Only proceed if we actually got input
        // Did we get the newline?
        if (NULL == strchr(c, '\n'))
            eat_extra(); // You could just exit with "Too much data!" here too

        printf("Enter num:\n");
        if (fgets(n, sizeof(n) - 1, stdin)) {
            num = atoi(n); // You could also use sscanf() here
            printf("data: %s", c);
            printf("num: %d\n", num);
        }
    }

    return 0;
}
于 2010-11-14T15:11:08.030 に答える
1

何が「起こり得る」のfgetsか?

  1. NULL入力にエラーがある場合に返されます
  2. 「実際の」文字NULLの前を見つけると戻りますEOF
  3. バッファへのポインタを返します
    1. バッファが完全に満たされていませんでした
    2. バッファは完全にいっぱいになりましたが、入力にデータがありません
    3. バッファが完全にいっぱいになり、入力にさらに多くのデータがあります

1とをどのように区別できます2か?
feof

3.1.をどのように区別できますか? 終了するヌルバイトと改行が書き込まれた場所を特定することにより:出力 バッファにが含まれている場合、それ以上のデータはあり ません(バッファが完全にいっぱいになっている可能性があります)バッファの最後の位置。待機中のデータがさらにあることがわかります。がバッファの最後の位置の前にある場合は、改行で終わらないストリームにヒットしています。3.2.3.3.

'\n'
'\n' '\0''\0'EOF

このような

/* fgets fun */
/*
char buf[SOMEVALUE_LARGERTHAN_1];
size_t buflen;
*/
if (fgets(buf, sizeof buf, stdin)) {
    buflen = strlen(buf);
    if (buflen) {
        if (buf[buflen - 1] == '\n') {
            puts("no more data (3.1. or 3.2.)"); /* normal situation */
        } else {
            if (buflen + 1 == sizeof buf) {
                puts("more data waiting (3.3.)"); /* long input line */
            } else {
                puts("EOF reached before line break (3.1.)"); /* shouldn't happen */
            }
        }
    } else {
        puts("EOF reached before line break (3.1.)"); /* shouldn't happen */
    }
} else {
    if (feof(stdin)) {
        puts("EOF reached (2.)"); /* normal situation */
    } else {
        puts("error in input (1.)");
    }
}

通常の不完全なテストは、戻り値buf[buflen - 1] == '\n'をチェックしています...fgets

while (fgets(buf, sizeof buf, stdin)) {
    if (buf[strlen(buf) - 1] != '\n') /* deal with extra input */;
}
于 2010-11-14T16:20:37.480 に答える
-1

データを読み取って、ユーザーエラーがないか確認します。

bool var = true;
while var {
printf("Enter data (max: %d chars):\n", MAX);
fgets(c, MAX, stdin);
// how do I discard all that is there on STDIN here?
if(strlen(c) <= 10)
var = false;
else
printf("Too long, try again! ");
}

一方、これを実行したくない場合は、numを2回読み取り、最初の1つを破棄します。

于 2010-11-14T14:49:04.873 に答える