web-dev-qa-db-ja.com

ユーザーが数字以外の文字を入力した場合に整数のみをスキャンして読み取りを繰り返す方法

ここに、ユーザーが文字または0未満または23を超える整数を入力できないようにするCコードに関する小さな若いtyroの問題があります。

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

int main(void)
{
    const char *input;
    char *iPtr;
    int count = 0;
    int rows;

    printf("Enter an integer: ");
    scanf("%s", input);
    rows = strtol(input, &iPtr, 0);
    while( *iPtr != '\0') // Check if any character has been inserted
    {
        printf("Enter an integer between 1 and 23: ");
        scanf("%s", input);
    }
    while(0 < rows && rows < 24) // check if the user input is within the boundaries
    {
        printf("Select an integer from 1 to 23: ");
        scanf("%s", input);
    }  
    while (count != rows)  
    {  
        /* Do some stuff */  
    }  
    return 0;  
}

私は途中でそれを作ったし、小さなプッシュアップは高く評価されます。

13
7kemZmani

scanf("%d",&rows)の代わりにscanf("%s",input)を使用します

これにより、intに変換する必要なく、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)

これは、ユーザー入力から整数とそれに近い非数字文字を期待することを意味します。

Example1:ユーザーがaaddkを入力してからENTERを入力すると、scanfは0を返します。キャプションなし

Example2:ユーザーが45を入力してからENTERを入力すると、scanfは2を返します(2要素がキャッピングされます) )。ここで%d45をキャッピングし、%c\nをキャッピングしています

Example3:ユーザーが45aaaddを入力してからENTERを入力すると、scanfは2を返します(2つの要素がキャッピングされます) )。ここで%d45をキャッピングし、%caをキャッピングしています

2)

(scanf("%d%c", &rows, &c)!=2 || c!='\n')

example1:では、 scanfは0!=2)を返すため、この条件はTRUEです

example2:では、scanfは2およびc == '\n'を返すため、この条件はFALSEです。

example3:では、scanfは2およびc == 'a' (!='\n')を返すため、この条件はTRUEです。

3)

((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())

関数は常に1を返すため、clean_stdin()は常にTRUEです。

example1:では、(scanf("%d%c", &rows, &c)!=2 || c!='\n')TRUEなので、&&の後の条件をチェックして、clean_stdin()が実行され、条件全体はTRUEです

example2の場合:(scanf("%d%c", &rows, &c)!=2 || c!='\n')FALSEなので、&&の後の条件はチェックされませんその結果は、条件全体がFALSEになるため、clean_stdin()は実行されず、条件全体はFALSEです。

example3で:(scanf("%d%c", &rows, &c)!=2 || c!='\n')TRUEなので、&&の後の条件をチェックして、clean_stdin()が実行され、条件全体はTRUEです

したがって、ユーザーが数字以外の文字を含む文字列を入力した場合にのみclean_stdin()が実行されることに注意してください。

そして、この条件((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())は、ユーザーがFALSEを入力した場合にのみintegerを返します。

そして、条件((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())FALSEであり、integerがbetweenであり、123である場合、whileループは中断し、そうでない場合はwhileループが継続します

33
MOHAMED
_#include <stdio.h>
main()
{
    char str[100];
    int num;
    while(1) {
        printf("Enter a number: ");
        scanf("%[^0-9]%d",str,&num);
        printf("You entered the number %d\n",num);
    }
    return 0;
}
_

scanf()の_%[^0-9]_は、_0_と_9_の間にないものをすべて使い果たします。基本的には、数字以外の入力ストリームを消去し、strに入れます。さて、非数字シーケンスの長さは100に制限されています。次の_%d_は、入力ストリーム内の整数のみを選択し、numに配置します。

2
Swathyprabhu

1から23の間の整数を読み取る関数、または非整数の場合は0を返す関数を作成できます。

例えば.

int getInt()
{
  int n = 0;
  char buffer[128];
  fgets(buffer,sizeof(buffer),stdin);
  n = atoi(buffer); 
  return ( n > 23 || n < 1 ) ? 0 : n;
}
1
Anders
char check1[10], check2[10];
int foo;

do{
  printf(">> ");
  scanf(" %s", check1);
  foo = strtol(check1, NULL, 10); // convert the string to decimal number
  sprintf(check2, "%d", foo); // re-convert "foo" to string for comparison
} while (!(strcmp(check1, check2) == 0 && 0 < foo && foo < 24)); // repeat if the input is not number

入力が数値の場合、fooを入力として使用できます。

1
Yonggoo Noh

ループ内でstrtolへの呼び出しを繰り返して、ユーザーに再試行を要求する必要があります。実際、whileの代わりにループをdo { ... } while(...);にすると、同じ種類の繰り返しが2回繰り返されることはありません。

また、コードがループ内ではなくどこにあるかを確認できるようにコードをフォーマットする必要があります。

0
Mats Petersson

MOHAMED、あなたの答えは素晴らしく、本当に助けになりました。ここにコードを投稿しましたが、それはもう少し簡単だと思います:

#include <stdio.h>

int getPositive(void);
void clean_input(void);

int main(void) {
     printf("%d\n",getPositive());

     return 0;
}



int getPositive(void) {
    int number;
    char buffer;  // Holds last character from user input. 
                  // (i.e '\n' or any other character besides numbers)
    int flag;     // Holds scanf return value

    do{ 
        flag = scanf("%d%c", &number, &buffer); // Gets input from user

        // While scanf did not read 2 objects (i.e 1 int & 1 char)
        // or the user inputed a number and then a character (eg. 12te)
        // ask user to type a valid value

        while (flag !=2 || buffer!='\n') {

            clean_input();
            printf("%s","You have typed non numeric characters.\n"
                    "Please type an integer\n?");
            flag = scanf("%d%c", &number, &buffer);
        }

        if(number<0) {
            printf("%s","You have typed a non positive integer\n"
                    "Please type a positive integer\n?");

        } else {     // If user typed a non negative value, exit do-while.
              break;
        }

    }while(1);
}

void clean_input(void) {
    while (getchar()!='\n');
    return;
}

私の場合、数字を正にしたいだけです。番号を1〜23にするには、ifステートメントでnumber<0number<1 || number>23に置き換えます。また、適切なメッセージを出力するには、printfを変更する必要があります。

0
Elefther