While loop to validate input is a number in C? [duplicate] - c

This question already has an answer here:
Why inside a loop, scanf() with %d does not wait for the user input in case it received an invalid input previously?
(1 answer)
Closed 5 years ago.
So today I am trying to find a way to check if this input is a number. I cant find a way to make this code work so far. If I enter a number, the while loops ends, which is my intention. But, if I enter anything else, the code SHOULD print the printf once and then reprompt me for input (via the scanf statement back at the top of loop). But it instead prints the printf statement infinitely. How can I fix this?
float num1;
while (scanf("%f",&num1)==0)
{
printf("Invalid input. Please enter a number: ");
}

If scanf fails to preform the requested conversion, it will leave the input stream unchanged. So while your check is correct, you need to clean the input stream of the erroneous input before re-attempting to read a number again.
You can do it with scanf itself and and the input suppression modifier:
float num1;
while (scanf("%f",&num1)==0)
{
printf("Invalid input. Please enter a number: ");
scanf("%*s");
}
%*s will instruct scanf to parse the input as though it's attempting to convert a string of characters (removing characters in the process from the stream), but thanks to the asterisk, it won't attempt to write it anywhere.

Related

while loop code not working (keepgoing='y') [duplicate]

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 3 years ago.
So I'm learning how to use the while and for loops in C but this code won't seem to work. the scanf statement seems to be getting ignored and the loop just repeats itself without requiring me to input 'Y' for it to repeat. Here's the code:
void showCommission();
void main() {
char keepGoing='y';
while(keepGoing=='y') {
showCommission();
printf("Do you want to calculate another?\n");
scanf("%c",&keepGoing);
}
}
void showCommission() {
float sales,commission;
const float COM_RATE=0.10;
printf("Enter the amount of sales\n");
scanf("%f",&sales);
commission=sales*COM_RATE;
printf("The commission is $%f.\n",commission);
}
Here's what running the code gives me:
Enter the amount of sales
5000
The commission is $500.000000.
Do you want to calclulate another?
...Program finished with exit code 10
Press ENTER to exit console.
it never prompts me to enter y and the code just exits for some reason.
The problem you're encountering is that the call to scanf to read in a value using the %c format will accept a newline character as valid input!
This, combined with the fact that the scanf("%f",&sales); call reads in a float value but does not 'consume' the following newline, will leave that newline character in the input buffer, for the subsequent call to read a value for keepGoing. Thus, you will have a value for keepGoing that is not y and the program will terminate.
There are several ways around this. The simplest, perhaps, is to add a space character before the %c field, which will instruct the scanf function to skip all 'whitespace' characters (which includes the newline) when 'scanning' for the input character:
scanf(" %c", &keepGoing); // Added space before %c will skip any 'leftover' newline!
You've got a few problems. First, you need to check your scanf return values; if stdin is closed without providing y, scanf will constantly return -1 without rewriting keepGoing (making the loop infinite).
The other problem is early exit; %c suppresses the normal scanf whitespace skipping behavior, so your scanf's in main are always trying to read whatever followed the float you just parsed to populate sales (usually whitespace or a newline of some sort), so when you enter:
1.12
y
the %c reads the newline after the 2, not the y, and the loop exits immediately.
A simple fix would be to change:
scanf("%c",&keepGoing);
to:
if (scanf(" %c", &keepGoing) != 1) break;
The leading space will reenable whitespace skipping so it consumes all whitespace before it tries to read the next character, and whenever it fails to read a character at all, it will end the loop, rather than running forever. A similar check should probably be added for your other scanf.
This is due to the newline (enter keystroke) leftover from non-chars input.
scanf("%f",&sales);
For example, if i enter 500 for the amount of sales, the program will read 500\n, where the \n is your enter keystroke. However, scanf("%f",&sales) will only read float value. Therefore the \n is leftover in your input buffer. Then, when the program try to run scanf("%c",&keepGoing), it consume the leftover \n and it will treat as you pressed enter keystroke and skipped the input.
The issue can be fixed by consuming the leftover \n.
void showCommission() {
float sales,commission;
char consumeNewLine;
const float COM_RATE=0.10;
printf("Enter the amount of sales\n");
scanf("%f",&sales);
scanf("%c",&consumeNewLine);
commission=sales*COM_RATE;
printf("The commission is $%f.\n",commission);
}

While loop never stops when I enter a character in a place [duplicate]

This question already has answers here:
Why is scanf() causing infinite loop in this code?
(16 answers)
Closed 5 years ago.
I have a problem with this loop when I enter a character for ˋscanfˋ. The loop will never stop. But when I enter a number all works good.
This Is The Code:
#include <stdio.h>
#include <stdlib.h>
int main() {
int x;
printf("Enter 1 Or 2\n");
scanf("%i",&x);
while (x!=1 && x!=2) {
printf("Please Enter A Right Value \n");
scanf("%i",&x);
}
printf("Finish");
}
Well when you input character, scanf actually tries to get those wrong character inputs from the stdin but as it is not as per the conversion specification provided it fails. And then it keeps those wrong input in the stdin. And next time the scanf fails again due to those wrong inputs. So you need to clear it before you attempt to get the input again using scanf. Also check the return value of scanf and in case it failed clear the stdin.
The provided code checks for EOF and also return value of scanf the standard says explicitly about the return value of scanf :-
7.21.6.2p16
The fscanf function returns the value of the macro EOF if an
input failure occurs before the first conversion (if any) has
completed. Otherwise, the function returns the number of input
items assigned, which can be fewer than provided for, or even
zero, in the event of an early matching failure.
The code will be something like this. (This is using scanf).
Better even use fgets. you can easily and more better way control the erro neous inputs. With fgets you will read the entire line and then parse the integer input from it using strtol or strtoul. Yes in case of integer input there will be a case there also - you need to check if the parsed long or unsigned long is of proper size so that they can be kept in int variable.

