-4

UPDATED CODE

Why does the input 12 works? It interprets 12 as option 1 and takes 2 for the first scanf of case'1'? I do not want to use int opcao as if I enter a leter it will run indefinitly.

I want that the user can only exit the program when he chooses option exit (one of the cases) thus the do... while.If the user enters an invalid character or leter or whatever the menu shows again and shows the default message. I also want that after the chosen case is executed, it presents the menu again for a new choice thus i am using an always valid condition of 1=1 on the while. I can't use integers as if you enter a leter the program goes bonkers a.k.a never stops running. just try it.

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);
Alberto Coletta
  • 1,563
  • 2
  • 15
  • 24
lmba
  • 9
  • 1
  • 1
  • 6
  • Use `opcao = getch()` instead of `scanf(" %c",&opcao)`. – barak manos Oct 24 '14 at 15:27
  • `while(opcao!=1 || opcao!=2 || opcao!=3 || opcao!=4 || opcao!=5 || opcao!=6 && opcao>=1 && opcao<=6);` condition is always true. – BLUEPIXY Oct 24 '14 at 15:28
  • In any case, you've got to make up your mind whether you want to use an `int opcao` or a `char opcao`. – barak manos Oct 24 '14 at 15:29
  • When demonstrating a problem, always make sure your example obeys the "Minimal" in ["Minimal, Complete, Verifiable Example"](http://stackoverflow.com/help/mcve). That means *shortest code* to demonstrate the confusion. Clearly cases 2 through 6 are not needed (and have no code) so those could be cut. But you also have many more scanf calls in case 1 than are needed to demonstrate the concern. Please remember also you can edit your posts to make them more concise and informative with the "EDIT" button. – HostileFork says dont trust SE Oct 24 '14 at 15:30
  • In the `while` do you really mean `while((opcao != '1')||(opcao != '1') ...`? The values you test in teh switch are ASCII '1', which = 0x31 or 49 (decimal). – Evil Dog Pie Oct 24 '14 at 16:44

3 Answers3

0

That's because you're reading your input with a single %c.

This way, the first character of 12 (1) is used by the switch, while the second is used by the scanf of case '1':.

To avoid this behaviour, you can read the options as integers and use the placeholder %d in your very first scanf.


EDIT:

To avoid your infinte loop problem, you can do like this:

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

What I've done is the following:

  • Check the scanf output if it reads the input correctly (in this specific case, if the input was a number it returned a number different from 0).
  • Use the function clean_stdin (Credits) to clean characters that scanf read but didn't consumed (it expects a number and you give it a character, so the character stays in stdin and create the infinite loop)
  • I use a flag to control the loop condition, when the exit option is chosen, flag value is changed to a value that makes the condition fail
  • I added the main() because I need it to run the program; you can incorporate what's inside in your main. Remember to copy clean_stdin() function.

I suggest you to read some scanf documentation to understand its return value.

I suggest also to read about scanf alternatives, since it's a boring function: link 1 and link2.

Remember to format your code with the right indentation, it's a best practice.

Community
  • 1
  • 1
Alberto Coletta
  • 1,563
  • 2
  • 15
  • 24
0

That's how scanf works.

You asked scanf to read a single character from the input stream. The input stream originally contained 12 sequence (more likely, 12<newline> sequence). So, just like you asked it to, scanf consumed that first 1, leaving the rest in the input stream.

The next scanf continued to consume the input stream where the previous one left off.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
0

scanf with the %c can read one character at once. '12' contains two characters '1' and '2'. So '1' will be consumed firstly by the scanf and hence,case '1': gets executed. The '2' is left in the input buffer(stdin) and it will be consumed by the next scanf with a %c.

To avoid this,you could declare opcao as an integer and use the following code:

    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
Spikatrix
  • 20,225
  • 7
  • 37
  • 83