In C scanf skips read int value - c

I am trying to creating a console program with menu in c. But I have a problem about validating the option int value. When I put char value it accepts it. I am trying to catch this condition. It understands the condition but scanf is not working second time to read input. It just skips. My code below. Thanks for help!
while (true) {
printf("%s", "Choose one option: ");
while (scanf("%d", &choice) != 0) {
puts("This is not a number! Enter again:");
}
// checking input
while (choice < 1 || choice > 8){
puts("Wrong input! You can choose only 1 - 8!");
printf("%s", "Choose one option: ");
scanf("%d", &choice);
}
if (choice == 8)
break;
(*options[choice])();
}

Related

C for loop, How do I continuously prompt the user?

I am learning about loops such as for and while loops, so I decided to put myself to the test and write a program which you can see the code for below. The program gives the user a range of options to enter an option, but the problem I have is that i want to be able to continuously ask the user to "Enter a command" after an operation has completed.
For example, if I entered 1, the necessary code would be executed but then the whole program just ends. How can I enhance this program so it continuously asks the user to enter new commands until the user forcibly exits by entering 0?
#include <stdio.h>
int main()
{
int n;
int credit = 0;
int YN;
printf("Welcome to Cash booking software Version 2.145\n");
printf("--------------------------------------------------------\n");
printf("Use the following options:\n");
printf("0 -- Exit\n");
printf("1 -- Display Credit\n");
printf("2 -- Change Credit\n");
printf("3 -- Remove Credit\n");
printf("\n");
for ( ; ; )
{
printf("Enter a command: ");
scanf("%d", &n);
if (n == 0)
{
return 0;
}
else if (n == 1)
{
printf("Your credit is £%d", credit);
}
else if (n == 2)
{
printf("Enter a new credit value: \n");
scanf("%d", &credit);
printf("Your new credit value is %d", credit);
}
else if (n == 3)
{
printf("Are you sure you want to remove your Credit value? (Y=1/N=2)");
scanf("%d", &YN);
if (YN == 1)
{
credit = 0;
}
else
;
}
return 0;
}
}
As other users explained return 0; inside of the loop is what is causing the problem and moving it out would solve it, But since you're learning about loops I think this is a great example to teach you something.
Usually you should only use a for loop when you have some parameter that defines de number of times the loop will be executed. The fact that you just used for( ; ; ) is a huge red flag for ther is a betther way to do this.
For example the proper way to write an infinite loop in c is while(1){//code in the loop}. So you could change your for loop with this and it will work fine (relocating return 0; in the correct location).
But since in this code you dont really want an infinite loop (usually they're a bad idea), but you want the loop to run until is pressed 0, the best solution is to use a do{} while(); loop where inside of do you check if either 1, 2 or 3 is pressed and perform their functionality, and then in the while condition you check if 0 has been pressed, and only in that case the program exits.
This is how the code would look like:
do{
printf("Enter a command: ");
scanf("%d", &n);
if (n == 1){
printf("Your credit is £%d\n", credit); // \n added
}
else if (n == 2){
printf("Enter a new credit value: \n");
scanf("%d", &credit);
printf("Your new credit value is %d\n", credit); // \n added
}
else if (n == 3){
printf("Are you sure you want to remove your Credit value? (Y=1/N=2):");
scanf("%d", &YN);
if (YN == 1){
credit = 0;
}
}
} while(n != 0);
return 0;
Also note that I added \n in some printf() commands for better visualization.
use continue statement at the end of each condition , and you can use break statement instead of return 0, so the code will be :
if (n == 0)
{
break;
}
else if (n == 1)
{
printf("Your credit is £%d ", credit);
continue;
}
else if (n == 2)
{
printf("Enter a new credit value: \n");
scanf("%d", &credit);
printf("Your new credit value is %d ", credit);
continue;
}
else if (n == 3)
{
printf("Are you sure you want to remove your Credit value? (Y=1/N=2) : ");
scanf("%d", &YN);
if (YN == 1)
{
credit = 0;
continue;
}
else {
continue;
}

How do I get my code from going into an infinte loop?

I am rewriting the Guessing Game code from 'C Programming for Absoulute Beginners' to verify that the user has entered in a digit, using the isdigit() function.
The rest of the code works, in terms of error checking; but the moment that the user enters in a non-digit, the code goes into an infinite loop.
#include <stdio.h>
#include <stdlib.h>
#define NO 2
#define YES 1
main()
{
int guessGame;
guessGame = 0;
int iRandomNum = 0;
int iResponse = 0;
printf("\n\nWould you like to play \"The Guessing Game\"?\n\n");
printf("\nType '1' for Yes or '2' for No!\n\n");
scanf("%d", &guessGame);
do{
if(guessGame == YES){
iRandomNum = (rand() % 10) + 1;
printf("\nGuess a number between 1 and 10:\n\n ");
scanf("%d", &iResponse);
if(!isdigit(iResponse)){
printf("\nThank you\n");
printf("\nYou entered %d\n", iResponse);
if(iResponse == iRandomNum){
printf("\nYou guessed right\n");
printf("\nThe correct guess is %d!\n", iRandomNum);
printf("\nDo you wish to continue? \n");
printf("\nType '1' for Yes or '2' for No!\n\n");
scanf("%d", &guessGame);
} else {
printf("\n\nSorry, you guessed wrong\n");
printf("\nThe correct guess was %d!\n", iRandomNum);
printf("\n\nDo you wish to continue? \n");
printf("\nType '1' for Yes or '2' for No!\n\n");
scanf("%d", &guessGame);
}
}
else {
printf("\nYou did not enter a digit\n");
printf("\n\nPlease enter a number between 1 and 10:\n\n");
scanf("%d", &iResponse);
}
}
else {
printf("\nThe window will now close. Try again later!\n");
exit(0);
}
}while(guessGame != NO);
}
The code goes into infinite loop as scanf() is unable to read an integer. The character you entered remains in the keyboard buffer.No more reading of integers is possible as long as the character is present in the buffer. scanf() simply returns the number of items read as 0 each time. Hence,the program does not wait for the user to enter data and infinite loop results.
scanf() returns number of items successfully read. So,you can simply check for the return value of scanf(), if its 1 then scanf() has correctly read an integer.
check = scanf("%d", &iResponse);
if(check == 1){
printf("\nThank you\n");
printf("\nYou entered %d\n", iResponse);
and flush the buffer if wrong input is entered
else {
while (getchar() != '\n'); //flush the buffer
printf("\nYou did not enter a digit\n");
printf("\n\nPlease enter a number between 1 and 10:\n\n");
//scanf("%d", &iResponse);
}
no need to ask for input here, while loop will continue and prompt for input in the beginning
Trying taking the input in the form of string .. also u will have to compare the input in the form 'number' :)

How to make a loop which ignores letters in C?

C noob here. Just ignore the title couldn't find a better one :D
void displayMainMenu() {
int choice;
do {
printf("1. Start the game.\n");
printf("2. Recruit troops.\n");
printf("3. Exit.\n");
scanf("%d", &choice);
} while (choice < 1 || choice > 3);
switch (choice) {
case(1) : printf("...");
break;
case(2) : printf("...");
break;
case(3) : printf("...");
exit(0);
break;
}
}
When I enter a a number out of the range it loops perfectly fine, but when I enter a letter or a symbol, it gets to an infinite loop. I want my programs to be perfect even though I am a beginner so I was wondering how can I achieve this? Should I use ASCII or is there a complete different method of doing this kind of thing.
Thanks very much for your help!
scanf("%d", &choice);
scanf("%*[^\n]%*c");//add
Reason why it goes infinite: the scanf rejects a letter for "%d" and nothing's read. Notice that didn't consumes the letter in the input buffer, so the next time scanf is invoked it fails again.
To know more about this, check the return value of scanf: 0 or EOF for nothing read, 1 for 1 item read.
So the solution would be to examine the return value of scanf and break out of the loop.
EDITED:
An example added:
do {
printf("1. Start the game.\n");
printf("2. Recruit troops.\n");
printf("3. Exit.\n");
int item_got = scanf("%d", &choice);
if (item_got != 1)
{
choice = -1; // mark it.
break;
}
} while (choice < 1 || choice > 3);
As scanf() function returns 0 if fails to read formatted input. So if you want to exit when user enter this kind of input then you can write:
if(!scanf("%d", &choice))break;

input validation with float as the correct type

I have to accept an input in the rang -5 to 5. The input is suppose to be of type float. I have tried the different methods suggested on this site but they do not work.
my code
while(1)
{
while(1)
{
printf("Please enter input voltage (-5V to 5V): ");
if((scanf("%f",&e) == 1){
if(e < -5.0 || e > 5.0) /*checks to make sure input is correct*/
{
printf("Please enter another input voltage.");
continue;
}
break;
else
{
printf("please enter new input.");
continue;
}
}
d = (e+5)*(4095)/(10); /*manual calculation for digital encoding*/
printf("The conversion in decimal is: %d\n",d);
printf("The conversion in hex is: %X\n\n",d);
printf("Would you like to continue (y/n)? ");/*prompt to end program*/
scanf("%c",&userInput);
if(userInput == 'y') {continue;}
if(userInput == 'n') {break;}
}
This still causes and infinite loop if say my input is "y".
Since other methods did not work for me am I doing them wrong or is this a special case?
EDIT:
To those asking the whole program is a controlled while(1) loop because at the end another user input is taken to see if the program should end or repeat. Sorry for not mentioning this.
You probably want this:
void main()
{
float e ;
char userInput ;
while(1)
{
while(1)
{
printf("Please enter input voltage (-5V to 5V): ");
if (scanf("%f",&e) == 1)
{
if(e < -5.0 || e > 5.0) /*checks to make sure input is correct*/
{
printf("Please enter another input voltage.\n");
continue;
}
else
break ;
}
}
float d = (e+5)*(4095)/(10); /*manual calculation for digital encoding*/
printf("The conversion in decimal is: %d\n",d);
printf("The conversion in hex is: %X\n\n",d);
printf("Would you like to continue (y/n)? ");/*prompt to end program*/
scanf("\n%c", &userInput);
if(userInput == 'y') {continue;}
if(userInput == 'n') {break;}
}
}
It's not very elegant, I just modified your solution so it exits the loop as soon as you have entered a value between -5 and +5.

C Programming Logic Error?

The following code compiles fine, but does not allow the user to choose whether or not the program is to run again. After giving the user the answer, the program automatically terminates. I placed the main code in a "do while" loop to have the ability to convert more than one time if I wanted too. I have tried to run the program in the command line (Mac and Ubuntu machines) and within XCode with the exact same results. Any assistance would be greatly appreciated.
C Beginner
P.S. Compiling on MacBookPro running Snow Leopard.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char anotherIteration = 'Y';
do
{
const float Centimeter = 2.54f;
float inches = 0.0f;
float result = 0.0f;
// user prompt
printf("\nEnter inches: ");
scanf("%f", &inches);
if (inches < 0) {
printf("\nTry again. Enter a positive number.\n");
break;
} else {
// calculate result
result = inches * Centimeter;
}
printf("%0.2f inches is %0.2f centimeters.\n", inches, result);
// flush input
fflush(stdin);
// user prompt
printf("\nWould you like to run the program again? (Y/N): ");
scanf("%c", &anotherIteration);
if ((anotherIteration != 'Y') || (anotherIteration != 'N'))
{
printf("\nEnter a Y or a N.");
break;
}
} while(toupper(anotherIteration == 'Y'));
printf("Program terminated.\n");
return 0;
}
You probably meant...
} while(toupper(anotherIteration) == 'Y');
since you want to convert the character, and then compare it with 'Y'.
Condition
if ((anotherIteration != 'Y') || (anotherIteration != 'N'))
is always true, so your program will terminate regardless of user input.
Moreover, you put break into virtually every if in your code intended to handle incorrect input. break will terminate the cycle and the program. This is a rather strange logic: ask user to try again and then immediately terminate the program without giving the user opportunity to actually try again. Why are you terminating the program instead of allowing the user to reenter the input?
Well,
while(toupper(anotherIteration == 'Y'));
looks like you meant to say
while(toupper(anotherIteration) == 'Y');
.. but there may be other issues.
This works.
/* convert inches to centimeters */
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char anotherIteration = 'Y';
do
{
const float Centimeter = 2.54f;
float inches = 0.0f;
float result = 0.0f;
// user prompt
printf("\nEnter inches: ");
scanf("%f", &inches);
if (inches < 0)
{
printf("\nTry again. Enter a positive number.\n");
break;
}
else
// calculate result
result = inches * Centimeter;
printf("%0.2f inches is %0.2f centimeters.\n", inches, result);
// flush input
fflush(stdin);
// user prompt
printf("\nWould you like to run the program again? (Y/N): ");
scanf("%c", &anotherIteration);
} while(toupper(anotherIteration) != 'N');
printf("Program terminated.\n");
return 0;
}
You have two big bugs here. The first one is what you have asked for in your
question:
} while(toupper(anotherIteration == 'Y'));
anotherIteration == 'Y' will return either 1 or 0, which both equal 0 after
being passed through toupper.
What you want instead is:
} while(toupper(anotherIteration) == 'Y');
The other bug lies here:
printf("\nWould you like to run the program again? (Y/N): ");
scanf("%c", &anotherIteration);
if ((anotherIteration != 'Y') || (anotherIteration != 'N'))
{
printf("\nEnter a Y or a N.");
break; // This breaks out of hte main program loop!
}
What you really want to do is ask the user again if they enter something wrong,
like this:
do
{
printf("\nWould you like to run the program again? (Y/N): ");
scanf("%c", &anotherIteration);
if ((anotherIteration != 'Y') && (anotherIteration != 'N'))
printf("\nEnter a Y or a N.");
} while ((anotherIteration != 'Y') && (anotherIteration != 'N'));
You have a few bugs, but since you're learning, you should probably figure them out. The answer to your specific question on this program is that you probably want to be using fpurge() for stdin, not fflush().
One error:
while(toupper(anotherIteration == 'Y'))
should be
while(toupper(anotherIteration) == 'Y')

Resources