Having more trouble with this than I probably should. I'm building a very simple bank menu interface where a user can check their balance, deposit, withdraw, or quit out of the menu. case 1
, case2
, and case3
appear to work fine, but case 4
doesn't function properly no matter what I try off of Google.
In this current version, the printf()
statement in case 4
occurs, then nothing else seems to happen until I input one of the other options (1 - 3) twice, at which point the loop will cycle through and automatically use whatever the second input was. I tried getchar()
but that didn't seem to work (or I wasn't implementing it correctly).
Why is this behavior occurring and how can I fix it?
Here's the code:
#include <stdio.h>
#include <cs50.h>
double deposit(double a, double b);
double withdraw(double a, double b);
int main(void)
{
int resume = 1;
int user_input = 0;
double user_balance = 10.00;
printf("Welcome to UBank!\n");
while (resume)
{
printf("\n====================\n");
printf("Select an operation:\n\n1. Show Balance\n2. Make a Deposit\n3. Make a Withdrawal\n4. Quit\n"
"====================\n\n");
scanf("%d", &user_input);
int quit_character = 0x00;
double deposit_amount = 0.00;
double withdraw_amount = 0.00;
switch (user_input)
{
case 1:
printf("Balance: $%.2lf\n", user_balance);
break;
case 2:
printf("How much would you like to deposit?\n");
scanf("%lf", &deposit_amount);
user_balance = deposit(user_balance, deposit_amount);
break;
case 3:
printf("How much would you like to withdraw?\n");
scanf("%lf", &withdraw_amount);
user_balance = withdraw(user_balance, withdraw_amount);
break;
case 4:
printf("Press Enter to finish banking or any other key to continue.\n");
scanf("%d\n", &quit_character);
if (quit_character == 0x0A)
{
resume = 0;
}
break;
}
}
}
double deposit(double a, double b)
{
if (b > 0 && b < 10000)
{
return a + b;
}
else
{
printf("Please enter a valid amount. (0.01 - 9999.99)\n");
return a;
}
}
double withdraw(double a, double b)
{
if (b > 0 && a - b >= 10)
{
return a - b;
}
else if (b <= 0)
{
printf("Withdrawal amount must be greater than $0.00.\n");
}
else if (a - b < 10)
{
printf("Withdrawal amount invalid. Remaining balance must be $10.00 or more.\n");
}
return a;
}
Assume I want to paint the exterior of my home. I purchase the paint, and return to my home (a 5 hour drive from the nearest store). When I get home, I realize that I forgot to also purchase a paint brush. I don't want to spend then next 10 hours driving to get a paint brush, but how should I apply the paint?
I could use a broom, mop, rag, my hands, my son's hands, etc., none of which are preferable to a brush. But then I realize... I have a horse! I clip the horse's main and make my own paintbrush! I paint for the day, and clip my horse again next week when I need another brush. That ends up being a lot cheaper than the 10 hour drive.
OK... that is a corny, fictional, story. The point is that using scanf() for user input is like painting with a pig-nose. It is just the wrong tool for the job. It would be preferable to write your own user input function that works the way you expect it to.
Consider the GetInput() function below. I had to make it myself, but it sure beats using scanf() for user input:
#include <stdio.h>
#include <stdlib.h>
double deposit(double a, double b);
double withdraw(double a, double b);
/*-----------------------------------------------------------------------------------
** Get input from user, and return it as specific types.
**
** Caller may specify NULL for any (or all) input types that are not needed.
*/
void GetInput(int *intOut, char *charOut, double *doubleOut)
{
// Pointer to a temporary (allocated memory) buffer to hold user input.
char *line_A = NULL;
// Number of bytes allocated to the temporary (allocated) buffer.
size_t lineSize = 0;
// Holds the number of bytes entered by the user, or (-1) for error.
ssize_t lineLength;
lineLength=getline(&line_A, &lineSize, stdin);
if(-1 == lineLength)
{
fprintf(stderr, "getline() failed.\n"
goto CLEANUP;
}
// If the caller did not specify NULL for intOut, ...
if(intOut)
// Convert the string to an int and pass it back to the caller.
*intOut = atoi(line_A);
if(charOut)
*charOut = *line_A;
if(doubleOut)
*doubleOut = atof(line_A);
CLEANUP:
if(line_A)
free(line_A);
return;
}
int main(void)
{
int resume = 1;
int user_input = 0;
double user_balance = 10.00;
printf("Welcome to UBank!\n");
while (resume)
{
printf("\n====================\n");
printf("Select an operation:\n\n1. Show Balance\n2. Make a Deposit\n3. Make a Withdrawal\n4. Quit\n"
"====================\n\n");
GetInput(&user_input, NULL, NULL); // Get an integer from the user.
char quit_character = 0x00;
double deposit_amount = 0.00;
double withdraw_amount = 0.00;
switch (user_input)
{
case 1:
printf("Balance: $%.2lf\n", user_balance);
break;
case 2:
printf("How much would you like to deposit?\n");
GetInput(NULL, NULL, &deposit_amount); // Get a double from the user.
user_balance = deposit(user_balance, deposit_amount);
break;
case 3:
printf("How much would you like to withdraw?\n");
GetInput(NULL, NULL, &withdraw_amount); // Get a double from the user.
user_balance = withdraw(user_balance, withdraw_amount);
break;
case 4:
printf("Press Enter to finish banking or any other key to continue.\n");
GetInput(NULL, &quit_character, NULL); //Get a character from the user.
if (quit_character == 0x0A)
{
resume = 0;
}
break;
}
}
}
double deposit(double a, double b)
{
if (b > 0 && b < 10000)
{
return a + b;
}
else
{
printf("Please enter a valid amount. (0.01 - 9999.99)\n");
return a;
}
}
double withdraw(double a, double b)
{
if (b > 0 && a - b >= 10)
{
return a - b;
}
else if (b <= 0)
{
printf("Withdrawal amount must be greater than $0.00.\n");
}
else if (a - b < 10)
{
printf("Withdrawal amount invalid. Remaining balance must be $10.00 or more.\n");
}
return a;
}