webentwicklung-frage-antwort-db.com.de

Wie kann ich nur ganze Zahlen scannen und das Lesen wiederholen, wenn der Benutzer nicht numerische Zeichen eingibt?

Hier ist ein kleines Problem des jungen Tyros mit C-Code, der lediglich versucht, den Benutzer daran zu hindern, ein Zeichen oder eine Ganzzahl kleiner als 0 oder mehr als 23 einzugeben.

#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;  
}

Ich habe es auf halbem Weg geschafft und ein kleines Push-Up wird geschätzt. 

13
7kemZmani

Verwenden Sie scanf("%d",&rows) anstelle von scanf("%s",input)

Dadurch können Sie direkt den Integer-Wert von stdin erhalten, ohne in int konvertieren zu müssen.

Wenn der Benutzer eine Zeichenfolge mit nicht numerischen Zeichen eingibt, müssen Sie Ihren Standardeintrag vor der nächsten scanf("%d",&rows) bereinigen.

ihr Code könnte so aussehen:

#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;  
}

Erklärung

1)

scanf("%d%c", &rows, &c)

Dies bedeutet, dass vom Benutzer eine Ganzzahl und in der Nähe ein nicht-numerisches Zeichen erwartet wird.

Beispiel1:Wenn der Benutzer aaddk und dann ENTER eingibt, gibt der scanf 0 zurück. Nichts erfasst

Example2:Wenn der Benutzer 45 und dann ENTER eingibt, gibt der scanf 2 zurück (2 Elemente werden erfasst). Hier erfasst %d45 und %c\n

Example3:Wenn der Benutzer 45aaadd und dann ENTER eingibt, gibt der scanf 2 zurück (2 Elemente werden erfasst). Hier erfasst %d45 und %ca

2)

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

Im Beispiel1:Diese Bedingung ist TRUE, da scanf 0 (!=2) zurückgibt.

Im Beispiel2:Diese Bedingung ist FALSE, da scanf 2 und c == '\n' zurückgibt.

Im Beispiel3:Diese Bedingung ist TRUE, da scanf 2 und c == 'a' (!='\n') zurückgibt.

3)

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

clean_stdin() ist immer TRUE, da die Funktion immer 1 zurückgibt.

Im Beispiel1:Der (scanf("%d%c", &rows, &c)!=2 || c!='\n') ist TRUE, also sollte die Bedingung nach dem && überprüft werden, so dass die clean_stdin() ausgeführt wird und die gesamte Bedingung TRUE ist.

Im Beispiel2:Der (scanf("%d%c", &rows, &c)!=2 || c!='\n') ist FALSE, so dass die Bedingung nach dem && nicht geprüft wird (da das Ergebnis immer die gesamte Bedingung FALSE ist), so dass die clean_stdin() nicht ausgeführt wird und die gesamte Bedingung ist FALSE

Im Beispiel3:Der (scanf("%d%c", &rows, &c)!=2 || c!='\n') ist TRUE, also sollte die Bedingung nach dem && überprüft werden, so dass die clean_stdin() ausgeführt wird und die gesamte Bedingung TRUE ist.

Sie können also feststellen, dass clean_stdin() nur ausgeführt wird, wenn der Benutzer eine Zeichenfolge mit nicht numerischen Zeichen eingibt.

Und diese Bedingung ((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin()) gibt FALSE nur zurück, wenn der Benutzer eine integer und nichts anderes eingibt

Wenn die Bedingung ((scanf("%d%c", &rows, &c)!=2 || c!='\n') && clean_stdin())FALSE ist und die integer zwischen und 1 und 23 liegt, bricht die while-Schleife, andernfalls wird die while-Schleife fortgesetzt

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;
}

%[^0-9] in scanf() verschlingt alles, was nicht zwischen 0 und 9 liegt. Im Allgemeinen wird der Eingabestrom von Nicht-Ziffern gesäubert und in str eingefügt. Nun, die Länge einer nicht-Ziffernfolge ist auf 100 begrenzt. Der folgende %d wählt nur ganze Zahlen im Eingabestrom aus und platziert sie in num.

2
Swathyprabhu

Sie können eine Funktion erstellen, die eine ganze Zahl zwischen 1 und 23 liest oder 0 zurückgibt, wenn nicht int

z.B.

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

Sie müssen Ihren Aufruf an strtol in Ihren Schleifen wiederholen, in dem Sie den Benutzer dazu auffordern, es erneut zu versuchen. In der Tat, wenn Sie die Schleife als do { ... } while(...); statt als while machen, erhalten Sie nicht dieselbe Art von zweimaligen Dingen. 

Sie sollten Ihren Code auch so formatieren, dass Sie sehen können, wo sich der Code in einer Schleife befindet und nicht. 

0
Mats Petersson

MOHAMED, Ihre Antwort ist großartig und hat mir wirklich geholfen. Hier habe ich einen Code gepostet, der meiner Meinung nach etwas einfacher ist:

#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;
}

In meinem Fall möchte ich, dass die Zahl nur positiv ist. Wenn Sie möchten, dass Ihre Nummer zwischen 1 und 23 liegt, ersetzen Sie number<0 durch number<1 || number>23 in der Anweisung if . Sie müssen auch die Variable printf ändern, um eine entsprechende Nachricht zu drucken. 

0
Elefther
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

Wenn die Eingabe eine Zahl ist, können Sie foo als Eingabe verwenden.

0
Yonggoo Noh