Repeat the Program Prompt - c

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;
}
}
}

Related

Retyping characters using getchar () and a while loop (Debugging)

I have a little problem with entering characters in C language. The program works fine after the first iteration of the loop, all the options from the MENU a), b), c), d), e) work. The problem, however, appears in subsequent iterations of the loop with the "a" and "c" options. It is as if it does not load characters immediately, only in the following lines. I put a link with an overview screen with the code and the console window.
Or maybe the problem is in another piece of code?
That's my fragment of code:
char menu(void) {
int ch;
printf("Enter the letter corresponding to the selected option:\n");
printf(" a) adding numbers to the BST tree from the keyboard \n");
printf(" b) adding random numbers to the tree to determine the number of numbers \n");
printf(" c) writing numbers in order from the smallest \n");
printf(" d) removing a specific number \n");
printf(" e) end \n");
while ((ch = getchar()) != EOF)
{
while (getchar() != '\n')
{
continue;
}
ch = tolower(ch);
if (strchr("abcde", ch) == NULL)
puts("Enter a, b, c, d or e:");
else
break;
}
if (ch == EOF)
ch = 'e';
return ch;
}
int main(int argc, char* argv[]) //This is main function
{
int number, size, size_moose, element_to_delete;
int left_compartment, right_compartment;
char choice;
root = NULL;
printf("Welcome to a number sorting program that uses the BST (Binary Search Tree) sorting algorithm\n");
printf("####################################################################################################\n");
printf("####################################################################################################\n");
printf("\t\tMENU\n\n");
while ((choice = menu()) != 'e') {
switch (choice) {
case 'a':
printf("How many numbers do you want to enter?\n");
scanf("%d", &size);
printf("Enter the numbers one after the other:\n");
for (int i = 0; i < size; i++)
{
scanf("%d", &number);
dodawanie(number, root); //the name of the adding function
}
printf("\n");
break;
case 'b':
printf("How many numbers do you want to draw?\n");
scanf("%d", &size_moose);
printf("Enter the left boundary of the range (e.g. 1):\n");
scanf("%d", &left_compartment);
printf("Enter the right bound of the range (e.g. 100):\n");
scanf("%d", &right_compartment);
for (int i = 0; i < size_moose; i++)
{
//using a random number function
number = losowanie(left_compartment, right_compartment);
dodawanie(number, root);
}
printf("...I drew a %d number/numbers...\n", size_moose);
printf("\n");
break;
case 'c':
printf("Listing the numbers in order from the smallest:\n");
in_order_tree_walk(root); //a function that prints out ordered numbers
printf("\n");
break;
case 'd':
printf("Give a specific value to delete:\n");
scanf("%d", &element_to_delete);
kasowanie(szukaj(root, element_to_delete)); //using a function to remove a specific element
printf("\n");
break;
default:
printf("Error in switch statement\n");
}
}
printf("####################################################################################################\n");
printf("####################################################################################################\n");
printf("Goodbye!\n");
return 0;
}
I put a screen with an example of the program's operation
problemC

Why non-integer inputs cause infinite loop?

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.

my do-while is terminating instead of continuing my C program

When I'm trying to run without debugging the code everything runs smooth but as soon as I press Y so I can continue inputting numbers it terminates (gotta say I need help)
int main() {
int a;
char c;
do {
puts("dwse mou enan arithmo: ");
scanf_s("%d", &a);
if (a > 0) {
if (a % 2 == 0)
printf("the number %d is even \n", a);
else
printf("the number %d is odd \n", a);
} else {
printf("the program won't run with negative numbers \n");
}
printf("if you want to proceed press y or Y :");
c = getchar();
getchar();
} while (c == 'y' || c == 'Y');
return 0;
}
The character read by getchar() is the pending newline that was typed after the number but was not consumed by scanf_s.
You should consume this pending newline before reading the next character for the continuation test, which can be done easily in scanf with a space before the %c conversion specification:
#include <stdio.h>
int main() {
int a;
char c;
for (;;) {
printf("dwse mou enan arithmo: ");
if (scanf_s("%d", &a) != 1)
break;
if (a >= 0) {
if (a % 2 == 0)
printf("the number %d is even\n", a);
else
printf("the number %d is odd\n", a);
} else {
printf("the program does not accept negative numbers\n");
}
printf("if you want to proceed press y or Y: ");
if (scanf_s(" %c", &c) != 1 || (c != 'y' && c != 'Y'))
break;
}
return 0;
}

Double while loop for flushing data before a switch statement

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) {
...
}
}

Using getchar() in a while loop, prints a statement twice.. how?

I have a very simple program like this
int main()
{
int opt;
int n;
int flag = 1;
while(flag)
{
printf("m inside while.Press c to continue\n");
if((opt = getchar())== 'c')
{
printf("choose a number\n");
scanf(" %d",&n);
switch(n)
{
case 0:
printf("m zero\n");
break;
case 1:
printf("entered one\n");
break;
case 3:
printf("m exit\n");
flag = 0;
break;
}
printf("m broke\n");
}
}
printf("m out\n");
return 0;
}
I get output like this:
m inside while.Press c to continue
c
choose a number
1
entered one
m broke
m inside while.Press c to continue
m inside while.Press c to continue
c
choose a number
My doubt is why "m inside while.Press c to continue" gets printed twice after every loop??
Thanks in advance
This is because of \n character left behind by previous scanf. When you input a number and press Enter key, an additional \n character passed to the standard input buffer. scanf reads that nuber leaving behind \n in the buffer. On next iteration of loop getchar reads \n before pressing any character by you and hence m inside while.Press c to continue printed twice as \n is not c.
Place this snippet of code just after the scanf statement in your while loop to eat up the newline characters
while(getchar() != '\n');
This will eat up any number of \n.
For more detailed explanation on the behavior of getchar read this answer.
You final code should be
int main()
{
int opt;
int n;
int flag = 1;
while(flag)
{
printf("m inside while.Press c to continue\n");
if((opt = getchar())== 'c')
{
printf("choose a number\n");
scanf(" %d",&n);
while(getchar() != '\n');
switch(n)
{
case 0:
printf("m zero\n");
break;
case 1:
printf("entered one\n");
break;
case 3:
printf("m exit\n");
flag = 0;
break;
}
printf("m broke\n");
}
}
printf("m out\n");
return 0;
}
After scanf reads the input there is a '\n' still in the buffer you have to clear it otherwise it will be readed by getchar in the next time and as it's != 'c' it will prompt again:
Try this :
printf("choose a number\n");
scanf(" %d",&n);
char c;
while (c = getchar != '\n' && c != EOF); // clear the buffer
while(flag)
{
printf("m inside while.Press c to continue\n");
while((opt=getchar()) != '\n') {
if(opt == 'c')
{
printf("choose a number\n");
scanf(" %d",&n);
switch(n)
{
case 0:
printf("m zero\n");
break;
case 1:
printf("entered one\n");
break;
case 3:
printf("m exit\n");
flag = 0;
break;
}
printf("m broke\n");
}
}
}

Resources