0

I have two sets of similar Do While codes files, one with stdin scanf function and the other getInt() from cs50 lib. Both files compile in CS50 appliance. I expect the do while works the same but different results outcome.

It suppose to loop if input value greater than 23 but it exit after input of any integer values and prompt "retry" for non integer value.

I wrote another similar code without GetInt() function in CS50 library instead scanf functions to get input for do while loop and it loop when input value greater than 24 and non-integer input show zero '0'. Why this happen? I cannot complete this PSET1 problem if required to used CS50 lib.

#include <cs50.h>
#include <stdio.h>

int main(void)
{
// Prompt user for keyboard input
// Input type checking done by CS50 lib
// Loop if input value greater than 23
// Default max height
int myHeight = 0;
do 
{
printf("Enter the height of half-pyramid: ");
int myHeight = GetInt();  
printf("You have entered %d\n",myHeight);
} 
while (myHeight>23);
}

#include <stdio.h>
#int main(void)
{
// Prompt user for keyboard input
// 
// Loop if input value greater than 23
// Default max height
int myHeight = 0;
do 
{
 printf("Enter the height of half-pyramid: ");
 scanf("%d",&myHeight);
 printf("You have entered %d\n",myHeight);
} 
while (myHeight>23);
}
0

That is because GetInt() and scanf() are two differnt functions that have different behaviors.

GetInt():

/**
 * Reads a line of text from standard input and returns it as an
 * int in the range of [-2^31 + 1, 2^31 - 2], if possible; if text
 * does not represent such an int, user is prompted to retry.  Leading
 * and trailing whitespace is ignored.  For simplicity, overflow is not
 * detected.  If line can't be read, returns INT_MAX.
 */

GetInt(), only returns when succesfully reads an integer.

scanf():

If successful, the total number of characters written is returned, otherwise a negative number is returned.

When you specify scanf("%d",&myHeight); if you don't type an intger scanf() will hot change the value in myHeight and since you intialized to zero that is the value that still haves.

1
  • Piggybacking off your answer, scanf will return the number of successfully matched items so OP should check the return value. Also, using scanf in a loop is a BAD idea as it leaves stuff in the input buffer causing an infinite loop. Better to use fgets() and sscanf()
    – chad
    Aug 25 '15 at 20:45
0
  1. Negative integers should be rejected as well, not only integers that are > 23.

  2. Make sure you're not outputting anything more than required before you submit your solution.

scanf vs. GetInt

what's interesting about GetInt is that it validates the input for you, a thing which scanf doesn't do by default. In order to use scanf, you have to understand how it works first.

First, per the man page of scanf, it returns the number of items matched. In case a matching failure occurs (the user doesn't provide an int value in this case), it returns 0 leaving what the user has inputted into the buffer of the standard in.

At this point, you can't just call scanf and ask it to read an int value because it will read from where it left off and a matching failure will occur again.

In order to get over that you need to empty the buffer first. You can do that maybe using

char c;
do
{
    c = getchar();
}
while (!isdigit(c));

ungetc(c, stdin);

the code above basically reads everything in the buffer and ignores it until it hits a digit, which scanf is looking for in this example which it puts back into the buffer for the next call to scanf to read. This won't defend against values like 150abc though. So you'll need to handle that too.

GetInt does all of that for you. It basically uses GetString from the same library to read what the user has inputted, then uses a function from the scanf family, namely sscanf, to read the integer out of that string making sure this number is not preceded/followed by non-numeric characters.

0

scanf() just reads from stdin. It has no retry functionality built in. However, from the scanf() man page:

These functions return the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure.

So you could check the return value of scanf() to make sure it read one and only one int.

However:

scanf() will ONLY consume input that matches your format string so if you feed it a non-int and base your loop of of scanf()'s return value, you will get an infinite loop because that non-int will stay in stdin.

Instead, you should use fgets() to get the text from stdin and sscanf() to parse it. Make sure you check the return values for both!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .