user1431627
user1431627

Reputation: 815

Random guessing game (integer) - bug when entering string

I am making a typical guessing game to learn C for the first time in my life and I noticed a bug. If you enter an integer you will get Guess a higher value or Guess a lower value and that works just fine. But if you put in a string, it goes insane and prints out a lot of strings saying Guess a higher value.

  1. What I am trying to do now is to make a check for if the user enters a string, it will say to the user something like Enter a number, not text. How do I do this?

  2. Is there anything you see that I can improve in this code?

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    int main () {
    
        int secret, answer;
    
        srand((unsigned)time(NULL));
    
        secret = rand() % 10 + 1;
    
        do {
            printf ("Guess a number between 1 and 10");
            scanf ("%d",&answer);
            if (secret<answer) puts ("Guess a higher value");
            else if (secret>answer) puts ("Guess a lower value");
        } while (secret!=answer);
    
        puts ("Congratz!");
        return 0;
    }
    

Upvotes: 2

Views: 374

Answers (4)

jvlync
jvlync

Reputation: 1

You may want to make a function to check if the input is numeric. Like:

int isNumeric( char *str){
   while(*str)
   {
     if (!isdigit(*str))
         return 0;
     str++;
   }
   return 1;
}

int main(){
   char guess[3];
   int iGuess;
   do {
      printf("Guess a number between 1 and 10");
      gets(guess);
      if (!isNumeric(guess)){
        printf("Invalid input");
        continue;
      }
      iGuess = atoi(guess);
     if (iGuess<secret)
           printf("Higher");
     else if (iGuess>secret)
           printf("Lower");
   } while (secret!=iGuess);
   printf("Congrats");
   return 0;
}

You need to include ctype.h and string.h

Upvotes: 0

phoxis
phoxis

Reputation: 61910

Check the return value of scanf . It will return the number of items successfully matched and assigned. In this case if you enter a string then it will not be matched and assigned, but the string stays in the input buffer, and the scanf tries to read it in each iteration and fails, and thus the problem arises.

You may change the code to:

int main () {

    int secret, answer;

    srand((unsigned)time(NULL));

    secret = rand() % 10 + 1;

    do {
        printf ("Guess a number between 1 and 10");
        if (scanf ("%d",&answer) != 1)
        {
         printf ("\nPlease enter an integer\n\n");
         scanf ("%*s");
         continue;
        }
        if (secret<answer) puts ("Guess a higher value");
        else if (secret>answer) puts ("Guess a lower value");
    } while (secret!=answer);

    puts ("Congratz!");
    return 0;
}

Note that inside the if the line scanf ("%*s"); is done. In the %*s the * is the input supression indicator, this tells that a string (stands for %s) will be read but the * tells that although the string will be read from the input, it will be discarded. This is being done to simply discard the previously entered string which is not read by the scanf ("%d",&answer) . In case you do not discard the string in the buffer, it will remain, and each iteration the scanf ("%d",&answer) will fail to match any integer, as it will encounter the leftover string in the input buffer.

On the other hand you may read a string and convert the string to an integer.

Like as below:

int main () {

    int secret, answer;
    char buff[128];

    srand((unsigned)time(NULL));

    secret = rand() % 10 + 1;
    do {
        printf ("Guess a number between 1 and 10");
        scanf ("%s",buff);
        if ((answer = atoi (buff)) == 0)
        {
          printf ("\nPlease enter an integer\n\n");
          continue;
        }
        if (secret<answer) puts ("Guess a higher value");
        else if (secret>answer) puts ("Guess a lower value");
    } while (secret!=answer);

    puts ("Congratz!");
    return 0;
}

atoi () will convert a string to an integer (in 10 base). If the characters which comprises the integer does not contain valid digits, it will return 0. Checking for it we can detect if the user entered correctly. Also because your application needs to enter an integer within 1 and 10 therefore 0 is not included, therefore it is okay to take 0 as an invalid. To get better control on detecting an invalid integer format, and the location of the error in the string use strtol ()

Upvotes: 0

JesperE
JesperE

Reputation: 64414

You are ignoring the return value of scanf, which will tell you if the conversion went well or not. scanf will return the number of items assigned, so if it returns 1 you know that answer was assigned to a number. If it returns 0, you know that something went wrong.

Upvotes: 1

dirkgently
dirkgently

Reputation: 111150

What I am trying to do now is to make a check for if the user enters a string, it will say to the user something like Enter a number, not text. How do I do this?

scanf does formatted input. You may also want to check out advanced formatting specifiers in scanf -- such as ignoring parts of the input, specifying buffer size for reading in strings, specifying only a particular set of characters that you want to read etc. If you want to verify input, you are probably best of reading a line from the console using fgets and then parsing the line.

Is there anything you see that I can improve in this code?

You may want to improve your random number generation algorithm. Read the C FAQ.

Upvotes: 0

Related Questions