Hi this program keeps crashing when I enter a character into the menu. I have figured out it is because scanf is looking for an integer and cannot find one so it goes into an infinite loop. I have yet to find how to correct this anywhere online and am looking for some much needed help. I cant seem to create a function to do input validation and that is where I need help as our professor does not seem to help us with these. Thank you.
#include <stdio.h>
void resistor (void);
float calc_freq(float ra, float rb, float c) // function to calculate Frequency
{
return 1.44/((ra+(2*rb))*c);
}
float calc_duty_cycle(float ra, float rb, float c) // function to calculate duty cycle
{
return (rb)/(ra+(2*ra));
}
int main (void)
{
int choice; // choice to run program from start menu or quit
while (1)
{
// Menu for entering resistor and capacitor values
printf("Welcome to the 555 Timer Frequency and Duty Cycle Calculator\n");
printf("Please enter two resistor values in between ");
printf("1 kOhms and 100 kOhms and a capacitor value\n\n");
printf("Menu\n\n");
printf("1. Continue\n");
printf("2. Exit\n");
scanf("%d", choice);
switch (choice)
{
case 1: resistor();
break;
case 2 : printf("Goodbye.");
break;
default: printf("Sorry I do not understand\n\n");
main();
}
break;
}
return 0;
}
void resistor (void)
{
float ra, rb, c; // Float variables for two resistor values and capacitor
while(1) // While loop to gather resistor A value
{
printf("Enter a value for Resistor Ra (kOhms): "); // First Resistor Value
scanf("%f", &ra);
if(ra < 1 || ra > 100) // Will repeat loop until value between 1 and 100 is entered
printf("Invalid selection, choose again.\n");
else
break; // breaks loop when valid data is entered
}
while(1)
{
printf("Enter a value for Resistor Rb (kOhms): "); // Second Resistor Value
scanf("%f", &rb);
if(rb < 1 || rb > 100) // Will repeat loop until value between 1 and 100 is entered
printf("Invalid selection, choose again.\n");
else
break; // breaks loop when valid data is entered
}
while(1)
{
printf("\nCapacitor (uF) : "); // Capacitor Value
scanf("%f", &c);
if(c <= 0)
printf("Invalid selection, choose again.\n");
else
{
float freq = calc_freq(ra, rb, c); // call function to calculate frequency
float duty_cycle = calc_duty_cycle(ra, rb, c); // cal function to calculate duty cycle
printf("\nFrequency is: %.2f kHz\n", freq); // print frequency
printf("Duty cycle is: %.2f percent\n", duty_cycle*100); // print duty cycle
break; // break while loop
}
}
}
Related
Hi I keep getting an error message saying that my functions resistor and freqduty are not defined. I am confused on what this means. I am attaching my code and hopefully can be lead in the right direction as this is stumping me. Thanks. I declare and define the prototypes and call the functions so I am confused why the complier will not take this code and compile.
#include <stdio.h>
void resistor (void);
void freqduty (float ra, float rb, float c); // Prototype function for frequency and duty cycle
int main (void)
{
int choice; // choice to run program from start menu or quit
while (1)
{
// Menu for entering resistor and capacitor values
printf("Welcome to the 555 Timer Frequency and Duty Cycle Calculator\n");
printf("Please enter two resistor values in between ");
printf("1 kOhms and 100 kOhms and a capacitor value\n\n");
printf("Menu\n\n");
printf("1. Continue\n");
printf("2. Exit\n");
scanf("%d",&choice);
switch (choice)
{
case 1: resistor();
break;
case 2: printf("Goodbye\n");
break;
default: printf("Wrong Choice. Enter again\n");
break;
}
void resistor (void);
float ra, rb, c; // Float variables for two resistor values and capacitor
while(1) // While loop to gather resistor A value
{
printf("Enter a value for Resistor Ra (kOhms): "); // First Resistor Value
scanf("%f", &ra);
if(ra < 1 || ra > 100) // Will repeat loop until value between 1 and 100 is entered
printf("Invalid selection, choose again.\n");
else
break; // breaks loop when valid data is entered
}
while(1)
{
printf("Resistor Rb (kOhms): "); // Second Resistor Value
scanf("%f", &rb);
if(rb < 1 || rb > 100) // Will repeat loop until value between 1 and 100 is entered
printf("Invalid selection, choose again.\n");
else
break; // breaks loop when valid data is entered
}
while(1)
{
printf("\nCapacitor (uF) : "); // Capacitor Value
scanf("%f", &c);
if(c <= 0)
printf("Invalid selection, choose again.\n");
else
{
freqduty (ra, rb, c); // call function to compute frequency and duty cycle
break; // break while loop and restart program from menu selection screen
}
break;
}
void freqduty (float ra, float rb, float c) // function to compute frequency and duty cycle
{
float freq, dutycyc, add; // Float variables for frequency and duty cycle equations
freq = 2.0 * rb;
add = (1.44 / (ra + ((2.0 * rb) * c)));
dutycyc = (rb / (ra + (2.0 * rb)));
printf("\nThe frequency for these values entered is %.2f and the duty cycle");
printf(" is %.2f \n\n", freq , dutycyc);
printf("%f %f %f", ra, rb, c);
}
}
return 0;
}
You declared the two functions at file scope. You defined the two functions inside function main(). This means that they are local to function main(), and invisible outside.
Also, at the point where they are are used, they are not defined yet.
Re-arrange the code and it has a chance to work.
I just noticed, they actually defined inside the while(1) inside main(), which is very unusual.
I need to loop the switch statement until 1 or 2 is entered as an input. Any help would be nice or sample code. I tried to use a while loop and it kept crashing. I tried a do while as well and it turned into an infinite loop so I must be doing something wrong.
int main (void)
{
int choice; // choice to run program from start menu or quit
while (1)
{
// Menu for entering resistor and capacitor values
printf("Welcome to the 555 Timer Frequency and Duty Cycle Calculator\n");
printf("Please enter two resistor values in between ");
printf("1 kOhms and 100 kOhms and a capacitor value\n\n");
//Start of menu
printf("Menu\n\n");
printf("1. Continue\n");
printf("2. Exit\n");
scanf("%d", &choice); // User inputs value
switch (choice)
{
case 1:
resistor(); // Program resistor is run if 1 is input
break;
case 2:
printf("Goodbye."); // Program ends if 2 is input
break; // break is used to exit while loop
default:
printf("Sorry I do not understand\n\n");
fflush(stdin); /* clears input buffer to allow user to input a new value if anything other
than 1 or 2 is input into scanf */
}
break;
}
return 0;
}
The problem is that you have a "break" right at the end of your "while", so it's only executed once.
It has been a long time since I did program in C, but if I remember correctly you should avoid using "fflush()" since it has an undefined behavior. Instead, you can change your "scanf()" to be something like:
scanf(" %d", &choice); // User inputs value
That way, you have the same supposed effect of the "fflush()" at the same time of having a cleaner code.
You can use this code
for(;;) {
// Menu for entering resistor and capacitor values
// Start of menu
// User inputs value
if(choice == 1) { ... break; }
else if(choice == 2) { ... return 0; } // If you use the break,the for loop will be stopped or You can use return 0; to return the whole function
else { ... break; }
}
or, also you can use this code
for(;;) {
switch(choice ) {
case 1: ... break;
case 2: ... return 0; // If you use the break, only switch statement is stopped. You can use return 0; to return the whole function
default: ... break;
}
}
Edit :
#include <stdio.h>
int main (void)
{
int choice; // choice to run program from start menu or quit
// Menu for entering resistor and capacitor values
printf("Welcome to the 555 Timer Frequency and Duty Cycle Calculator\n");
printf("Please enter two resistor values in between ");
printf("1 kOhms and 100 kOhms and a capacitor value\n\n");
while (1)
{
//Start of menu
printf("Menu\n");
printf("1. Continue\n");
printf("2. Exit\n");
scanf("%d", &choice); // User inputs value
switch (choice)
{
case 1: // Program resistor is run if 1 is input
break;
case 2: printf("Goodbye."); // Program ends if 2 is input
return 0; // return 0; is used to exit while loop
default: printf("Sorry I do not understand\nStart Again !\n");
// fflush(stdin); /* clears input buffer to allow user to input a new value if anything other than 1 or 2 is input into scanf */
break;
}
printf("\n");
}
return 0;
}
In this code I have several querys for user input. If there is an invalid input like 'r' instead of 4, I want my programm to say "invalid input" and ask for another user input. I tried a lot but I couldn't get it to work.
I commented the problematic locations in the code. Thanks for help.
#include <stdio.h>
int main()
{
double Operand1;
double Operand2;
int Menuchoice;
int Input;
char Dummy;
double Result;
do
{
printf("Simple Calculator\n");
printf("========================\n");
printf("\n");
printf("1. Addition\n");
printf("2. Subraction\n");
printf("3. Multiplication\n");
printf("4. Division\n");
printf("9. Quit\n");
Input = scanf("%i", &Menuchoice); // At this point I want to check if there is a valid input and
do scanf("%c", &Dummy); // if not the programm should ask again
while (Dummy != '\n');
if(Input)
{
switch(Menuchoice)
{
case 1: printf("Type in the first operand:\n");
scanf("%lf", &Operand1) // Here I want to validate the input
printf("Type in the second operand:\n"); // again and the programm should also ask
scanf("%lf", &Operand2) // again if it was invalid
printf("%lf + %lf = %lf\n", Operand1, Operand2, Result);
break;
case 2:
case 3:
case 4:
default: printf("No valid input!\n");
break;
}
}
}while (Menuchoice != 9);
return 0;
}
Manual page of scanf:
On success, these functions return the number of input items successfully matched and assigned; this can be fewer than provided for, or even zero, in the event of an early matching failure.
So here is a sample which could lead you to solve your problem:
#include <stdio.h>
int main (int argc, char* argv)
{
double o;
int res;
// To illustrate, I chose to set up an infinite loop.
// If the input is correct, we'll "break" it
while(1)
{
printf("Enter a double: ");
res = scanf("%lf",&o);
// Success = 1 read input
if (res == 1)
{
printf("Yahoo, got it right: %f\n",o);
break; // We exit the loop
}
// Ah, we failed
printf("Please retry.\n");
// popping the CR character to avoid it to be got by the next scanf()
getchar();
// Here we go for another loop.
}
// Good, we got our double.
printf("Hey, sounds like we got outside this infinite loop.\n");
}
Example:
user#so:~$ ./a.out
Enter a double: r
Please retry.
Enter a double: f
Please retry.
Enter a double: 6.543
Yahoo, got it right: 6.543000
Keep in mind this check is not perfect. For example, "frg6sgg" will success and be displayed as 6.0000000 by printf().
I have a converter, but it converts all the units that are in the program.how can i make that the user who opens the project to choose what type of unit to convert?
#include<stdio.h>
#include<conio.h>
int main()
{
float m, f, l, g, cm, inch;
printf("Type meter : ");
scanf("%f",&m);
f = 3.2808399 * m;
printf("feets: %f",f);
printf("\nType gallons : ");
scanf("%f",&g);
l = 3.78541178 * g;
printf("litres: %f",l);
printf("\ninches : ");
scanf("%f", &inch);
cm = 2.54 * inch;
printf("cm: %f", cm);
return 0;
}
This code below is definitely not the best one in terms of complexity, portability, optimisation (Memory/Time) and many other aspects of programming, but it should get you going.
I have added comments to explain the code. Almost all of the code with all those printfs is self-explanatory.
#include<stdio.h>
int main(void)
{
// We need just 3 variables
// This one is for getting the user option
int choice = 0;
// We need these to float variables for user input and an output
float Input = 0.0, Output = 0.0;
// Following code till `while(1)` is optional.
printf("\nThis is a converter with a fixed set of functions.");
printf("\nNote: This converter does support floating point inputs.");
printf("\nNote: Floating point inputs and outputs are truncated to 2 digits after decimal place.");
printf("\nNote: Press any key to acknowledge!");
getchar();
// To get user input multiple times, you'll need to loop
while(1)
{
printf("\n\nFollowing functions are supported, enter a suitable choice form the list below.");
printf("\nPress `1` for Converting Metres to Feet.");
printf("\nPress `2` for Converting Gallons to Litres.");
printf("\nPress `3` for Converting Inches to Centimetres.");
printf("\nPress `0` for Exiting the program.");
printf("\nEnter your Option : ");
scanf("%d", &choice);
// Lets implement a switch-case statement to get the job done
switch(choice)
{
case 1:
printf("Enter input value (in Metres) : ");
scanf("%f",&Input);
Output = 3.2808399 * Input;
printf("%0.2f Metres is equal to %0.2f Feets", Input, Output);
break;
case 2:
printf("Enter input value (in Gallons) : ");
scanf("%f",&Input);
Output = 3.78541178 * Input;
printf("%0.2f Gallons is equal to %0.2f Litres", Input, Output);
break;
case 3:
printf("Enter input value (in Inches) : ");
scanf("%f",&Input);
Output = 2.54 * Input;
printf("%0.2f Inches is equal to %0.2f Centimetres", Input, Output);
break;
case 0:
printf("Thank you. The program will exit now!\n\n");
return 0;
break;
// This default case should take care of the invalid set of choices entered by user
default:
printf("Option you entered is either invalid or is not supported as of now!");
}
}
return 0;
}
Another way to implement this could be using an if-else if-else ladder.
So you can remove swtich-case statements from the code below and replace it with the following:
if(choice == 0)
{
printf("Thank you. The program will exit now!\n\n");
return 0;
}
else if(choice == 1)
{
printf("Enter input value (in Metres) : ");
scanf("%f",&Input);
Output = 3.2808399 * Input;
printf("%0.2f Metres is equal to %0.2f Feets", Input, Output);
}
else if(choice == 2)
{
printf("Enter input value (in Gallons) : ");
scanf("%f",&Input);
Output = 3.78541178 * Input;
printf("%0.2f Gallons is equal to %0.2f Litres", Input, Output);
}
else if(choice == 3)
{
printf("Enter input value (in Inches) : ");
scanf("%f",&Input);
Output = 2.54 * Input;
printf("%0.2f Inches is equal to %0.2f Centimetres", Input, Output);
}
else
{
// This should take care of the invalid set of choices entered by user
printf("Option you entered is either invalid or is not supported as of now!");
}
char unit;
printf("Which unit do you want to convert (input:m,g,i): ");
scanf("%c",&unit);
if(unit == 'm') ...
else if( if(unit == 'g'))....
else if( if(unit == 'i'))....
else printf("wrong input ! \n");
I might be giving more than enough but long story short I am working on an ATM machine program and I am trying to put the "switch" statement in the main function inside a loop so the user can get more transactions.
I am running into a problem where I would deposit 100 but then when I check the balance it is still at 0. I know everything else works fine but that loop is killing me, I would appreciate any help!
Don't mind all of the extra stuff it is just there to give an idea on what i am working on
int main ()
{
char option;
float balance ;
int count = 1;
option = displayMenu();
do
{
switch (option)
{
case 'D':
getDeposit(balance);
main();
count++;
break;
case 'W':
getWithdrawal(balance);
main();
count++;
break;
case 'B':
displayBalance(balance);
main();
count++;
break;
case 'Q':
printf("Thank you!");
break;
main();
}
} while ( count <= 5);
return 0;
}
char displayMenu()
{
char option;
printf("\n Welcome to HFC Federal Credit Union \n");
printf("\n Please select from the following menu: \n ");
printf("\n D: Make a deposit \n ");
printf("\n W: Make a withdrawal \n ");
printf("\n B: Check your account balance \n ");
printf("\n Q: To quit \n ");
scanf("\n%c" , &option);
return option;
}
float getDeposit(float balance)
{
float deposit;
printf("\n Please enter the amount you want to deposit! ");
scanf("%f" , &deposit);
balance += deposit;
return balance;
}
float getWithdrawal(float balance)
{
float withdrawal;
printf("\n Please enter the amount you want to withdraw! ");
scanf("%f" , &withdrawal);
balance -= withdrawal;
return balance;
}
void displayBalance(float balance)
{
printf("\n Your current balance is %f " , balance);
}
You're recursively calling main() on every iteration of the loop. Just remove this call, and you should be good to go.
You'll also need to assign the return values of your functions to balance, otherwise they won't be able to affect its value.
There are a number of issues with this code... Here are my main pointers (but not all of them, I'm just answering the question):
You're calling main over and over again, for simplicity, you could consider this as restarting the application every time (except for stack issues, that I'm ignoring and other nasty side effects).
You didn't initialize the balance (and friends) variables. They might contain "junk" data.
You're ignoring the return values from the functions you use. If you're not using pointer, you should use assignment.
Your menu printing function is out of the loop... I doubt if that's what you wanted.
Here's a quick dirty fix (untested):
int main() {
char option;
float balance = 0;
int count = 1;
do {
option = displayMenu(); // moved into the loop.
switch (option) {
case 'D':
balance = getDeposit(balance);
count++;
break;
case 'W':
balance = getWithdrawal(balance);
count++;
break;
case 'B':
balance = displayBalance(balance);
count++;
break;
case 'Q':
printf("Thank you!");
break;
}
} while (count <= 5);
return 0;
}
char displayMenu(void) {
char option;
printf("\n Welcome to HFC Federal Credit Union \n");
printf("\n Please select from the following menu: \n ");
printf("\n D: Make a deposit \n ");
printf("\n W: Make a withdrawal \n ");
printf("\n B: Check your account balance \n ");
printf("\n Q: To quit \n ");
scanf("\n%c", &option);
return option;
}
float getDeposit(float balance) {
float deposit;
printf("\n Please enter the amount you want to deposit! ");
scanf("%f", &deposit);
balance += deposit;
return balance;
}
float getWithdrawal(float balance) {
float withdrawal;
printf("\n Please enter the amount you want to withdraw! ");
scanf("%f", &withdrawal);
balance -= withdrawal;
return balance;
}
void displayBalance(float balance) {
printf("\n Your current balance is %f ", balance);
}
Good Luck!
I think the main problem is the update of the switch control variable outside the loop.
Reacting to "Q" with ending is somewhat necessary... then only allowing 5 becomes unneeded.
I fixed several other things, too; and provided comments on them.
And I improved testability a little (5->6). I kept the counting, just extended to 6, in order to allow a complete test "D 100 , B, W 50, B ,Q".
Nice design by the way, to return the balance from the functions, instead of using pointers or global variable. But you need to use the return value instead of ignoring it.
/* include necessary headers, do not skip this when making your MCVE */
#include <stdio.h>
/* prototypes of your functions,
necessary to avoid the "immplicitly declared" warnigns
when compiling "gcc -Wall -Wextra"; which you should
*/
char displayMenu(void);
float getDeposit(float balance);
float getWithdrawal(float balance);
void displayBalance(float balance);
/* slightly better header of main, with "void" */
int main (void)
{
char option;
float balance=0.0; /* initialise your main variable */
int count = 1;
/* your very important update of the switch control variable has been moved ... */
do
{
option = displayMenu(); /* ...here */
/* If you do not update your switch variable inside the loop,
then it will forever think about the very first command,
this explains most of your problem.
*/
switch (option)
{
case 'D':
balance=getDeposit(balance); /* update balance */
/* removed the recursive call to main(),
it is not needed as a solution to the problem that the program
always uses the first command (when updating inside the loop)
and otherwise just makes everything much more complicated and
risky.
*/
count++;
break;
case 'W':
balance=getWithdrawal(balance); /* update balance */
count++;
break;
case 'B':
displayBalance(balance);
count++;
break;
case 'Q':
printf("Thank you!");
/* adding a way to get out of the loop,
using a magic value for the count,
this is a mehtod frowned upon by most,
but it minimises the changes needed to your
own coding attempt.
*/
count=0;
break;
}
} while ( (count <= 6)&&(count>0) ); /* additionally check for the magic "Q" value
check against count<=6, to allow testing D,B,W,B,Q */
return 0;
}
/* use explicitly empty parameter list for functions */
char displayMenu(void)
{
char option;
printf("\n Welcome to HFC Federal Credit Union \n");
printf("\n Please select from the following menu: \n ");
printf("\n D: Make a deposit \n ");
printf("\n W: Make a withdrawal \n ");
printf("\n B: Check your account balance \n ");
printf("\n Q: To quit \n ");
scanf("\n%c" , &option);
return option;
}
float getDeposit(float balance)
{
float deposit;
printf("\n Please enter the amount you want to deposit! ");
scanf("%f" , &deposit);
balance += deposit;
return balance;
}
float getWithdrawal(float balance)
{
float withdrawal;
printf("\n Please enter the amount you want to withdraw! ");
scanf("%f" , &withdrawal);
balance -= withdrawal;
return balance;
}
void displayBalance(float balance)
{
printf("\n Your current balance is %f " , balance);
}
you haven't changed the variable in main().
you can change the loop to this:
do
{
switch (option)
{
case 'D':
balance = getDeposit(balance);
count++;
break;
case 'W':
balance = getWithdrawal(balance);
count++;
break;
case 'B':
displayBalance(balance);
count++;
break;
case 'Q':
printf("Thank you!");
break;
}
} while (count <= 5);