10

ユーザーが整数変数に浮動小数点数を入力すると、無効な入力を出力したい。それは可能ですか?

 int a;
 scanf("%d",&a); // if user enters 4.35 print invalid input 

このようなキャラクターを試してみました

  if(scanf("%d",&a)==1);
  else printf("invalid input");

しかし、浮動小数点数の場合はどうすればよいですか。ユーザーが入力4.35すると切り捨てられ4ますが、無効な入力が必要です。

4

9 に答える 9

11

小数点の前に任意の桁がある浮動小数点数の先頭は整数のように見えるため、%d単独でこれを検出する方法はありません。

行全体を読んでから、次のようfgets()に分析することを検討してsscanf()ください。

int a;
int n;
char line[4096];
if (fgets(line, sizeof(line), stdin) != 0 && sscanf(line, "%d%n", &a, &n) == 1)
   ...analyze the character at line[n] for validity...

(そして、はい、1 と比較するつもりでした。変換仕様は、 et al.%nからの戻り値にはカウントされません。)sscanf()

scanf()このコードではできないことの 1 つは、数値を入力する前に空白行をスキップすることです。それが問題になる場合は、ループをコーディングして (空でない) 行まで読み取り、次に空でない行を解析する必要があります。また、回線上に後続のジャンク (存在する場合) がどれだけ許容されるかを決定する必要があります。空白は使用できますか? タブ?アルファ文字?句読点?

于 2013-08-20T15:46:32.403 に答える
4

double として読み取ってから、整数かどうかを確認する必要があります。整数かどうかを確認する最善の方法は、modfを使用することです。これは double の小数部分を返します。エラーがある場合:

double d;
scanf("%lf", &d);

double temp;
if(modf(d, &temp)){
  // Handle error for invalid input
}

int a = (int)temp;

0これにより、 のように小数点の後に sのみを持つ整数または浮動小数点数が許可され54.00000ます。それも無効と見なしたい場合は、文字ごとに読み取り、各文字が ~09(ASCII 48 ~ 57) の間にあることを確認することをお勧めします。

于 2013-08-20T15:47:12.760 に答える
3

intこれは、スキャンを停止した原因を確認するためにパスを読み取らないと実行できません。

古典イディオム

char buf[100];
if (fgets(buf, sizeo(buf), stdin) == NULL) {
  ; // deal with EOF or I/O error
}
int a;
char ch;
if (1 != sscanf(buf, "%d %c", &a, &ch)) {
  ; // Error: extra non-white space text
}
于 2013-08-20T15:56:51.327 に答える
2

エンドポインターを使用strtol()strtod()て比較することで、これを行うことができます。たとえば、次のようになります。

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

int main(void) {
    char buffer[100];
    char * endptr_n;
    char * endptr_d;
    long n;
    double d;

    fgets(buffer, 100, stdin);
    n = strtol(buffer, &endptr_n, 10);
    if ( endptr_n == buffer ) {
        fputs("You didn't enter a number.", stderr);
        return EXIT_FAILURE;
    }

    d = strtod(buffer, &endptr_d);

    if ( *endptr_d == '\0' || *endptr_d == '\n' ) {
        if ( endptr_d == endptr_n ) {
            puts("You entered just a plain integer.");
        } else {
            puts("You entered a floating point number - invalid.");
        }
    } else {
        puts("You entered garbage after the number - invalid.");
    }

    return EXIT_SUCCESS;
}

出力:

paul@local:~/src/c$ ./testint
2
You entered just a plain integer.
paul@local:~/src/c$ ./testint
2.3
You entered a floating point number - invalid.
paul@local:~/src/c$ ./testint
3e4
You entered a floating point number - invalid.
paul@local:~/src/c$ ./testint
4e-5
You entered a floating point number - invalid.
paul@local:~/src/c$ ./testint
423captainpicard
You entered garbage after the number - invalid.
paul@local:~/src/c$

は使用しませんがscanf()、それは良いことであり、読み取った整数に続く入力を手動でチェックする必要がなくなります。

strtol()明らかに、回線上の唯一のものが番号である場合、電話してすぐに確認できるため、これの多くは不要になりますが*endptr_n、回線上に他のものがある可能性がある場合は、これを行う方法です。整数の後に数値以外が続くものは受け入れたいが、浮動小数点の後に同じものが続くのは受け入れたくない場合は、if ( *endptr_d == '\0' || *endptr_d == '\n' )ロジックを削除するだけです。

編集: にチェックを表示するようにコードを更新しました*endptr

于 2013-08-20T23:14:32.970 に答える
1

まず第一に、何も問題はありませんscanf。ユーザーが float を入力すると、実際には number dot number を入力します。そのため、scanf をコーディングして、そのデータ エントリを検出します。

main()
  {
       char c1[2];
       int num1;

       int nr_nums;

       nr_nums = scanf("%d%1[.e0123456789]", &num1, &c1);

       if (nr_nums == 1) {printf("\ndata = %d", num1);}
       if (nr_nums == 2) {printf("\nInvalid");}

 }

コメントで提案されているように、1. または 3e-1 の別の可能なデータ入力形式に従ってこのコードを変更しました。

このコードは、要件の基本に到達します。整数データ入力を受け入れ、float が入力されたことを検出します。

于 2013-08-20T20:47:01.247 に答える
1

簡単な方法は次のとおりです。

#include <stdio.h>

int main(int argc, char **argv) {
    int d;
    printf("Type something: ");

    // make sure you read %d and the next one is '\n'
    if( scanf("%d", &d) == 1 && getchar() == '\n' ) {
        printf("%d\n", d);
    }

    return 0;
}

.

$ a.exe
Type something: 312312.4214

$ a.exe
Type something: 2312312
2312312

$ a.exe
Type something: 4324.

$
于 2013-08-20T17:15:21.730 に答える
0

数値を文字列として表した場合 (fgets を使用した場合)、for ループを実行して、各文字を '.' と比較できます。

于 2016-04-01T03:18:07.933 に答える