When I enter a non-integer value it cause an infinite loop. Do I need to replace scanf? If so how can I do that.
int num=1;
if(num==1){
int slct;
printf("\n\tWelcome");
printf("\n1. Login\n2. Register\n3. Account\n4. Exit\n");
SELECTION: ;
printf("\n\tEnter a number:");
scanf("%d",&slct);
if (slct == 1){}
else if (slct == 2){}
else if (slct == 3){}
else if (slct == 4){
return 0;
} else {
goto SELECTION;
}
}
You need to check the return value of scanf and flush the input:
#include <stdbool.h>
#include <stdio.h>
int main()
{
bool done = false;
while (!done) {
printf("\n\tWelcome\n");
printf("1. Login\n");
printf("2. Register\n");
printf("3. Account\n");
printf("4. Exit\n\n");
printf("Enter a number:");
int selection;
int result = scanf("%d", &selection);
if (EOF == result) {
done = true;
}
else if (1 != result) {
printf("You did not enter a valid number\n");
int c;
while ((c = getchar()) != '\n' && c != EOF) {}
done = (c == EOF);
}
else if (1 == selection) {
printf("You chose login\n");
}
else if (2 == selection) {
printf("You chose register\n");
}
else if (3 == selection) {
printf("You chose account\n");
}
else if (4 == selection) {
done = true;
}
else {
printf("Please pick a number between 1 and 4\n");
}
}
}
The format string in scanf("%d",&slct); is %d which means you want to read a number.
When you enter something else than a number, scanf returns 0 to indicate that zero numbers were read.
If the scanf encounters and end-of-file when attempting to read the input (enter control-D) then it returns the special value EOF.
Also, scanf does not consume the incorrect input, so you need to explicitly flush it.
Related
I need the code below to recognize if the grades entered is below 1 or greater than 100. If it is not within the parameters, I want to let the user know and allow them to enter another grade without exiting the program or losing grades they have already entered. I don't want the program to quit until the user enters q and I want to ensure all of the valid grades entered print at that time. I have tried numerous methods and am not getting the right results. I think I probably need some other else if statement, but I haven't been able to find the right one to work. Any information you can share to get me on the right track would be greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char choice;
int gradeArray[100];
int grades;
int gCount=0,i;
for(gCount=0; gCount<100; gCount++)
{
//for loop to read the grades till array size
printf("******Enter Choice Selection in Parenthesis******\n Add grades(a)\n Quit(q) \n");
scanf("%c",&choice);
if(choice == 'a' || 'A')
{
//if user choice is a, then read the grade
printf( "Enter grade: ");
scanf("%d", &grades);
getchar();
gradeArray[gCount] = grades; //add the grade to array
}
if(choice == 'q') //if the user choice is q, then exit the loop
{
break;
}
}
printf("Grades are:\n");
for(i=0; i<gCount; i++)
{
printf(" %d%%\n", gradeArray[i]); //print grades
}
return 0;
}
You can do a while loop to verify the user input. With a while you'll be able to force the user to enter the right grade.
if(choice == 'A' || choice == 'a'){
printf("Enter grade:");
scanf("%d", &grades);
getchar();
while(grade < 1 || grade > 100){
printf("You entered a wrong number\n");
printf("Enter a grade between 1 and 100: ");
scanf("%d", &grades);
getchar();
}
gradeArray[gCount] = grades;
}
your solution is almost aligned with what you had in mind. Here is how you can do it differently.
#include <stdio.h>
int main()
{
char choice;
int arraySize = 100; //change this to any number you wish
int gradeScore = 0;
int gradeArray[arraySize];
int gCount = 0;
int showCount = 0;
while(choice != 'q')
{
//to ask for user's input every time
printf("What do you want to do? Enter\n");
printf("'a' to add grades\n");
printf("'q' to quit\n");
scanf(" %c", &choice); //space is entered to ensure the compiler does not read whitespaces
//your implementation should check for user input before proceeding
if(choice != 'a')
{
//in this condition, 'q' is technically an incorrect input but your design states that 'q' is for quitting
//thus, do not alert the user here if 'q' is entered
if(choice != 'q')
{
//a condition to warn the user for incorrect input
printf("Incorrect input. Please enter only 'a' or 'q'\n");
}
}
else if(choice == 'a')
{
printf("Enter grade: \n");
scanf(" %d", &gradeScore);
//to check for user input if the grades entered are less than 1 or more than 100
if(gradeScore < 1 || gradeScore >100)
{
//print a warning message
printf("The grade you entered is invalid. Please enter a grade from 1 - 100\n");
}
//for all correct inputs, store them in an array
else
{
printf("Grade entered\n");
gradeArray[gCount] = gradeScore;
gCount++;
}
}
}
//prints grade when 'q' is entered
if(choice == 'q')
{
printf("Grades are: \n");
for(showCount = 0; showCount < gCount ; showCount++)
{
printf("%d\n", gradeArray[showCount]);
}
}
}
To sum up the important parts, be sure to check for the user grade input to be in range of 1 - 100. Store the grade in the array if it is within range and be sure to increase the array counter, otherwise it will always store it in gradeArray[0] for the subsequent grades. Hope this helps
Use a do-while loop to keep the program looping back to get another choice unless a valid choice has been entered. Use fgetc to read a single character - fewer problems. Only print grades if at least one grade has been entered.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char choice;
int gradeArray[100];
int grades;
int gCount=0,i;
for(gCount=0; gCount<100; gCount++)
{
//for loop to read the grades till array size
printf("******Enter Choice Selection******\n Add grades(a)\n Quit(q) \n");
do
{
choice = fgetc(stdin);
if(choice == 'a' || choice == 'A')
{
//if user choice is a, then read the grade
printf( "Enter grade: ");
scanf("%d", &grades);
getchar();
gradeArray[gCount] = grades; //add the grade to array
}
else if(choice != 'q')
printf("Invalid choice - try again\n");
} while (choice != 'a' && choice != 'A' && choice != 'q');
if(choice == 'q') //if the user choice is q, then exit the loop
break;
}
if(gCount > 0)
{
printf("Grades are:\n");
for(i=0; i<gCount; i++)
printf(" %d%%\n", gradeArray[i]); //print grades
}
return 0;
}
The current problem is with the Evaluate another interval (Y/N)? prompt. Let's say I run the program 4 times; in order to end it, it requires me to type N 4 times.
int main() {
int trap, test;
double low, hi;
char repeat, c;
//Gather End Points
do {
printf("Enter endpoints of interval to be integrated (low hi): ");
test = scanf("%lf %lf", &low, &hi);
if (test != 2) {
printf("Error: Improperly formatted input\n");
while((c = getchar()) != '\n' && c != EOF); //Discard extra characters
} else
if (low > hi)
printf("Error: low must be < hi\n");
} while ((test != 2 || low > hi));
//Gather amount of triangles
do {
printf("Enter number of trapezoids to be used: ");
test = scanf("%d", &trap);
if (test != 1) {
printf("Error: Improperly formated input\n");
while((c = getchar()) != '\n' && c != EOF); //Discard extra characters
} else
if (trap < 1)
printf("Error: numT must be >= 1\n");
} while ((trap < 1 || test != 1));
//Output integrate
printf("Using %d trapezoids, integral between %lf and %lf is %lf",
trap, low, hi, integrate(low, hi, trap));
//Prompt user for another time
while (1) {
printf("\nEvaluate another interval (Y/N)? ");
scanf(" %c", &repeat);
switch (repeat) {
case 'Y':
main();
case 'y':
main();
case 'N':
return 0;
case 'n':
return 0;
default:
printf("Error: must enter Y or N");
}
}
return 0;
}
I expect it so that no matter what run of the program I'm on it will close when I type one N.
There are many ways to achieve what you want but calling main recursively is not a good idea.
A pretty simple way to change your program is to add an additional while(1) level. Something like:
int main(void)
{
char repeat;
while(1){ // Outer while to keep the program running
printf("running program\n");
// Put your program here
printf("program done\n");
repeat = '?';
while(repeat != 'y' && repeat != 'Y'){ // Repeat until input is 'Y' or 'y'
printf("\nEvaluate another interval (Y/N)? ");
scanf(" %c", &repeat);
switch (repeat){
case 'Y':
case 'y':
break;
case 'N':
case 'n':
return 0; // Stop if input is 'n' or 'N'
default:
printf("Error: must enter Y or N");
}
}
}
return 0; // This will never be reached
}
Another way (a simpler way, IMO) is to put the code where you ask the user into a function that you call from main. Like:
int continueProg()
{
char repeat = '?';
while(1){
printf("\nEvaluate another interval (Y/N)? ");
scanf(" %c", &repeat);
switch (repeat){
case 'Y':
case 'y':
return 1;;
case 'N':
case 'n':
return 0;
default:
printf("Error: must enter Y or N");
}
}
}
int main(void)
{
do {
printf("running program\n");
// Put your program here
printf("program done\n");
} while(continueProg());
return 0;
}
BTW: Take a look at getchar instead of using scanf
There are multiple problems in your program:
You test the return value of scanf() when reading the user's answer to the prompts, and you clear the pending input correctly, but you do not handle the potential end of file, leading to endless loops.
c must be defined as int to accommodate for all values returned by getchar(): 256 values of type unsigned char and the special value EOF.
You can main() recursively to repeat the program's action requiring multiple N answers. You should instead add an outer loop and exit from it upon a N answer or an end of file condition.
Here is a modified version:
#include <stdio.h>
double integrate(double low, double hi, int trap) {
...
}
int flush_line(void) {
// Consume the pending input and return `'\n`` or `EOF`
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
return c;
}
int main() {
// Main program loop
for (;;) {
int trap, test;
double low, hi;
char repeat;
//Gather End Points
for (;;) {
printf("Enter endpoints of interval to be integrated (low hi): ");
test = scanf("%lf %lf", &low, &hi);
if (test == EOF)
return 1;
if (test != 2) {
printf("Error: Improperly formatted input\n");
if (flush_line() == EOF)
return 1;
continue; // ask again
}
if (low > hi) {
printf("Error: low must be < hi\n");
continue;
}
break; // input is valid
}
//Gather amount of triangles
for (;;) {
printf("Enter number of trapezoids to be used: ");
test = scanf("%d", &trap);
if (test == EOF)
return 1;
if (test != 1) {
printf("Error: Improperly formated input\n");
if (flush_line() == EOF)
return 1;
continue;
}
if (trap < 1) {
printf("Error: numT must be >= 1\n");
continue;
}
break;
}
//Output integrate
printf("Using %d trapezoids, integral between %lf and %lf is %lf\n",
trap, low, hi, integrate(low, hi, trap));
//Prompt user for another time
for (;;) {
printf("\nEvaluate another interval (Y/N)? ");
if (scanf(" %c", &repeat) != 1)
return 1; // unexpected end of file
switch (repeat) {
case 'Y':
case 'y':
break;
case 'N':
case 'n':
return 0;
default:
printf("Error: must enter Y or N\n");
if (flush_line() == EOF)
return 1;
continue;
}
break;
}
}
}
I need to write a script for the user to enter a score between 0 and 10, flush the bad input out, if user inputs it and then using a switch statement, tell a user what grade did he/she got.
Here is my script:
...
int main()
{
int input; // input from user
printf("Enter the number between 0 and 10 and I will tell you your grade!");
while ((input=scanf("Your input:", &input) != EOF))
{
if (input < 0 || input > 10) //input is invalid
{
printf("Sorry, invalid character data.");
while (getchar() !='\n')
{
printf("Your input must be from 0 to 10.", input);
scanf("%d", &input); //This part looks very bad for me
}
}
else
switch (input)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
printf("Your grade is F. \n");
break;
case 6:
printf("Your grade is D. \n");
break;
...
I got this far with my homework, and here are some "leftover" problems I can't fight with.
1) Whenever user submits anything after enter, it goes into infinite loop and prints Your grade is F., even when case = 6 for example.
2) I used break; at the end of each case. It looks like they don't work(?)
3) It looks like the problem in the second line in the second loop
scanf("%d", &input); //This part looks very bad for me
but then I guess the scripts accepts it as true since the else statements that includes switch begins to work, because otherwise it wouldn't print Your grade is F.
Try the following code. Have a look at what flush_stream is doing when we have invalid data...
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
void flush_stream();
void flush_stream() {
char c;
do {
c = getchar();
}
while (!isdigit(c) && c != '\n');
ungetc(c, stdin);
}
int main(void) {
const char *prompt = "Input please: ";
int input; // input from user
printf("Enter the number between 0 and 10 and I will tell you your grade!\n");
while(1) {
printf("%s", prompt);
int ret = scanf("%d", &input);
if(ret == 0) {
printf("Sorry, invalid character data, your input must be from 0 to 10.\n");
flush_stream();
continue;
}
if(ret > 0) {
if (input < 0 || input > 10) {
printf("Sorry, invalid character data, your input must be from 0 to 10.\n");
flush_stream();
continue;
}
switch (input) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
printf("Your grade is F. \n");
break;
case 6:
printf("Your grade is D. \n");
break;
}
}
}
}
It seems you are using scanf and printf wrong.
To input a number:
scanf("%d", &input);
To output a number:
printf("%d\n", input);
And in you while loop, when the input is illegal, why not just continue to the next loop?
while (true) {
printf("input your grade here: ");
if (scanf("%d", &input) == EOF) {
break;
}
if (input < 0 || input > 10) {
printf("your input is illegal.\n");
continue;
}
switch (input) {
...
}
}
I'm using a do-while loop to print a menu to the screen. And I'm reading choice as an integer. The proplem is that if the user enter a character the program blows up. How can I avoid that?
#include <stdio.h>
int menu() { // prints the main menu of labs///
int choice;
printf("1)Lab 5 ( Repetetitions ).\n2)Lab 10 ( Passing 1D-Arrays to functions ).\n3)GPA Calculation.\n4)EXIT.\n\nEnter your choice: ");
scanf("%d", &choice);
return choice;
}
int main() {
int choice;
do {
choice = menu();
if (choice != 4) {
if (choice == 1)
//lab5(choice);
else if (choice == 2)
//lab10(choice);
else if (choice == 3)
// lab11(choice);
else
printf("invalid choice\n");
}
} while (choice != 4);
return 0;
}
This should work for you, you need to check the return value of scanf
int menu() { // prints the main menu of labs///
int choice;
printf("1)Lab 5 ( Repetetitions ).\n2)Lab 10 ( Passing 1D-Arrays to functions ).\n3)GPA Calculation.\n4)EXIT.\n\nEnter your choice: ");
if(scanf("%d", &choice) == 1)
{
return choice;
}
else
{
return 0;
}
}
The scanf() (and family of functions) returns the number of successful conversions from the input buffer, if the conversion (%d) fails the function returns 0 (or EOF). In this case the character that could not be converted is not removed from buffer, this is why the endless loop occur, the conversion keeps failing for ever.
I used this method to flush the input buffer after the scanf call and the program behaved as expected.
Run the program online (don't know for how long this will stay up)
void flushInput(){
int c;
while((c = getchar()) != EOF && c != '\n')
/* discard */ ;
}
int menu() { // prints the main menu of labs///
int choice;
printf("1)Lab 5 ( Repetetitions ).\n2)Lab 10 ( Passing 1D-Arrays to functions ).\n3)GPA Calculation.\n4)EXIT.\n\nEnter your choice: ");
if(scanf("%d", &choice) != 1){
flushInput();
return 0;
}else{
flushInput();
return choice;
}
}
/*USE This Code*/
#include <stdio.h>
#include <stdlib.h>
void orderAsk(int orderStorage[1]);
int main()
{
int orderStorage[1];
orderAsk(orderStorage);
printf("%d",orderStorage[0]);
return 0;
}
void orderAsk(int orderStorage[1]){
int d;
d = scanf("%d", &orderStorage[0]);
if ( d!= 1) {
system("cls");
fflush(stdin);
printf("Error! Re-Enter\n");
orderAsk(orderStorage);
}
}
I am trying to make a simple calculator in Turbo C(I have my own reasons to why I use Turbo C now)
#include <stdio.h>
#define P printf
int loop[] = {1, 1, 1, 1};
int num;
char input[64];
void main()
{
int num1, num2;
char x, y;
while(loop[0] == 1)
{
clrscr();
P("Hello!, This simple calculator will help you compute 2 numbers.");
P("\nPress the corresponding key to choose the operation you will use.");
P("\n\nA - (A)ddition");
P("\nS - (S)ubtraction");
P("\nM - (M)ultiplication");
P("\nD - (D)ivision");
P("\n\nAnswer: ");
while(loop[1] == 1)
{
x = getchar();
if(tolower(x) == 'a')
{
P("\nYou have chosen addition.");
num1 = askForNumber("\n\nEnter 1st number: ");
num2 = askForNumber("\nEnter 2nd number: ");
P("\n\n%d + %d = %d", num1, num2, num1+num2);
}
else if(tolower(x) == 's')
{
P("\nYou have chosen subtraction.");
num1 = askForNumber("\n\nEnter 1st number: ");
num2 = askForNumber("\nEnter 2nd number: ");
P("\n\n%d - %d = %d", num1, num2, num1-num2);
}
else if(tolower(x) == 'm')
{
P("\nYou have chosen multiplication.");
num1 = askForNumber("\n\nEnter 1st number: ");
num2 = askForNumber("\nEnter 2nd number: ");
P("\n\n%d * %d = %d", num1, num2, num1*num2);
}
else if(tolower(x) == 'd')
{
P("\nYou have chosen division.");
num1 = askForNumber("\n\nEnter 1st number: ");
num2 = askForNumber("\nEnter 2nd number: ");
P("\n\n%g* %g = %.2f", (float)num1, (float)num2, (float)(num1/num2));
}
else
{
P("\nYou have entered an invalid character!");
P("\n\nAnswer: ");
continue;
}
while(loop[2] == 1)
{
P("\n\nDo you want to do another calculation? Y/N: ");
y = getchar();
if(tolower(y) == 'y' || tolower(y) == 'n')
{
loop[2] = 0;
}
else
{
P("\nYou have entered an invalid character.");
continue;
}
}
loop[1] = 0;
}
if(tolower(y) == 'y')
{
continue;
}
if(tolower(y) == 'n')
{
loop[0] = 0;
}
}
}
int askForNumber(const char *string)
{
P("%s", string);
while(loop[3] == 1)
{
fgets(input, (sizeof(input)/sizeof(input[0]))-1, stdin);
if(sscanf(input, "%d", &num) != 1)
{
num = 0;
P("Invalid number!");
continue;
}
return num;
}
}
I have these bugs:
After I finish a calculation, and press 'Y', it clears the screen non-stop.
After "Enter 1st number: ", the "Invalid number" shows up once even though I haven't typed anything yet(but i can still input a number and it will be saved to 'num1', "Invalid number just bugs me".
At the top where I am to input 'a' or 's' or 'm' or 'd' to choose an operation, if I put some letter except for that above, i get this
OUTPUT:
Answer: o
You have entered an invalid character!
Answer:
You have entered an invalid character!
Answer:
the error shows up twice, but i only typed once.
When there are no characters in the input buffer, the getchar function blocks until the return key is pressed. All keys, including return, are stored in the input buffer, then getchar returns the first character in the buffer. The next call to getchar will immediately return the next character in the buffer.
So if you press 'y' then return, the first call to getchar returns the 'y' character, and the next returns a newline character, i.e. the return key.
You need to flush the input buffer each time you use getchar to skip over the newline:
do {
c = getchar();
} while (c == '\n');
You nedd #include ctype.h to lower is part of that library tolower uses this library and its nowhere in your code