【问题标题】:Function(s) are being improperly executed/repeated within a switch statement. Rest of code doesn't execute函数在 switch 语句中被不正确地执行/重复。其余代码不执行
【发布时间】:2016-08-25 01:09:23
【问题描述】:

到目前为止,main() 执行良好,while 循环执行良好。如果我输入了错误的 PIN,程序执行会立即停止。否则,程序将继续执行其余部分。

我决定测试一个函数transfer(),这就是我遇到问题的地方。传递函数仅对 printf 语句正确执行。程序没有等待我输入要在哪个帐户上进行转账,而是跳回到transfer()的开头并不断重复……

transfer() 中的 switch 语句甚至没有执行!为什么?

//This program will mimick an ATM machine
//It will do deposits, withdrawals, and authentication

//Function Declarations
//float withdrawal();
//float deposit();
float transfer ();
void decision ();

float checking = 15050.00;
float savings = 8200.83;

#include <stdio.h>

int main ()
{
    int PIN;
    printf ("Welcome to Wells Fargo 24HR Teller!\n");
    printf ("Enter Your 4-Digit PIN \n");
    scanf ("%d", &PIN);

    while (PIN == 2016) {
        decision ();            //this starts the ATM choices user can select
    }
    if (PIN != 2016) {
        printf ("AUTHENTICATION FAILED");
    }
    return 0;
}

void decision ()
{

    printf ("I want to:\n");
    printf ("A) Make a Transfer\n");
    //printf("B) Make a Deposit\n");
    //printf("C) Make a Withdrawal\n");
    //printf("D) Exit\n");

    char selection;
    scanf ("%c", &selection);

    switch (selection) {
    case 'A':
        transfer ();
        //case 'B':  deposit();
        //case 'C':  withdrawal();
        //case 'D': break;
    }
}

float transfer ()
{
    float transamt;
    float chekbal;
    float savbal;
    printf ("Transfer Amount? \n");
    scanf ("%f", &transamt);
    printf ("\n Transfer Amount of %f", transamt);


    printf ("\n Which Account? \n");
    printf (" A) Checking \n");
    printf (" B) Savings \n");

    /*Right after this point, execution goes back to beginning of decision()
    program execution doesn't go through switch statement */
    char confirm;
    scanf ("%c", &confirm);

    switch (confirm) {
    case 'A':
        chekbal = (transamt + checking);
        printf ("Checking Balance is Now %f", chekbal);
        break;

    case 'B':
        savbal = (transamt + savings);
        printf ("Savings Balance is Now %f", savbal);
        break;
    }

    return 0;
}

【问题讨论】:

  • 请创建一个minimal reproducible example。减少代码将帮助您确定大多数问题的罪魁祸首。请务必在提问时标记您的编程语言,并确保在发布之前正确格式化您的代码。
  • 用scanf打印你读到的字符,你就会明白为什么了。
  • 好吧,在main 中的if 语句之后有一个return 0;,如果PIN 是正确的,则调用函数,如果不是,则执行if 中的printf 并函数return0.
  • 我的水晶球说用scanf读取浮点数后,输入缓冲区中会留下一个新行并由字符scanf读取。
  • 您需要在%c 之前使用带有空格的" %c",以便在读取PIN 时将换行符留在缓冲区中后跳过空格(换行符等)。等等。在switch 中的操作之后,您缺少break 语句,因此在您期望它只执行一个的地方执行了许多函数。

标签: c function loops switch-statement


【解决方案1】:

问题是带有%c 转换说明符的scanf 不消耗空格,请参阅here

除 [、c 和 n 之外的所有转换说明符都会消耗并丢弃所有前导空白字符

输入转账金额后按回车键会在标准输入中插入一个换行符,scanf("%c", &amp;confirm) 然后看到并存储在confirm 中,即confirm 现在包含一个换行符。要明确地看到这一点,请尝试将 case '\n': 添加到 switch(confirm) 语句;您会看到 switch 语句实际上正在执行,只是 confirm 的值与您之前的任何情况都不匹配。最好始终在 switch 语句中添加 default: 标签以捕获任何意外值。

解决方案很简单,你只需要在格式字符串中%c之前添加任何空白字符,因为(来自上述相同来源),

格式字符串中的任何单个空白字符都会消耗输入中所有可用的连续空白字符

因此,scanf(" %c", &amp;confirm); 在读取将分配给confirm 的字符之前,将首先删除标准输入中的所有空格(在我们的例子中是剩余的换行符)。

【讨论】:

  • 我虽然默认更多的是个人选择。但如果它有效,我会尝试它。你能解释一下break和default的目的吗?我是 C 新手。
【解决方案2】:

你缓冲存储了\n,如果你把300A放在"transfer Amount?"后面就可以看到了他们“工作”。

一个快速而肮脏的解决方案:在 scanf 之后放置一个 getchar(),这会“获取”新行。

//This program will mimick an ATM machine
//It will do deposits, withdrawals, and authentication

//Function Declarations
//float withdrawal();
//float deposit();
float transfer ();
void decision ();

float checking = 15050.00;
float savings = 8200.83;

#include <stdio.h>

int main ()
{
    int PIN;
    printf ("Welcome to Wells Fargo 24HR Teller!\n");
    printf ("Enter Your 4-Digit PIN \n");
    scanf ("%d", &PIN);

    while (PIN == 2016) {
        decision ();            //this starts the ATM choices user can select
    }
    if (PIN != 2016) {
        printf ("AUTHENTICATION FAILED");
    }
    return 0;
}

void decision ()
{

    printf ("I want to:\n");
    printf ("A) Make a Transfer\n");
    //printf("B) Make a Deposit\n");
    //printf("C) Make a Withdrawal\n");
    //printf("D) Exit\n");

    char selection;
    scanf ("%c", &selection);

    switch (selection) {
    case 'A':
        transfer ();
        //case 'B':  deposit();
        //case 'C':  withdrawal();
        //case 'D': break;
    }
}

float transfer ()
{
    float transamt;
    float chekbal;
    float savbal;
    printf ("Transfer Amount? \n");
    scanf ("%f", &transamt);
    // THIS GETCHAR
    getchar();
    printf ("\n Transfer Amount of %f", transamt);


    printf ("\n Which Account? \n");
    printf (" A) Checking \n");
    printf (" B) Savings \n");

    /*Right after this point, execution goes back to beginning of decision()
    program execution doesn't go through switch statement */
    char confirm;
    scanf ("%c", &confirm);
    // THIS GETCHAR
    getchar();
    switch (confirm) {
    case 'A':
        chekbal = (transamt + checking);
        printf ("Checking Balance is Now %f", chekbal);
        break;

    case 'B':
        savbal = (transamt + savings);
        printf ("Savings Balance is Now %f", savbal);
        break;
    }

    return 0;
}

【讨论】:

    【解决方案3】:

    发布代码的一个主要问题(以及为什么它不断循环)是以下代码块

    while (PIN == 2016) 
    {
        decision ();            //this starts the ATM choices user can select
    }
    

    这导致代码永远不会退出,即使用户输入D

    建议将用户输入的菜单值传递回调用decision() 的位置,以便代码可以在必要时使用该值退出

    一些小问题是:

    scanf() 的调用没有检查返回值以确保操作成功

    switch() 语句缺少 default: 案例以(例如)处理任何无效输入

    当使用%c 格式说明符调用scanf() 时,请在%c 之前放置一个空格,这样所有空格都会被占用而不是被放置在关联的变量中

    transfer()的返回值需要是float,建议返回0.0f

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-26
      • 1970-01-01
      • 2021-11-05
      相关资源
      最近更新 更多