How do I fix scanf? (FailSafes) [duplicate]

This question already has answers here:
Why does scanf appear to skip input?
(7 answers)
Closed 8 years ago.
Here i have a simplified piece of code that asks and displays a number on a loop, it works fine for all numbers i type in, But if i input a letter or a special character (!"£$%^&*-_=+ etc ) it goes mental and skips the input.
#include<stdio.h>
int number;
int main()
{
do
{
system("cls");
printf("Enter a number");
scanf("%d",&number);
}
while(1==1);
}
My question is, what can i do to stop this from happening?, is there some code that filters out this nonsense or is scanf pretty much worthless?
//Edit: This is somehow been marked as a duplicate, heh.
From here:
if the input doesn't conform to the expected format scanf() can be
impossible to recover sensibly [..] A "better" alternative here is to
use an input function like fgets() or fgetc() to read chunks of input,
then scan it with sscanf() or parse it with string handling functions
like strchr() and strtol().
scanf with %d will fail to scan an integer and returns 0 when a character was entered. So just check if it doesn't return 1. If it doesn't , a character was entered (if it returned 0) or else, an integer was entered. Note that if EOF was encountered, scanf will return -1.
if(scanf("%d", &number) != 1)//character entered
{
printf("Invalid input\n");
scanf("%*s");//clear the invalid character(s) from stdin
}
else
{
//a number was entered
}
The reason that scanf becomes "mental" and the program prints Enter a number many times when you enter a character is that when the scanf fails to scan an integer from the standard input stream(stdin), it returns 0 and the execution continues. When scanf is called the next time, it sees the characters which you had entered the last time and again fails and this process continues. To prevent it, just clear the stdin like I've done in the code above.
Another popular way of clearing the stdin is using:
int c;
while((c = getchar()) != '\n' && c != EOF);

C Skipped Operation [duplicate]

This question already has an answer here:
Does scanf() take '\n' as input leftover from previous scanf()?
(1 answer)
Closed 9 years ago.
Im trying to make a basic C console application calculator. Yet when i execute it the second scanf command is skipped and the third is run instead. This is a problem as here i need to get operation of the user +, -, *, or /. How do i stop this from happening?
float num1;
char sign;
float num2;
float total;
printf("~~~ Calculator ~~~\n");
printf("Please enter the first number: ");
scanf("%f", &num1);//Get value of num1 from user
printf("\nNow please enter the operation , either +, -, *, or / : ");
scanf("%c", &sign);//Get value of sign from user
printf("\n\nFinaly enter the second number: ");
scanf("%f", &num2);
Edit: Actually after trying various suggestions it seams a space before the %c was the correct way and cleanest way of fixing things. Thanks for the help.
Put a blank character before %c so it will consume the new line character like this:
scanf(" %c", &sign);//Get value of sign from user
After you hit enter, the first scanf consumes the actual number and leaves the \n. The latter is consumed in the next scanf.
scanf("%f\n", &order)
Do that in order to consume the \n you are entering.
As #JonathanLeffler mentioned, it's better approach to use " %c" (Note the space) in the next line in order to consume the newline character.
After the program asking for the first number you enter a number the you hit return. So the the number is stored in the variable num1. But the new line character '\n' still in the buffer you need to clear the buffer before the second scanf is executed Otherwise the signe variable will accept that '\n' as an input because it's a character and it will not prompt for an input.
You should always clear the buffer before asking to input a char
int c;
do {
c = getchar(); // clearing the buffer
} while (c!='\n' && c!=EOF);
printf("\nNow please enter the operation , either +, -, *, or / : ");
scanf("%c", &sign);//Get value of sign from user
Now it shouold work
Actually, this happens because there is still a value in the stdin stream of the program.
An easy solution would be using:
fix: DON'T USE -> fflush(stdin);
Consume the newline char by using scanf("%f\n")...
before the second call to scanf...
Best!

Unable to execute a do-while loop completely [duplicate]

This question already has answers here:
Yes/No loop in C
(3 answers)
Closed 8 years ago.
I am trying to execute a small program using do-while.
#include<stdio.h>
#include<conio.h>
void main()
{
char another;
int num;
do
{
printf("Enter a number");
scanf("%d",&num);
printf("Square of %d id %d",num,num*num);
printf("Want to another another number y/n");
scanf("%c",&another);
}while(another=='y');
}
Now when I try to execute the program, it runs fine. I input a number and it displays its square. And then I see Want to enter another number y/n. But as soon as I press any key (y or n), the program exits itself before I can press enter to provide the input. I tried it many times but no success.
But the program runs fine if I ask the user to input either 1 or 2(in place of y/n). In that case it takes an integer input and can check the while block. If another == 1, the program runs again.
My problem is that why can't I check for a character in the while condition.
The reason it doesn't work is that after scanf gets num, the new line is still in the buffer, so it will be processed by the next scanf with %c format specifier. A direct way of fixing it is to use:
scanf(" %c", &another);
// ^space
Note that your original scanf("%c:,&another); won't compile, but I assume that's a typo. And always use int main, or it's undefined behavior.

Resources