Scanf with pointers in C - c

I have some code, but I'll shorten it to show only the relevant parts.
// Displays the list of user’s options available
//Displays the user’s selections and sets the value of the choice
void mainMenu(int *choice);
//Displays the types of account they would like to access and sets the
//value of the chosen account type
void AccountMenu(char *typeAcct);
//Prompts the user for the amount of their deposit and updates the selected account
void DepositMoney(double *currBal);
//Asks the user if they want another transaction
void Repeat(char * doAgain);
int main(){
int choice = 0;
char repeat = 'y';
double checkBal = 575.0,
saveBal = 3750.0,
credBal = 450.0;
char typeAcct;
while(repeat!='n'){
mainMenu(&choice); //get action from user
AccountMenu(&typeAcct); //get account to perform action on from user
switch (choice){
case 1:
switch (typeAcct){
case 'c':
DepositMoney(&checkBal);
break;
case 's':
DepositMoney(&saveBal);
break;
case 'r':
DepositMoney(&credBal);
break;
} //case 1
break;
}
Repeat(&repeat);
repeat = tolower(repeat);
}
}
// Displays the list of user’s options available
//Displays the user’s selections and sets the value of the choice
void mainMenu(int *choice){
printf("Bank Program\n\n");
printf("Please enter your choice:\n");
printf("[1] Deposit\n");
printf("[2] Withdraw\n");
printf("[3] Balance Inquiry\n\n >> ");
scanf(" %d", choice);
}
//Displays the types of account they would like to access and sets the
//value of the chosen account type
void AccountMenu(char *typeAcct){
char choice;
printf("Please enter your choice:\n");
printf("[C] Checking\n");
printf("[S] Savings\n");
printf("[R] Credit\n\n >> ");
scanf(" %c", &choice);
*typeAcct = tolower(choice);
}
//Prompts the user for the amount of their deposit and updates the selected account
void DepositMoney(double *currBal){
printf("Depositing money.\nHow much would you like to deposit?\n\n >> ");
double amount = 0; //deposit amount
scanf(" &f", &amount);
*currBal = *currBal + amount;
}
void Repeat(char * doAgain){
printf("Would you like to perform another transaction? (y/n)\n\n >> ");
scanf(" &c", doAgain);
}
When I execute this code, it runs mostly fine. For example, if I enter "1" for mainMenu and "c" for AccountMenu, choice and typeAcct are both indeed set to "1" and "c" respectively.
The problem doesn't seem to be with the loop. I've tried taking out the loop and only running it once and it still doesn't work. What happens is that after inputting the amount of money I would like to deposit, the value of the variable isn't updated and mainMenu and AccountMenu are run again (even when DepositMoney is the last line of code in the main function and there is no loop). Why does this happen?

1) Incorrect scanf() usage
double amount = 0;
// scanf(" &f", &amount);
scanf(" %lf", &amount);
// scanf(" &c", doAgain);
scanf(" %c", doAgain);
2) Insure your compiler warning are fully enabled. This is the most important bit as most problems are quickly identified this way.
3) Always check the return value of scanf(). BTW, the leading space in " %f" is not needed as "%f" scans over leading white-space anyways. Good though, to have with " %c".
if (scanf("%lf", &amount) != 1) Handle_Error();
4) tolower() take an int. In the rare siuation where a user enters a char in the range \x80 to \xFF, the conversion of char to int is a sign extend and likely a negative number. Unfortunately, this does not work for tolower() which is well defined for 0 to 255 and EOF, but not other negative values.
// repeat = tolower(repeat);
repeat = tolower((unsigned char) repeat);
...
// *typeAcct = tolower(choice);
*typeAcct = tolower((unsigned char) choice);

Related

I want to create a menu that shows 1. Client details, 2.Property details and 3. Exit

