用户将输入与每个操作相对应的整数。当输入动作时,执行相关功能(请参阅下文)。这些操作将对用户进行操作当前余额,改变其价值。请注意,每次操作完成后,主菜单为再次显示(循环),直到用户在主菜单上输入4退出。
有人能在不使用全局变量的情况下,在C:中帮助进行提款和存款操作,然后在使用新余额后显示在当前余额上吗
#include <stdio.h>
#include <stdlib.h>
int checkBalance(int balance);
int withdraw(int balance, int amountWithdraw);
int deposit(int balance, int amountDeposit);
int main()
{
int balance = 10;
int menuChoice;
do{
printf("1) Withdrawn");
printf("2) Depositn");
printf("3) CheckBalancen");
printf("4) Quitn");
printf("Select an option: ");
scanf("%d", &menuChoice);
switch(menuChoice){
case(1):
checkBalance(balance);
withdraw(balance, withdraw);
checkBalance(balance);
break;
case(2):
checkBalance(balance);
deposit(balance, deposit);
checkBalance(balance);
break;
case(3):
checkBalance(balance);
printf("n");
}
}while(menuChoice!=4);
checkBalance(balance);
return 0;
}
int withdraw(int balance, int amountWithdraw){
//int amountWithdraw;
balance = 10;
printf("What is the amount of your withdraw: n");
scanf("%d", &amountWithdraw);
balance - amountWithdraw;
}
int deposit(int balance, int amountDeposit){
//int amountDeposit;
balance = 10;
printf("What is the amount of ur deposit: n");
scanf("%d", &amountDeposit);
balance + amountDeposit;
}
int checkBalance(int balance){
balance = 10;
printf("Your current balance is: %dn", balance);
}
Tom,很明显,您正在努力确定如何确定代码的各个部分需要做什么,以及如何组织它们。这很正常,这是学习的一部分。这些年来,我注意到,这通常是在你用纸和铅笔完成逻辑运算之前拿起键盘的结果。
成功完成任何旅程的关键是在出门前知道自己要去哪里。编写任何单独的程序都只是另一段旅程。
据我所知,要完成一个简单的整数银行余额程序,需要将四个函数组合在一起。在你拿起键盘之前,你应该知道你想让每个人做什么。从你的账户余额balance
开始。这将在main()
中声明。任何需要平衡的函数都需要将balance
作为参数传递。在C中,所有参数都是通过值传递的,这意味着函数接收自己的变量副本。当函数返回时,对该变量的任何操作都将丢失。
为了对参数进行任何修改以返回调用函数(此处为main()
),您需要return
修改后的值。这样,对于balance
,main()
中的帐户balance
可以通过任何更改进行更新。(您也可以传递一个指向变量的指针,并更新该地址的值,这将在getint()
函数中看到,但对于您的情况,只有return
更改的值)
当考虑函数应该做什么时,这也意味着为函数选择一个合适的返回类型。任何可以成功或失败的函数(如输入函数)都必须有一种向调用者指示成功/失败的方式。任何修改和返回值的函数都需要返回正确的类型。如果函数对代码的继续操作没有影响(就像打印数据的简单函数一样),那么void
是正确的选择。
当查看函数的操作时,checkBalance()
函数只打印用户的余额。它不返回任何内容,所以void
类型是可以的。剩下的两个函数deposit()
和withdraw()
都修改了作为参数传递的balanc
,因此它们都必须返回更新后的银行余额。在上面的代码中,int
是正确的返回类型。
最后,您希望将程序接口与程序实现分离。程序界面是与用户交互、显示提示、获取输入和输出数据的部分。您的程序实现是对程序数据、计算等的处理。这意味着对于deposit()
或withdraw()
函数,您不希望在那里生成输出。考虑不是在终端上显示文本,而是在X的窗口中更新GUI表单。如果余额应该显示在图形文本框中,则不希望deposit()
或withdraw()
向stdout
喷出一堆文本。
总会有一些重叠,一些函数总是需要重写,但尽可能地,尽量将接口和实现分开。这样,在哪里调用deposit()
或return()
并不重要。如果他们只是返回更新后的余额,他们将在任何环境中工作。
经过一些笔和纸的时间后,checkBalance()
所需要做的就是输出作为参数的电流平衡。它不会修改任何内容,因此使用void
类型。CCD_ 27需要检查以确保在将帐户减少CCD_ 29之前CCD_。使用deposit()
,只需将amountDeposit
添加到当前的balance
中,然后返回更新后的金额。有了这些变化,你的功能,在合理的程度上清除了接口可能是:
int withdraw (int balance, int amountWithdraw)
{
if (balance > amountWithdraw) /* validate money available */
return balance - amountWithdraw; /* return updated balance */
puts (" error: insuffient funds"); /* otherwise notify user */
return balance; /* return balance unchanged */
}
int deposit(int balance, int amountDeposit)
{
return balance + amountDeposit;
}
void checkBalance (int balance)
{
printf ("nYour current balance is: %dn", balance);
}
如果您注意到上面的内容,就不会有任何与函数相关联的用户输入。在调用函数之前,您可以处理所有输入以获得amountDeposit
或amountWithdraw
。
现在,您已经选择scanf()
作为输入。无论您使用的是什么输入函数,除非检查返回以确定输入是成功还是失败,否则都无法正确使用它。如果未能检查返回并盲目使用变量,则可能会在输入失败的地方调用Undefined Behavior。(例如用户按下'r'
而不是'4'
,这将使您的程序进入无限循环)。虽然可以使用scanf()
,但它提供了一个脆弱的输入例程(除非在每次输入后正确清空stdin
)。
在C中进行输入的推荐方法是使用函数fgets()
或POSIXgetline()
一次读取一行,将输入读取到fgets()
的足够大小的字符数组中(getline()
可以自动为您分配存储空间)。这样,无论输入是否正确,整行都会被消耗掉,并且stdin
中的任何无效字符都不会未读,只是在等待下一次尝试。若要单独使用scanf()
,必须在每次调用后手动清空stdin
(除非scanf()
返回EOF
)。你可以用一个简单的助手功能来做到这一点,例如
void empty_stdin (void)
{
int c = getchar(); /* read 1st char from stdin */
while (c != 'n' && c != EOF) /* if not n or EOF */
c = getchar(); /* repeat until it is */
}
由于您只读取代码中的整数值,因此最好有一个简单的函数来处理显示提示,然后读取和验证输入,并在需要时调用empty_stdin()
。一个简单的getint()
函数可以写成:
int getint (int *value, const char *prompt)
{
for (;;) { /* loop continually until good input or canceled */
int rtn; /* var for return from scanf */
fputs (prompt, stdout); /* display prompt */
rtn = scanf ("%d", value); /* read int, save return */
empty_stdin(); /* empty input buffer */
if (rtn == EOF) { /* user generated manual EOF */
puts ("(user canceled input)");
return 0;
}
else if (rtn == 1) /* good input, break read loop */
break;
/* otherwise matching failure */
fputs (" error: invalid integer input.n", stderr);
}
return 1; /* return success */
}
这大大简化了代码的主体,并将接口与实现分离开来。然后,您的主程序循环只需要进行一些小的更改就可以处理输出到的内容,无论是窗口中的窗体还是终端。利用上面的helper函数,您可以编写简化的main()
,如下面的完整示例所示:
#include <stdio.h>
#include <stdlib.h>
/** account related funcitons */
void checkBalance (int balance);
int withdraw (int balance, int amountWithdraw);
int deposit (int balance, int amountDeposit);
/** helper functions */
void empty_stdin (void);
int getint (int *value, const char *prompt);
int main (void)
{
int amount = 0,
balance = 10,
menuChoice = 0;
for (;;) { /* loop continually displaying menu and handling input until quit */
/* use common getint() function to handle all user-input, validate return */
if (!getint (&menuChoice, "n 1) Withdrawn"
" 2) Depositn"
" 3) CheckBalancen"
" 4) Quitnn"
"Select an option: ")) {
puts ("(user canceled input)");
return 0;
}
switch (menuChoice) { /* switch on choice */
case 1:
if (!getint (&amount, "namount to withdraw: "))
goto canceled;
balance = withdraw (balance, amount);
checkBalance (balance);
break;
case 2:
if (!getint (&amount, "namount to deposit: "))
goto canceled;
balance = deposit (balance, amount);
checkBalance (balance);
break;
case 3:
checkBalance (balance);
break;
case 4:
goto done;
break;
default:
fputs (" error: invalid menu selection.n", stderr);
break;
}
canceled:;
}
done:;
checkBalance(balance);
return 0;
}
int withdraw (int balance, int amountWithdraw)
{
if (balance > amountWithdraw) /* validate money available */
return balance - amountWithdraw; /* return updated balance */
puts (" error: insuffient funds"); /* otherwise notify user */
return balance; /* return balance unchanged */
}
int deposit(int balance, int amountDeposit)
{
return balance + amountDeposit;
}
void checkBalance (int balance)
{
printf ("nYour current balance is: %dn", balance);
}
void empty_stdin (void)
{
int c = getchar(); /* read 1st char from stdin */
while (c != 'n' && c != EOF) /* if not n or EOF */
c = getchar(); /* repeat until it is */
}
int getint (int *value, const char *prompt)
{
for (;;) { /* loop continually until good input or canceled */
int rtn; /* var for return from scanf */
fputs (prompt, stdout); /* display prompt */
rtn = scanf ("%d", value); /* read int, save return */
empty_stdin(); /* empty input buffer */
if (rtn == EOF) { /* user generated manual EOF */
puts ("(user canceled input)");
return 0;
}
else if (rtn == 1) /* good input, break read loop */
break;
/* otherwise matching failure */
fputs (" error: invalid integer input.n", stderr);
}
return 1; /* return success */
}
示例使用/输出
任何时候你写任何类型的输入例程,都要尝试并打破它。你需要尝试并思考你的用户输入无效数据的任何方式,并确保你的代码正确处理了这一点。当你发现一些东西不起作用,或者溜走了,去修复它,然后再试一次。事实上,你编写的输入例程中断并不是失败,它只是显示了哪里需要额外的工作。唯一的失败将来自于未能彻底检查它
如果下面有故意无效的输入,你会得到:
$ ./bin/bankbalance
1) Withdraw
2) Deposit
3) CheckBalance
4) Quit
Select an option: 3
Your current balance is: 10
1) Withdraw
2) Deposit
3) CheckBalance
4) Quit
Select an option: I want to Deposit money
error: invalid integer input.
1) Withdraw
2) Deposit
3) CheckBalance
4) Quit
Select an option: 2
amount to deposit: 10
Your current balance is: 20
1) Withdraw
2) Deposit
3) CheckBalance
4) Quit
Select an option: 1
amount to withdraw: 5
Your current balance is: 15
1) Withdraw
2) Deposit
3) CheckBalance
4) Quit
Select an option: 1
amount to withdraw: 20
error: insuffient funds
Your current balance is: 15
1) Withdraw
2) Deposit
3) CheckBalance
4) Quit
Select an option: 9000000 and a lot more
error: invalid menu selection.
1) Withdraw
2) Deposit
3) CheckBalance
4) Quit
Select an option: 4
Your current balance is: 15
仔细看看,如果你还有问题,请告诉我。