0

ユーザー入力を検証するためのこのコードがあります。条件: 入力する値は、ゼロまたは正の数値のみにする必要があります。負の値と英字は使用できません。

これがループし続ける私のコードです:

#include <stdio.h>

int main ()
{
   int a, b, c, d;

   printf ("enter value for a:");
   do {
      b = 0;
      scanf ("%d", &a);
      if (!isdigit(a)) {
         printf("Number must be numeric!:\n");
         b++;
      }
      else if (a < 0) {
         printf ("number must be postive\n");
         b++;
      } else {
         printf("\neverything is goood\n");
      }
   } while (b != 0);
}
4

5 に答える 5

4

isdigit()はASCIIでエンコードされた文字を期待していますがscanf%d引数を使用すると、ASCIIでエンコードされた数値(文字列)を実際の数値に変換しています。

すなわち。'1'をASCIIコードで0x31入力するscanf("%d",...と、これが値に変換されます1。1のASCIIコードは数値ではありません。

これを修正するには、次のいずれかを行います。

  • タイプを作成し、フォーマット指定子を使用すると、必要aな処理が実行されます。charscanf%cisdigit()
  • strtol複数の文字を読み込み、引数を使用して独自のエラーチェックを実行するために使用しchar **endptrます。

isdigit()また、コンパイラの警告を表示し、関数を含むヘッダーファイルをインクルードする必要がありますctype.h

于 2012-07-15T01:39:03.717 に答える
1

ユーザーが間違えると、bは常に> 0になります。正しい情報を入力した後(つまり、printf( "\ neverthing is good \ n");ステートメントの後にb=0を設定する行を追加する必要があります。必ず確認してください。その前のelseステートメントに{&}を追加して、printf&new b = 0;ステートメントがそのブランチに含まれるようにします)

于 2012-07-15T01:33:21.953 に答える
1

私が見つけることができるコードのいくつかの問題は次のとおりです。

  1. 入力を整数値としてすでに解析しているフォーマット指定子とscanf一緒に使用します。%dしたがって、 で数値かどうかを確認する必要はありませんisdigit。実際、isdigitは 10 進数の文字をチェックしているため、使用方法が正しくありません。
  2. 返品を確認することはありませんscanf。あなたがすべき。エラーが発生した場合 (つまり、値が数値以外の場合)、入力はストリームから削除されません。言い換えれば、同じ悪い値を何度も解析しようとして行き詰まります。
  3. 未使用の変数があり、特定のヘッダー ファイルを含めるのを忘れています。しかし、これらはあなたの場合は些細なことです (しかし、特定の状況では重大になる可能性があります!)。

そうは言っても、ここにあなたのためにうまくいくかもしれないいくつかのコードがあります:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

static void skip_input(FILE *stream)
{
    int c;
    do {
        c = fgetc (stream);
    } while (c != EOF && c != '\n');
}

int main()
{
    int a;
    int r;

    printf("Please enter a value: ");

    for (;;) {
        r = scanf("%d", &a);
        if (r == EOF)
            return EXIT_FAILURE;
        if (r != 1) {
            printf("Number must be numeric!\n");
            skip_input(stdin);
        } else if (a < 0) {
            printf("Number must be postive\n");
            skip_input(stdin);
        } else {
            printf("Everything is goood\n");
            break;
        }
    }

    return EXIT_SUCCESS;
}

それが役に立てば幸い。

于 2012-07-15T01:50:26.493 に答える
0

エラーフラグとしてbを使用しています。

「すべてが良いブロック」で、設定してみてくださいb=0;
さらに、そうすれば、b++;行を削除して、単純に初期化できます。ユーザーが混乱した回数を報告する必要がある場合にb=1;
のみ実行する必要があります。b++あなたが必要ないと仮定しますか?

于 2012-07-15T01:33:19.863 に答える
0

ここにはいくつかの問題があります。

1 つ目は、scanf() の戻り値がチェックされていないことです。入力が利用可能な場合、scanf は割り当てられた変数の数を返します。この場合は 0 または 1 になります (変数を 1 つだけ割り当てようとしているため)。ユーザーが数字以外の文字を入力すると、使用可能な入力があるため、ユーザー入力を待たずにループが繰り返し実行されますが、「%d」変換と一致することはありません。scanf() を使用する場合は、戻り値を確認する必要があります。戻り値がゼロの場合は、数値以外の値が入力されています。つまり、行の終わりまで読み取って、入力バッファーからその値をクリアする必要があります。戻り値が EOF と等しい場合は、I/O エラーが発生したか、ストリームの終わりに達したかのいずれかです。

ルーチン isdigit() は整数の引数を取りますが、その整数値が文字を表すことを期待しています。入力を整数に変換するために scanf() を使用しているため、 a に格納されている値はもはや文字を表していません。これは実際の数値を表します。このため、 isdigit() の呼び出しは、ユーザーが数字に対応する数字を入力した場合にのみ true 値を返します。私のロケールでは、これは、ユーザーが 48 から 57 までの数字を入力した場合にのみ検証が成功することを意味します。scanf() を使用している場合、ユーザーが数値を入力した場合にのみ scanf() が値 1 を返すため、isdigit() チェックは必要ありません。

しかし、正直なところ、ユーザーが何か間違ったことを入力した場合に入力バッファーをフラッシュする必要があるため、正確に回避できるのであれば、scanf() を使用してユーザー入力を読み取ることはしません。あなたの要件が何であるかは完全にはわかりませんが、コマンドラインから正の整数を読み取る必要があり、桁数は問題ではないと仮定します。

この場合、おそらく fgets() を使用してユーザー入力を読み取り、次に strtol() を使用して値を符号付き長整数に変換し、同時に検証を実行する必要があります。

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>

int main () {
  long result;
  long len;
  int is_valid = 0;
  char buf[128];
  char *arg;
  char *end;

  while (!is_valid) {

    /* Prompt the user for the integer. */
    printf("Enter a non-negative integer: ");
    if (fgets(buf, sizeof(buf), stdin) == NULL) {
      printf("Giving up so soon?\n");
      break;
    }

    /* Verify that the input doesn't exceed our buffer length. */
    len = strlen(buf);
    if (buf[len] != '\n') {
      printf("Input buffer length exceeded - aborting.\n");
      exit(1);
    }

    /* Skip any leading whitespace. */
    for (arg = buf; isspace(*arg); arg++);

    /* Attempt to convert the argument. */
    errno = 0;
    result = strtol(arg, &end, 10);
    if (errno == EINVAL) {
      printf("Please enter a numeric value.\n");
      continue;
    }
    if (errno == ERANGE) {
      printf("Numeric value out of range.\n");
      continue;
    }

    /* Check for non-whitespace characters after the end of the integer. */
    for (; isspace(*end); end++);
    if (*end != '\0') {
      printf("Please enter a numeric value.\n");
      continue;
    }

    /* Verify that the number is non-negative. */
    if (result < 0) {
      printf("Please enter a positive value.\n");
      continue;
    }

    /* The number is valid. */
    printf("Excellent!\n");
    is_valid = 1;
  }

  return 0;
}

これは完璧ではありません。入力バッファの長さを超えた場合の中止は、ユーザーフレンドリーではありません。ただし、検証の問題は処理する必要があります。

于 2012-07-15T02:52:48.357 に答える