I want to create a menu that shows:
Client details
Property details
Exit
#include <stdio.h>
#include <conio.h>
void main() {
char L,F,H;
float CID,Aoc,Pte,Cost_per_sqft;
int dicnt,age,ch;
printf("Enter the Client ID\n");
scanf("%f", &CID);
printf("Enter the age of client\n");
scanf("%f", &Aoc);
if (age >=60) {
printf("The client is eligible for a discount\n");
} else if (age<60) {
printf("The client is not eligible for a discount\n");
} {
printf("Select Porperty type\nF=Flat\nL=Land\nH=House\n");
scanf("%f", &Pte);
}
printf("Please select the menu option\n");
printf("1.Client ID\n");
printf("2.Property details\n");
printf("3.Exit\n");
scanf("%d", &ch);
switch(ch) {
case 1:
printf("Client ID %f", CID);
printf("Age of client %f", Aoc);
}
}
It's not letting me enter the option to open a menu, also the age else is doesn't work because age => 60 is also showing not eligible for discount. The switch case doesn't work either.
Problem 1 is that you have defined two variables, float Aoc and int age, then attempt to use them interchangeably. Also, the first time age is referenced ( here: if (age >=60) ) it is uninitialized, which contributes to the problems you have described.
Addressing the following will fix the if-else statement for age, and will allow the menu to appear...
Since age is typically a non-float value, i.e. 45 or 50, but never expressed as 45.5.
Suggest replacing, Aoc everywhere it exists with age, (modifying the format specifiers accordingly), and finally, initialize age before use.
Problem 2 is here:
...
{ printf("Select Porperty type\nF=Flat\nL=Land\nH=House\n");
scanf("%f", &Pte);
You are prompting user to input a char value, then attempt to read it in into a float variable Pte. Suggest if desiring to read in as a char, use a " %c" format specifier, and change float Pte to char Pte.
(Note space in format specifier, it is there for this reason.)
{ printf("Select Porperty type\nF=Flat\nL=Land\nH=House\n");
scanf(" %c", &Pte);//note space in front of %c to consume newline
Working code adapted from your original:
void main()
{
char L,F,H;
float CID,Aoc;/*Pte*/
float Cost_per_sqft;
int dicnt,age,ch;
char Pte;
printf("Enter the Client ID\n");
scanf("%f", &CID);
printf("Enter the age of client\n");
scanf("%d", &age);
if (age >=60)
{
printf("The client is eligible for a discount\n");
}
else if (age<60)
{
printf("The client is not eligible for a discount\n");
}
{ printf("Select Porperty type\nF=Flat\nL=Land\nH=House\n");
scanf(" %c", &Pte);
}
printf("Please select the menu option\n");
printf("1.Client ID\n");
printf("2.Property details\n");
printf("3.Exit\n");
scanf("%d", &ch);
switch(ch)
{
case 1:
printf("Client ID %f\n", CID);
printf("Age of client %d", age);
break;
case 2:
;//add content
break;
case 3:
;//add content
break;
}
}

My do while loop is not looping correctly

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

C scanf unsigned long values

I wrote this piece of code, but cases 2 and 3 seem to have a problem. As noted in the title I think it has to do with unsigned long operations, but I can't understand what it is exactly.
*Edited version (scanf changes).
#include <stdio.h>
int main()
{
int pin, inp, count=0;
unsigned dep=100, add, withdraw;
start:;
if (count>0)
{
printf("\n");
}
printf("Please, input your PIN number:");
scanf("%i", &pin);
while (5)
{
if (pin==2014)
{
printf("To view your deposit, press 1.\n");
printf("To add money to your deposit, press 2.\n");
printf("To withdraw money from your deposit, press 3.\n");
printf("To log off, press 4.\n");
scanf("%i", &inp);
switch(inp)
{
case 1:
printf("The remainder of your deposit is %i.\n\n", dep);
break;
case 2:
printf("Enter the amount of money you want to add: ");
scanf("%u", add);
dep+=add;
break;
case 3:
printf("Enter the amount of money you want to withdraw. We would like to remind you that it should be multiple of 20.\n");
scanf("%u", withdraw);
if(((withdraw)%20==0)&&(withdraw<dep))
{
dep-=withdraw;
}
else
{
printf("We are sorry, but you either chose an invalid withdraw amount or you tried to withdrw more money than you have deposited.\n");
}
break;
case 4:
printf("Logging off.\n");
goto end;
break;
}
}
else
{
printf("You entered an invalid PIN.");
count++;
goto start;
}
}
end:;
}
You're not using scanf correctly.
scanf("%lu", add);
For "%lu" it expects a pointer to an unsigned long int, but what you're passing is not a pointer and not an unsigned long int.
Try:
scanf("%u", &add);
Or change add's type.
I'd also recommend checking scanf's returned value.
See: Value returned by scanf function in c

How to make getchar() read a negative number?

I am writing a program that can calculate the areas of a square, cube, and circle. The program needs to present an error message and allow the user to enter a new choice if they enter something not included in the menu. My problem is that if they type anything includes my menu options then the program still executes. (i.e. -1, 23, 344) I was wondering how to get it to ignore anything after the first character or to read the whole string. Or if there is something better than getchar(). I'm open to any solutions! Thank you!
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int choice;
int lengthsq;
int areasq;
int lengthcube;
int areacube;
int radius;
double circlearea;
printf("Area Calculation\n");
printf("(1) Square\n");
printf("(2) Cube\n");
printf("(3) Circle\n");
fputs("Please make a selction: ", stdout);
while((choice = getchar()) != '\n')
switch (choice) {
case '1':
printf("\nPlease enter the length: ");
scanf("%d", &lengthsq);
while(lengthsq <= 0){
printf("Error! Please enter a positive number: ");
scanf("%d", &lengthsq);
}
areasq = lengthsq * lengthsq;
printf("The area of the square is %d.", areasq);
return 0;
case '2':
printf("\nPlease enter the length: ");
scanf("%d", &lengthcube);
while (lengthcube <= 0) {
printf("Error! Please enter a positive number: ");
scanf("%d", &lengthcube);
}
areacube = 6 * lengthcube * lengthcube;
printf("The surface area of the cube is %d.\n", areacube);
return 0;
case '3':
printf("\nPlease enter the radius: ");
scanf("%d", &radius);
while(radius <= 0){
printf("Error! Pleae enter a postive number: ");
scanf("%d", &radius);
}
circlearea = 3.14159 * radius * radius;
printf("The area of the circle is %.2f.\n", circlearea);
return 0;
case '\n':
case '\t':
case ' ':
break;
default:
printf("\nInvalid choice entered.\n");
fputs("Enter a new choice: ", stdout);
break;
}
}
You could add another switch case for the dash, which would toggle some kind of negative flag and then read a number as you're already doing. If you do not like introducing such a flag, then the best option would be using fgets, which returns the entire input line. But that has the downside that you need to parse the input. I.e. do some string manipulation, which may be slightly more complex than a simple flag parameter.
On the other hand, from the code you attached, I deduct that the only valid input consists of mere numbers (integers). You could just read an integer then with scanf.

I cannot seem to loop again after selecting default in switch case in C

hello guys I coded something like kfc menu,and I got it to work(finally),but when I input something other than numbers for "menu",eg:the letter "A", I just can't get it to loop again to normal,instead it finishes the program
#include <stdio.h>
#include <stdlib.h>
int main()
{
char counter='y';
float totalprice=0;
while (counter=='Y' || counter=='y')
{
int menu;
float price=0;
printf("\nplease select from menu:");
scanf (" %i", &menu);
switch(menu)
{
case 1: {
printf("\none hotbox1 =RM10.50");
totalprice=totalprice+10.50;
break;
}
case 2: {
printf ("\none hotbox2=RM10.60");
totalprice=totalprice+10.60;
break;
}
case 3:{
printf ("\none hotbox3=RM10.70");
totalprice=totalprice+10.70;
break;
}
default : {
printf ("\nplease enter proper number please:");
scanf("%2f", &menu);
break;
}
}
printf("\n\nadd order?(Y/N):");
scanf (" %c", &counter);
}
printf("\n\nThe total price is: %f", totalprice);
return 0;
}
You should use fgets() (reference here) first and then sscanf() (reference here), checking it's return value to see if it's a number.
char inputBuffer[MAX_BUFFER];
do
{
fgets(inputBuffer, MAX_BUFFER, stdin);
}
while(sscanf(inputBuffer, "%d", &menu) != 1)
You scanf with %f in the default case, I am fairly certain that is for floats. Use %d.
Remove scanf("%2f", &menu);
Switch in C does not support char in switch-case. Before you start switch-case validate the user input. If it is a number go into switch case otherwise display a user message to enter only numeric value
I recommend that you debug this by printing out the value of "counter" at various points in the loop (i.e. after you read it in, at the bottom of the loop, etc.). This will give you visibility into what your code is doing.
You can try something like this
#include <stdio.h>
int main()
{
char counter;
float totalprice=0;
int menu=0;
do
{
printf("\n1. one hotbox1=RM10.50");
printf("\n2. one hotbox2=RM10.60");
printf("\n3. one hotbox3=RM10.70");
printf("\nplease select from menu:");
scanf ("%d", &menu);
switch(menu)
{
case 1:
printf("\none hotbox1 =RM10.50");
totalprice=totalprice+10.50;
break;
case 2:
printf ("\none hotbox2=RM10.60");
totalprice=totalprice+10.60;
break;
case 3:
printf ("\none hotbox3=RM10.70");
totalprice=totalprice+10.70;
break;
default :
printf ("\nplease enter proper number please:");
scanf("%d", &menu);
}
printf("\n\nadd more order?(Y/N):");
fflush(stdin); //to empty the input stream.
scanf("%c",&counter);
}while(tolower(counter) != 'n'); //tolower returns the lowercase character.
printf("\n\nThe total price is: %.2f", totalprice);
return 0;
}
When scanf("%i", &menu) tries to read an integer from the input, it finds A, which it cannot interpret as a number, so it does not read it(*). Then the next scanf continues reading the input from when the other left off and happily reads the letter 'A'. Since you loop as long as the read letter is either 'y' or 'Y' (which A is neither), it exits the loop.
(*) read up on the documentation of scanf to see how to tell if it encountered an error.
Note: scanf("%i", &menu) should be scanf("%d", &menu) as%d` is the formatting symbol for integers.
One solution would be to change the loop condition to:
while (counter!='N' && counter!='n')
{
...
}
This way you end the loop only if an explicit 'N' or 'n' is inputted.
Note: it won't help if you accidentally type 'n' for the menu item, so see the comment about the error handling above.

Resources