web-dev-qa-db-ja.com

入力がCの整数型かどうかを確認します

難点は、atoiまたはそのような他の関数を使用できないことです(数学演算に依存することになっていると確信しています)。

 int num; 
 scanf("%d",&num);
 if(/* num is not integer */) {
  printf("enter integer");
  return;
 }

私はもう試した:

(num*2)/2 == num
num%1==0
if(scanf("%d",&num)!=1)

しかし、これらのどれも機能しませんでした。

何か案は?

28
Gal

numであるため、intには常に整数が含まれます。コードのreal問題は、scanf戻り値をチェックしないことです。 scanf は、正常に読み取られたアイテムの数を返します。したがって、この場合、有効な値に対して1を返す必要があります。そうでない場合、無効な整数値が入力され、num変数はおそらく変更されませんでした(つまり、初期化していないため、まだ任意の値を保持しています)。

コメントの時点では、ユーザーに整数の入力とEnterキーの入力のみを許可したいと考えています。残念ながら、これはscanf("%d\n")で簡単に達成することはできませんが、それを行うコツは次のとおりです。

int num;
char term;
if(scanf("%d%c", &num, &term) != 2 || term != '\n')
    printf("failure\n");
else
    printf("valid integer followed by enter key\n");
37
AndiDog

まず入力を文字列として読み取り、次に文字列を解析して有効な数字が含まれているかどうかを確認する必要があります。その場合、整数に変換できます。

char s[MAX_LINE];

valid = FALSE;
fgets(s, sizeof(s), stdin);
len = strlen(s);
while (len > 0 && isspace(s[len - 1]))
    len--;     // strip trailing newline or other white space
if (len > 0)
{
    valid = TRUE;
    for (i = 0; i < len; ++i)
    {
        if (!isdigit(s[i]))
        {
            valid = FALSE;
            break;
        }
    }
}
23
Paul R

%d変換指定子でscanfを使用してこれを行うには、いくつかの問題があります。

  1. 入力文字列が有効な整数(「12abc」など)で始まる場合、「12」が入力ストリームから読み取られ、変換されてnumに割り当てられ、scanfが返されます1。したがって、(おそらく)すべきでないときに成功を示します。

  2. 入力文字列does n'tが数字で始まる場合、scanfは入力ストリームからany文字を読み取らず、numは変更されず、戻り値は0になります。

  3. 非10進形式を処理する必要があるかどうかは指定しませんが、8進形式または16進形式(0x1a)の整数値を処理する必要がある場合は機能しません。 %i変換指定子は、10進数、8進数、および16進数の形式を処理しますが、まだ最初の2つの問題があります。

まず、入力を文字列として読み込む必要があります(fgetsを使用することが望ましい)。 atoiの使用が許可されていない場合、おそらくstrtolの使用も許可されていません。そのため、文字列の各文字を調べる必要があります。数字の値をチェックする安全な方法は、isdigitライブラリ関数を使用することです(それぞれ8進数と16進数をチェックするisodigit関数とisxdigit関数もあります)。なので

while (*input && isdigit(*input))
   input++;    

isdigitisodigit、またはisxdigitを使用することさえ許可されていない場合、本当に必要以上に課題を難しくするために教師/教授を平手打ちしてください) 。

8進形式または16進形式を処理できるようにする必要がある場合は、もう少し複雑になります。 Cの規則では、8進数形式では先頭に0数字が付き、16進数形式では先頭に0xが付きます。したがって、最初の非空白文字が0の場合、使用する非10進形式を知る前に、次の文字を確認する必要があります。

基本的なアウトラインは

  1. 最初の非空白文字が「-」、「+」、「0」、またはゼロ以外の10進数でない場合、これは有効な整数文字列ではありません。
  2. 最初の非空白文字が「-」の場合、これは負の値です。それ以外の場合、正の値を想定します。
  3. 最初の文字が「+」の場合、これは正の値です。
  4. 最初の非空白文字および非符号文字がゼロ以外の10進数字の場合、入力は10進形式であり、isdigitを使用して残りの文字をチェックします。
  5. 最初の非空白文字および非符号文字が「0」の場合、入力は8進数形式または16進数形式です。
  6. 最初の非空白文字および非符号文字が「0」で、次の文字が「0」から「7」までの数字である場合、入力は8進形式であり、isodigitを使用します残りの文字を確認します。
  7. 最初の非空白文字および非符号文字が0で、2番目の文字がxまたはXである場合、入力は16進形式であり、isxdigitを使用します残りの文字を確認します。
  8. 残りの文字のいずれかが上記で指定されたチェック機能を満たさない場合、これは有効な整数文字列ではありません。
