7

nループのサイズを表す整数を読み取ってから、文字列を 1 行読み取りn、ユーザーの入力の直後に出力するように求める宿題をやっています。だから私はそれを使っscanfてそれを印刷しましたprintf。問題は、ユーザーの入力が改行文字のみの場合、別の を出力する必要があります\nscanf、単一の場合は入力を無視するよう\nです。

この割り当てを行う方法はありますか、scanfそれとも何か他のことを試す必要がありますか?

int i;
scanf("%d", &i);
for(int ct=0; ct<i; ct++)
{
    char buff[28];
    scanf("%s", buff); // if I just press enter here
    prtinf("%s\n", buff); // then I must get \n\n here
}
4

4 に答える 4

11

を使用fgetsして行を読み取るのは、より簡単で堅牢です。

if (!fgets(buff, 28, stdin))
{
    // reading failed, do appropriate error handling
    // we're just exiting here
    exit(EXIT_FAILURE);
}
// We have successfully read in a line, or at least the first 27
// characters of the line. Check whether a full line was read,
// if it was, whether the line was empty
size_t l = strlen(buff);    // <string.h> must be included
if (buff[l-1] == '\n')
{
    // a full line was read, remove trailing newline unless
    // the line was empty
    if (l > 1)
    {
        buff[l-1] = 0;
    }
}
else
{
    // the input was too long, what now?
    // leave the remaining input for the next iteration or
    // empty the input buffer?
}
printf("%s\n",buff);

scanf("%s",buff)ほとんどのscanf変換は先頭の空白を無視するため、これは機能しません:

指定に 、、または指定子が含まれていない限り、 (関数で指定された) 入力空白文字isspaceはスキップされます。[cn

そのため、ユーザーが空の行を入力したscanf場合、その入力の形式が例外的なものでない限り、その入力は無視されます。

scanf代わりに、文字セット形式で使用できます。

scanf("%27[^\n]%*c", buff);

改行までのすべての文字を読み取り (ただし、28 - 1バッファ オーバーランを避けるためにここに限定されます)、それから格納せずに改行を消費します (変換指定子の は代入を抑制します) *。変換はしません。しかし、入力の最初の文字が改行の場合、変換は失敗し (注目を集めてくれたchuxに感謝します)、改行は入力バッファーに残り、改行がそうでない場合、その形式での後続のスキャンも失敗します。入力バッファから削除されます。%*c%s%27[^\n]

やや堅牢な(しかし醜く、長すぎる入力を処理しない)ループを使用scanfすると、私が見る限り、スキャンする前に改行をチェックする必要があります。

for(int ct = 0; ct < i; ++ct)
{
    int ch = getchar();
    if (ch == EOF)
    {
        // something bad happened; we quit
        exit(EXIT_FAILURE);
    }
    if (ch == '\n')
    {
        // we had an empty line
        printf("\n\n");
    }
    else
    {
        // The first character was not a newline, scanning
        // with the character set format would have succeeded.
        // But we don't know what comes next, so we put the
        // character back first.
        // Although one character of pushback is guaranteed,
        if (ungetc(ch,stdin) == EOF)
        {
            // pushback failed
            exit(EXIT_FAILURE);
        }
        scanf("%27[^\n]%*c",buff);
        printf("%s\n",buff);
    }
}

を使用してくださいfgets。それは良いです。

于 2013-01-28T16:10:18.623 に答える
2

これには2つの解決策があります:

  • fgetsの代わりに使用しscanfます。
  • \n使用すると入力が で終わることがわかっているため、文字列の末尾にa を追加し\nます。

最初の解決策:

...
char buf[28];
fgets(buf, 28, stdin);
...

2番目の解決策:

#include <string.h>

...
char buf[28];
scanf("%s", buf);
strcat(buf, "\n"); // add the newline to the string
...
于 2013-01-28T16:16:53.273 に答える
0

1 つのオプションは、 を使用して一度に 1 行ずつ読み取りgets、次に を使用して各行を解析することsscanfです。

コメントに基づく編集:fgetsバッファ オーバーランを回避できるため、使用する方が適切です。

于 2013-01-28T16:00:35.470 に答える