如何在不使用C中的全局变量的情况下使操作正常工作



用户将输入与每个操作相对应的整数。当输入动作时,执行相关功能(请参阅下文)。这些操作将对用户进行操作当前余额,改变其价值。请注意,每次操作完成后,主菜单为再次显示(循环),直到用户在主菜单上输入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修改后的值。这样,对于balancemain()中的帐户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);
}

如果您注意到上面的内容,就不会有任何与函数相关联的用户输入。在调用函数之前,您可以处理所有输入以获得amountDepositamountWithdraw

现在,您已经选择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

仔细看看,如果你还有问题,请告诉我。

最新更新