13
John Bode

まず、どのようになるかを自問してくださいeverこのコードに期待する[〜#〜] not [〜#〜]整数を返します:

int num; 
scanf("%d",&num);

変数を整数型として指定した後、scanfを指定しましたが、整数の場合はonly%d)。

この時点で他に何を含むことができますか?

4
abelenky

上記の全員の入力を確認しました。これは非常に便利で、自分のアプリケーションに適した関数を作成しました。この関数は、実際にはユーザーの入力が「0」ではないことを評価するだけですが、私の目的には十分でした。お役に立てれば!

#include<stdio.h>

int iFunctErrorCheck(int iLowerBound, int iUpperBound){

int iUserInput=0;
while (iUserInput==0){
    scanf("%i", &iUserInput);
    if (iUserInput==0){
        printf("Please enter an integer (%i-%i).\n", iLowerBound, iUpperBound);
        getchar();
    }
    if ((iUserInput!=0) && (iUserInput<iLowerBound || iUserInput>iUpperBound)){
        printf("Please make a valid selection (%i-%i).\n", iLowerBound, iUpperBound);
        iUserInput=0;
    }
}
return iUserInput;
}
0
Nick

これは私が推測するよりユーザーフレンドリーなものです:

#include<stdio.h>

/* This program checks if the entered input is an integer
 * or provides an option for the user to re-enter.
 */

int getint()
{
  int x;
  char c;
  printf("\nEnter an integer (say -1 or 26 or so ): ");
  while( scanf("%d",&x) != 1 )
  {
    c=getchar();

    printf("You have entered ");
    putchar(c);
    printf(" in the input which is not an integer");

    while ( getchar() != '\n' )
     ; //wasting the buffer till the next new line

    printf("\nEnter an integer (say -1 or 26 or so ): ");

  }

return x;
}


int main(void)
{
  int x;
  x=getint();

  printf("Main Function =>\n");
  printf("Integer : %d\n",x);

 return 0;
}
0
sjsam

これを試して...

#include <stdio.h>

int main (void)
{
    float a;
    int q;

    printf("\nInsert number\t");
    scanf("%f",&a);

    q=(int)a;
    ++q;

    if((q - a) != 1)
        printf("\nThe number is not an integer\n\n");
    else
        printf("\nThe number is an integer\n\n");

    return 0;
}
0
OscaRoCa
printf("type a number ");
int converted = scanf("%d", &a);
printf("\n");

if( converted == 0) 
{
    printf("enter integer");
    system("PAUSE \n");
    return 0;
}

scanf()は、一致するフォーマット指定子の数を返します。入力されたテキストが10進整数として解釈できない場合、ゼロを返します。

0
Eduardo

Scanfの手間のかからない取得を使用してこのロジックを開発しました。

void readValidateInput() {

    char str[10] = { '\0' };

    readStdin: fgets(str, 10, stdin);
    //printf("fgets is returning %s\n", str);

    int numerical = 1;
    int i = 0;

    for (i = 0; i < 10; i++) {
        //printf("Digit at str[%d] is %c\n", i, str[i]);
        //printf("numerical = %d\n", numerical);
        if (isdigit(str[i]) == 0) {
            if (str[i] == '\n')break;
            numerical = 0;
            //printf("numerical changed= %d\n", numerical);
            break;
        }
    }
    if (!numerical) {
        printf("This is not a valid number of tasks, you need to enter at least 1 task\n");
        goto readStdin;
    }
    else if (str[i] == '\n') {
        str[i] = '\0';
        numOfTasks = atoi(str);
        //printf("Captured Number of tasks from stdin is %d\n", numOfTasks);
    }
}
0
Shaimaa Yehia