を使用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
はスキップされます。[
c
n
そのため、ユーザーが空の行を入力した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
。それは良いです。