scanf("%d",&rows)の代わりに使用scanf("%s",input)
これにより、intに変換しなくても、stdinから整数値を直接取得できます。
ユーザーが数字以外の文字を含む文字列を入力した場合は、次の文字列の前にstdinをクリーンアップする必要がありますscanf("%d",&rows)。
コードは次のようになります。
#include <stdio.h>
#include <stdlib.h>
int clean_stdin()
{
while (getchar()!='\n');
return 1;
}
int main(void)
{
int rows =0;
char c;
do
{
printf("\nEnter an integer from 1 to 23: ");
} while (((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin()) || rows<1 || rows>23);
return 0;
}
説明
1)
scanf("%d%c", &rows, &c)
これは、ユーザー入力から整数を期待し、それに近い数字以外の文字を期待することを意味します。
例1:ユーザーが入力aaddkとENTER、scanfは0を返します。大文字と小文字は区別されません。
例2:ユーザーが入力45とENTER、scanfは2を返します(2つの要素がキャプされます)。ここ%dにキャッピングが45あり、%cキャッピング\n
例3:ユーザーが入力45aaaddとENTER、scanfは2を返します(2つの要素がキャプされます)。ここ%dにキャッピングが45あり、%cキャッピングa
2)
(scanf("%d%c", &rows, &c)!=2 || c!='\n')
例1:この条件はTRUE、scanfが0(!=2)
例2の場合:この条件はFALSE、scanfが戻り2、c == '\n'
例3の場合:この条件はTRUE、scanfが戻り2、c == 'a' (!='\n')
3)
((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())
clean_stdin()関数が常にTRUE戻るためです1
例1の場合:(scanf("%d%c", &rows, &c)!=2 || c!='\n')はTRUE、後の条件を&&チェックする必要があるため、clean_stdin()が実行され、条件全体はTRUE
例2の場合:これ(scanf("%d%c", &rows, &c)!=2 || c!='\n')はFALSE、後の条件&&がチェックされないため(結果が条件全体になるためFALSE)、clean_stdin()実行されず、条件全体がFALSE
例3の場合:(scanf("%d%c", &rows, &c)!=2 || c!='\n')はTRUE、後の条件を&&チェックする必要があるため、clean_stdin()が実行され、条件全体はTRUE
したがってclean_stdin()、ユーザーが数字以外の文字を含む文字列を入力した場合にのみ実行されることに注意してください。
そして、この状態は、ユーザーが他に何も入力しない場合にのみ((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())返されますFALSEinteger
そして、条件((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())がFALSEであり、integerがとの間に1ある23場合、whileループは中断されます。そうでない場合、whileループは続行されます。