Program entering the default case of switch statement always

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Phoe6

    Program entering the default case of switch statement always

    The Program Fragment is this:

    int choice; /* Users Input Command */
    ..
    ..
    ..
    printf("Enter a command: ");
    fflush(stdin);
    choice = getc(stdin);
    printf("\n");
    ..
    ..
    ..
    while(choice!=' Q')
    {
    switch(choice)
    {
    /* Movement options */
    case 'n':
    dx = 0;
    dy = -1;
    action = 1;
    break;
    case 's':
    ..
    ..
    ..
    ..
    ..
    default:
    printf("You cannot do that!\n");
    action = 0;
    break;

    }

    ..
    ..
    ..
    printf("Enter a Command :");
    fflush(stdin);
    choice = getc(stdin);
    printf("\n");

    } /* <- End Brace of while loop */


    The Problem I am observing is the Default Section of the Switch command
    is being entering all the times (except for the first time).

    I am guessing that the choice variable is getting someother value which
    is causing it to enter the default; but using
    getchar,getc(st din),fgetc(stdi n) and flushing the stdin is not solving
    the problem.

    ---
    The Complete Source (with the bug) is here:
    Latest news coverage, email, free stock quotes, live scores and video are just the beginning. Discover more every day at Yahoo!

    'Hunt the Wumpus' Game.
    You can see the problem, when compiled and executed(on Linux,gcc)


    Regards,
    Senthil

  • Phoe6

    #2
    Re: Program entering the default case of switch statement always

    The smallest example which I can give to express the the problem I am
    facing is here:

    #include<stdio. h>

    int main(void)
    {
    int choice;

    choice=getc(std in);

    while(choice='Q ')
    {
    switch(choice)
    {
    case 'n':
    putchar('n');
    break;
    case 's':
    putchar('s');
    break;
    case 'N':
    putchar('N');
    break;
    case 'S':
    putchar('S');
    break;
    default:
    putchar('%');
    break;
    }
    choice=getc(std in);
    }
    putchar('Q');

    return 0;

    }

    The Output is always %%; which means that it is entering the default
    section no matter what.

    Comment

    • Walter Roberson

      #3
      Re: Program entering the default case of switch statement always

      In article <1109530173.660 994.217400@g14g 2000cwa.googleg roups.com>,
      Phoe6 <orsenthil@gmai l.com> wrote:
      :The Problem I am observing is the Default Section of the Switch command
      :is being entering all the times (except for the first time).

      :The Complete Source (with the bug) is here:
      :http://geocities.com/uthcode2/wumpus.c
      :'Hunt the Wumpus' Game.
      :You can see the problem, when compiled and executed(on Linux,gcc)

      The problem does not occur when I compile on IRIX with SGI's
      compiler or with gcc.

      I do find a bug in the code: shooting south should have
      a dy of +1 instead of -1. And of course, having debug set to 1
      makes for a pretty uninteresting game.
      --
      When your posts are all alone / and a user's on the phone/
      there's one place to check -- / Upstream!
      When you're in a hurry / and propagation is a worry/
      there's a place you can post -- / Upstream!

      Comment

      • Walter Roberson

        #4
        Re: Program entering the default case of switch statement always

        In article <1109533031.347 928.166950@g14g 2000cwa.googleg roups.com>,
        Phoe6 <orsenthil@gmai l.com> wrote:
        : The smallest example which I can give to express the the problem I am
        :facing is here:

        : while(choice='Q ')

        That's an assignment statement, so you are clobbering choice with
        the value 'Q' and then testing whether that is non-zero (which
        of course it is). 'Q' is not one of the cases listed so it is going
        to use the default tag.

        The code you pointed to had while(choice!=' Q') which tests
        choice's value instead of setting it.
        --
        What is "The Ultimate Meme"? Would it, like Monty Python's
        "The World's Funniest Joke", lead to the deaths of everyone who
        encountered it? Ideas *have* lead to the destruction of entire cultures.
        -- A Child's Garden Of Memes

        Comment

        • Phoe6

          #5
          Re: Program entering the default case of switch statement always

          >The problem does not occur when I compile on IRIX with SGI's[color=blue]
          >compiler or with gcc.[/color]

          You mean you don not see:

          Enter a Command :
          You cannot do that!

          In the output neccessarily! Thats strange and interesting. Thats what
          my whole problem is about
          [color=blue]
          >I do find a bug in the code: shooting south should have
          >a dy of +1 instead of -1.[/color]

          Thanks, I have corrected it.

          Comment

          • Phoe6

            #6
            Re: Program entering the default case of switch statement always

            Thanks a lot.
            I corrected it to while(choice!=' Q')

            but still the output is:
            [machine@26Feb]# ./a.out
            n
            n%S
            S%S
            S%N
            N%S
            S%N
            N%

            The '%' things which are coming up.(which is the original bug)

            -Senthil

            Comment

            • infobahn

              #7
              Re: Program entering the default case of switch statement always

              Phoe6 wrote:[color=blue]
              >
              > The Program Fragment is this:
              >
              > int choice; /* Users Input Command */
              > .
              > .
              > .
              > printf("Enter a command: ");
              > fflush(stdin);[/color]

              Undefined behaviour. fflush's functionality is defined only for
              streams open for output or update.
              [color=blue]
              > choice = getc(stdin);[/color]

              Program may block for input before displaying prompt.
              [color=blue]
              > printf("\n");
              > .
              > .
              > .
              > while(choice!=' Q')
              > {
              > switch(choice)
              > {
              > /* Movement options */
              > case 'n':
              > dx = 0;
              > dy = -1;
              > action = 1;
              > break;
              > case 's':
              > .
              > .
              > .
              > .
              > .[/color]

              This is where you forgot your break statement...
              [color=blue]
              > default:[/color]

              ....which is why you fall through to the default case.

              Comment

              • Kiru Sengal

                #8
                Re: Program entering the default case of switch statement always

                Phoe6 wrote:[color=blue]
                > The Program Fragment is this:
                >
                > int choice; /* Users Input Command */
                > .
                > .
                > .
                > printf("Enter a command: ");
                > fflush(stdin);
                >[/color]

                You can't portably flush stdin, even if you could there would be no
                point in doing it at this location. This location is a perfect place
                to fflush(stdout), because you don't have a newline in your printf
                format string.
                [color=blue]
                >
                > choice = getc(stdin);
                >[/color]

                After getc returns a character, there would still be AT LEAST a newline
                sitting in stdin (and possible some other junk if the user didn't
                immediately hit ENTER after providing a character). This isn't true if
                the user hits ENTER right from the start, in which case there won't be
                anything sitting in stdin, so you must be careful about what I just
                said.

                [color=blue]
                >
                > printf("\n");[/color]
                [color=blue]
                > while(choice!=' Q')
                > {
                > switch(choice)
                > {
                > /* Movement options */
                > case 'n':
                > dx = 0;
                > dy = -1;
                > action = 1;
                > break;[/color]
                [snipped some cases][color=blue]
                > default:
                > printf("You cannot do that!\n");
                > action = 0;
                > break;
                >
                > }
                >
                > .
                > .
                > .
                > printf("Enter a Command :");
                > fflush(stdin);
                > choice = getc(stdin);
                > printf("\n");
                >[/color]
                You are repeating yourself down here. To get around this, use a
                do-while loop, which always executes the body at least once (and only
                tests the condition at the bottom)[color=blue]
                >
                > } /* <- End Brace of while loop */
                >
                >
                > The Problem I am observing is the Default Section of the Switch[/color]
                command[color=blue]
                > is being entering all the times (except for the first time).
                >[/color]

                Yes, because there are characters left in stdin.
                [color=blue]
                >
                > I am guessing that the choice variable is getting someother value[/color]
                which[color=blue]
                > is causing it to enter the default; but using
                > getchar,getc(st din),fgetc(stdi n) and flushing the stdin is not[/color]
                solving[color=blue]
                > the problem.[/color]

                Do not fflush stdin.
                Do fflush stdout if you don't provide a trailing newline to printf.


                I altered your program a little to get it to work. Beware though, this
                may not be exactly what you wanted and there are probably more robust &
                elegant solutions (I myself rarely take single character inputs, and
                have my own wrapper functions to deal with different situations -
                leading whitespace, etc). I only provide this to help you understand
                what the original bug was:

                #include <stdio.h>
                #include <stdlib.h>

                int main(void)
                {
                int choice;

                do{
                printf("Enter a Command : ");
                fflush(stdout);
                choice = getc(stdin);

                /* clearing stdin manually */
                if(choice != '\n')
                while(getchar() != '\n')
                ; /* empty statement */

                switch(choice)
                {
                case 'N':
                case 'n': puts("\nYou hit 'n'\n");
                break;

                case 'S':
                case 's': puts("\nYou hit 's'\n");
                break;

                /* more cases */

                case '\n': puts("\nYou didn't provide a choice\n");
                break;

                case 'Q':
                case 'q': puts("\nHit ENTER to quit\n");
                getchar();
                break;

                default: puts("\nYou cannot do that!\n");
                break;
                }
                }while(choice != 'Q' && choice != 'q');

                return EXIT_SUCCESS;
                }

                Comment

                • Phoe6

                  #9
                  Re: Program entering the default case of switch statement always

                  Thanks for your reply:

                  /* clearing stdin manually */
                  if(choice != '\n')
                  while(getchar() != '\n')
                  ; /* empty statement */

                  Solves the problem.
                  I am unable to understand how this works. :-(
                  I am getting confused here.

                  Before posting, I tried with getchar,getc,fg etc etc... hoping to
                  eliminate the extra '\n' character at input, but failed. How is the
                  above statement clearing stdin manually and is there anyother way the
                  problem could have been solved.

                  Thanks!
                  Senthil

                  Comment

                  • Eric Sosman

                    #10
                    Re: Program entering the default case of switch statement always

                    Phoe6 wrote:[color=blue]
                    > The smallest example which I can give to express the the problem I am
                    > facing is here:
                    >
                    > #include<stdio. h>
                    >
                    > int main(void)
                    > {
                    > int choice;
                    > choice=getc(std in);
                    > while(choice='Q ')[/color]

                    ITYM `while (choice != 'Q')' ...
                    ^^

                    As things stand, `while (choice = 'Q')' sets the variable
                    to the code for the character 'Q', overwriting whatever
                    was read from stdin. When you reach the `switch' statement
                    inside the loop, `choice' is 'Q' no matter what you typed.

                    --
                    Eric Sosman
                    esosman@acm-dot-org.invalid

                    Comment

                    • Kiru Sengal

                      #11
                      Re: Program entering the default case of switch statement always

                      Phoe6 wrote:[color=blue]
                      > Thanks for your reply:
                      >
                      > /* clearing stdin manually */
                      > if(choice != '\n')
                      > while(getchar() != '\n')
                      > ; /* empty statement */
                      >
                      > Solves the problem.
                      > I am unable to understand how this works. :-(
                      > I am getting confused here.
                      >
                      > Before posting, I tried with getchar,getc,fg etc etc... hoping to
                      > eliminate the extra '\n' character at input, but failed. How is the
                      > above statement clearing stdin manually and is there anyother way the
                      > problem could have been solved.[/color]


                      The text input stream (associated with stdin) is "line buffered" so
                      characters don't appear in stdin, lines do. A line happens to be a
                      sequence of characters terminated with a newline character.

                      So when you use getchar, getc(stdin), or fgetc(stdin) you're
                      essentially telling it to "look in stdin and grab the first available
                      character" - this is how those functions/macros work. Stdin stays
                      empty until a full line is sent to it (user hits ENTER to send newline
                      character and signal end of line).
                      So getchar, getc, fgetc wait until a character appears. Say the user
                      hit 'n' and then enter. The character 'n' isn't sent to stdin
                      immediately, but rather both 'n' and '\n' go to stdin together (because
                      \n signals end of line, and it's lines that are sent to stdin).

                      So now stdin has two characters sitting in it (STDIN: 'n' '\n') So now
                      your getchar, getc, fgetc can grab the n, and return it to your program
                      (which continues through the switch and back through to getchar, getc,
                      fgetc again).
                      This time, getchar, getc, fgetc don't need to wait for the user to
                      provide anything because stdin is not empty, so they immediately grab
                      the '\n' (without involving the user in any way) and return it the
                      program. The third time through the loop, stdin is once again empty,
                      so the user will have a chance to type something and hit ENTER to
                      provide stdin with another line.

                      Now let me ask you a question, what happens if the user types:
                      snsnsnsnsn[enter] ? [Answer: 11 characters will rush into stdin as a
                      whole line and your while loop will execute 10 extra times (without
                      ever needing user input)]

                      How do you prevent this? I personally wouldn't do character input, but
                      as a solution to your original code I added the "rest of line consuming
                      while loop" to clear out the rest of stdin. But, there is a special
                      case: if the user actually hit ENTER immediately, then stdin would only
                      have one character in it '\n', which getchar/fgetc/getc grabs and the
                      consuming while loop would eat the next line coming into stdin (which
                      we wouldn't want) - thus the "consuming while loop" is only let loose
                      if it gets passed the IF statement (which verifies that the character
                      grabbed by getchar, getc, fgetc isn't a newline).

                      I might be oversimplifying here with terminology/explanation, but I
                      think I'm making an accurate enough point for your to wrap your mind
                      around. I really hoped you would only take my original post as a start
                      to some self-learning/research, and now I hope the same for this post
                      (you still have to research why fflush(stdin) is a no-no and
                      fflush(stdout) is required at times).

                      Take care.

                      Comment

                      • Phoe6

                        #12
                        Re: Program entering the default case of switch statement always

                        Thanks a lot, Kiru, for your explaination.
                        It was really helpful to me and I am getting some details; I will take
                        your suggestion to go further with this issue to learn more.


                        Regards,
                        Senthil

                        Comment

                        • Gordon Burditt

                          #13
                          Re: Program entering the default case of switch statement always

                          >The Program Fragment is this:[color=blue]
                          >
                          >int choice; /* Users Input Command */
                          >.
                          >.
                          >.
                          >printf("Ente r a command: ");
                          >fflush(stdin );[/color]

                          fflush(stdin) invokes the wrath of undefined behavior.
                          [color=blue]
                          >choice = getc(stdin);
                          >printf("\n") ;
                          >.
                          >.
                          >.
                          >while(choice!= 'Q')
                          > {[/color]

                          Note: newline ('\n') is a real character. Believe it. Worship
                          it. You type it after entering your command, right? So don't be
                          too surprised when choice == '\n' some of the time when you run
                          your program (like maybe every other time around the loop).
                          [color=blue]
                          > switch(choice)
                          > {
                          > /* Movement options */
                          > case 'n':
                          > dx = 0;
                          > dy = -1;
                          > action = 1;
                          > break;
                          > case 's':
                          >.
                          >.
                          >.
                          >.
                          >.[/color]
                          Note: case 's' falls through to the default: case as it is written
                          here.
                          [color=blue]
                          > default:
                          > printf("You cannot do that!\n");
                          > action = 0;
                          > break;
                          >
                          > }
                          >
                          >.
                          >.
                          >.
                          >printf("Ente r a Command :");
                          > fflush(stdin);
                          > choice = getc(stdin);
                          > printf("\n");
                          >
                          >} /* <- End Brace of while loop */
                          >
                          >
                          >The Problem I am observing is the Default Section of the Switch command
                          >is being entering all the times (except for the first time).[/color]

                          Newline is a real character. You typed it, right?
                          [color=blue]
                          >I am guessing that the choice variable is getting someother value which
                          >is causing it to enter the default; but using
                          >getchar,getc(s tdin),fgetc(std in) and flushing the stdin is not solving
                          >the problem.[/color]

                          fflush(stdin) only creates problems; it does not solve them.

                          Gordon L. Burditt

                          Comment

                          Working...