【问题标题】:Detecting Enter within a switch case in C?在C中的开关盒中检测Enter?
【发布时间】:2019-10-26 21:13:16
【问题描述】:

在这方面遇到的麻烦比我应该的要多。我正在构建一个非常简单的银行菜单界面,用户可以在其中查看余额、存款、取款或退出菜单。 case 1case2case3 似乎工作正常,但无论我在 Google 上尝试什么,case 4 都无法正常工作。

在当前版本中,case 4 中的 printf() 语句出现,然后似乎没有其他任何事情发生,直到我输入其他选项之一 (1 - 3) 两次,此时循环将自动循环使用第二个输入。我尝试了getchar(),但这似乎不起作用(或者我没有正确实现它)。

为什么会出现这种行为,我该如何解决?

代码如下:

#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;
}

【问题讨论】:

  • 您不能使用%d 格式来读取通用字符。尤其不是任何空格字符(换行符是空格字符),因为%d 格式scanf 函数将跳过(并忽略)前导空格字符。
  • 你需要学习如何检查scanf的返回值来检测错误。
  • @Someprogrammerdude 抱歉,C 新手,你有什么建议?

标签: c switch-statement cs50 enter


【解决方案1】:

假设我想粉刷我家的外部。我买了油漆,然后回到我家(从最近的商店开车 5 小时)。当我回到家时,我意识到我忘了买一个画笔。我不想在接下来的 10 个小时里开车去拿油漆刷,但我应该怎么涂油漆呢?

我可以使用扫帚、拖把、抹布、我的手、我儿子的手等等,没有一个比刷子更可取。但后来我意识到……我有一匹马!我剪下马的主要部分并制作自己的画笔!我为这一天作画,下周当我需要另一支刷子时,我会再次给我的马剪毛。这最终比 10 小时车程便宜很多。

好吧...这是一个老生常谈的虚构故事。关键是使用 scanf() 进行用户输入就像用猪鼻子作画。这只是工作的错误工具。最好编写您自己的用户输入函数,该函数按您期望的方式工作。

考虑下面的 GetInput() 函数。我必须自己做,但它肯定比使用 scanf() 进行用户输入要好:

  #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;
  }

【讨论】:

  • 很遗憾scanf()是老师教的,所以还是有些期待的。也许我会在最后一种情况下跳过它。但是,我想学习:你能向我解释一下这个新功能吗?看起来您的函数将地址传递给变量(取决于您所处的情况)。我不明白顶部以char *line_Agetline() 函数开头的三行是怎么回事。然后,如果相关指针不是NULL,它会交换地址处的值。为什么if(charOut)= 的两边都有一个*
  • lineSize 初始化为 0 时如何工作?另外,如果你不使用malloc(),为什么还需要free(line_A)
  • @dylosaur, getline() 根据需要分配内存来保存用户输入的所有字符(参见手册页)。 lineSize 保存分配给line_A的内存大小,这里调用get line()时为0字节。它工作正常。如果您对 get line() 有其他疑问,请随时将其发布到 Stack Overflow。
  • @dylosaur,我在代码中添加了一些关于您有疑问的项目的 cmets。
  • 据我了解,由于*line_A 设置为NULLlineSize 设置为0getline() 将根据需要分配缓冲区,只要内存可用?还有一个问题:为什么atoi(line_A) 可以正常工作,但*charOut = *line_A 需要*
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多