为什么这个无效输入仍然有效? (切换案例)char错误

时间:2014-10-24 15:23:26

标签: c switch-statement

更新代码

为什么输入12有效?它将12解释为选项1,并在案例的第一次扫描中取2作为' 1&#39 ;?我不想使用int opcao,好像我输入了一个无限期运行的内容。

我希望用户只能在选择退出选项时退出程序(其中一个案例),因此do ... while。如果用户输入无效字符或者leter或者菜单再显示的内容,则显示默认消息。我还希望在执行所选案例之后,它再次显示菜单以进行新选择,因此我在while时使用1 = 1的始终有效条件。我不能使用整数,好像你进入了一个程序去疯子a.k.a永远不会停止运行。试试吧。

char opcao;



do {
    menu();
    scanf(" %c",&opcao);

    switch(opcao) {
      case '1':
    printf("Massa do módulo (sem combustível):\n");
    scanf("%f",&m_modulo);
    printf("Massa de combustível:\n");
    scanf("%f",&m_combustivel);
    printf("Altitude no início da alunagem em relação a um ponto de referência:\n");
    break;
      case '2':

    break;
      case '3':
    printf("Funcionalidade nao disponivel.\n");
    break;
      case '4':
    printf("Funcionalidade nao disponivel.\n");
    break;
      case '5':
    printf("Funcionalidade nao disponivel.\n");
    break;
      case '6':
    exit(0);
    break;
      default:
    printf("Opcao invalida, as seguintes opcoes estao disponiveis:\n");
    break;
    }
  }
while(1==1);

3 个答案:

答案 0 :(得分:0)

那是因为你用一个%c来阅读你的输入。

这样,交换机使用12(1)的第一个字符,而case '1':的scanf使用第二个字符。

要避免此行为,您可以将选项作为整数阅读,并在第一个%d中使用占位符scanf


修改

为了避免你的infinte循环问题,你可以这样做:

#include <stdio.h>

void clean_stdin();

int main() {
  int opcao;
  float m_modulo, m_combustivel;
  int flag = 0;

  do {
      printf("Make a choice: ");
      if (scanf("%d", &opcao) == 0) {
        clean_stdin();
      }
      else {
          switch(opcao) {
            case 1:
                    printf("Massa do módulo (sem combustível): ");
                    scanf("%f", &m_modulo);
                    printf("Massa de combustível: ");
                    scanf("%f", &m_combustivel);
                    printf("Altitude no início da alunagem em relação a um ponto de referência.\n");
                    break;
            case 2:

                    break;
            case 3:
                    printf("Funcionalidade nao disponivel.\n");
                     break;
            case 4:
                    printf("Funcionalidade nao disponivel.\n");
                     break;
            case 5:
                    printf("Funcionalidade nao disponivel.\n");
                    break;
            case 6:
                    flag = 1;
                    break;
            default:
                    printf("Opcao invalida, as seguintes opcoes estao disponiveis:\n");
          }
      }

  } while(flag == 0);
}

void clean_stdin()
{
    int c;
    do {
        c = getchar();
    } while (c != '\n' && c != EOF);
}

我所做的是以下内容:

  • 检查scanf输出是否正确读取输入(在这种特定情况下,如果输入是一个数字,则返回的数字不同于0)。
  • 使用函数clean_stdinCredits)清除scanf读取但未消耗的字符(它需要一个数字并给它一个字符,因此字符保留在stdin中并创建无限循环)
  • 我使用标志来控制循环条件,当选择退出选项时,标志值更改为使条件失败的值
  • 我添加了main()因为我需要它来运行程序;你可以在main中加入内部的内容。请记住复制clean_stdin()功能。

我建议您阅读一些scanf documentation以了解其返回值。

我建议您阅读有关scanf替代方案的内容,因为这是一项无聊的功能:link 1link2

请记住使用正确的缩进格式化代码,这是最佳做法。

答案 1 :(得分:0)

scanf的工作原理。

您要求scanf从输入流中读取单个字符。输入流最初包含12序列(更可能是12<newline>序列)。所以,就像你问的那样,scanf消耗了第一个1,剩下的就留在了输入流中。

下一个scanf继续消耗前一个输入流的输入流。

答案 2 :(得分:0)

scanf

%c可以同时读取一个字符。 &#39; 12&#39;包含两个字符&#39; 1&#39;和&#39; 2&#39;。所以&#39; 1&#39;将由scanf首先消耗,因此case '1':被执行。 &#39; 2&#39;保留在输入缓冲区(stdin)中,下一个scanf将使用%c消费。

为避免这种情况,您可以将opcao声明为整数并使用以下代码:

    while(1)
     {
              if(scanf("%d",&opcao)==0)
              {
              printf("Invalid input. Try again:");
              scanf("%*s"); //remove the invalid input
              continue;
              }
              if(opcao>0 && opcao<7)
              break;
              else
              printf("invalid integer. Try again:");
     }
    switch(opcao) {
      case 1://your code
    break;
      case 2://your code
    break;
      case 3://your code
    break;
       // etc...
       case 6:exit(0);
             }
  //no need of do...while or a default case