COMPGROUPS.NET | Search | Post Question | Groups | Stream | About | Register

### Program entering the default case of switch statement always

• Email
• Follow

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(stdin),fgetc(stdin) and flushing the stdin is not solving
the problem.

---
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)

Regards,
Senthil


 0
Reply orsenthil (94) 2/27/2005 6:49:33 PM

See related articles to this posting

 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(stdin);

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(stdin);
}
putchar('Q');

return 0;

}

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


 0
Reply orsenthil (94) 2/27/2005 7:37:11 PM

In article <1109530173.660994.217400@g14g2000cwa.googlegroups.com>,
Phoe6 <orsenthil@gmail.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!

 0
Reply roberson2 (8606) 2/27/2005 7:43:33 PM

In article <1109533031.347928.166950@g14g2000cwa.googlegroups.com>,
Phoe6 <orsenthil@gmail.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

 0
Reply roberson2 (8606) 2/27/2005 7:47:58 PM

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

You mean you don not see:

Enter a Command :
You cannot do that!

In the output neccessarily! Thats strange and interesting. Thats what

>I do find a bug in the code: shooting south should have
>a dy of +1 instead of -1.

Thanks, I have corrected it.


 0
Reply orsenthil (94) 2/27/2005 7:48:56 PM

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

Undefined behaviour. fflush's functionality is defined only for
streams open for output or update.

> choice = getc(stdin);

Program may block for input before displaying prompt.

> printf("\n");
> .
> .
> .
> while(choice!='Q')
>         {
>                 switch(choice)
>                 {
>                         /* Movement options */
>                         case 'n':
>                                         dx = 0;
>                                         dy = -1;
>                                         action = 1;
>                                         break;
>                         case 's':
> .
> .
> .
> .
> .

This is where you forgot your break statement...

>                         default:

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

 0
Reply infobahn (503) 2/27/2005 8:01:22 PM

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


 0
Reply orsenthil (94) 2/27/2005 8:01:56 PM

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

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.

>
> choice = getc(stdin);
>

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.

>
> printf("\n");

> while(choice!='Q')
> 	{
> 		switch(choice)
> 		{
> 			/* Movement options */
> 			case 'n':
> 					dx = 0;
> 					dy = -1;
> 					action = 1;
> 					break;
[snipped some cases]
> 			default:
> 					printf("You cannot do that!\n");
> 					action = 0;
> 					break;
>
> 		}
>
> .
> .
> .
> printf("Enter a Command :");
> 	fflush(stdin);
> 	choice = getc(stdin);
> 	printf("\n");
>
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)
>
> } /* <- 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).
>

Yes, because there are characters left in stdin.

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

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


 0
Reply kiru.sengal (37) 2/27/2005 8:04:47 PM

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,fgetc 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


 0
Reply orsenthil (94) 2/27/2005 8:28:54 PM

Phoe6 wrote:
>  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(stdin);
>         while(choice='Q')

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

 0
Reply esosman (1384) 2/27/2005 9:36:52 PM

Phoe6 wrote:
>
>  /* 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,fgetc 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.

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.


 0
Reply kiru.sengal (37) 2/27/2005 9:49:40 PM

Thanks a lot, Kiru, for your explaination.
It was really helpful to me and I am getting some details; I will take

Regards,
Senthil


 0
Reply orsenthil (94) 2/27/2005 10:04:24 PM

>The Program Fragment is this:
>
>int choice;			/* Users Input Command */
>.
>.
>.
>printf("Enter a command: ");
>fflush(stdin);

fflush(stdin) invokes the wrath of undefined behavior.

>choice = getc(stdin);
>printf("\n");
>.
>.
>.
>while(choice!='Q')
>	{

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).

>		switch(choice)
>		{
>			/* Movement options */
>			case 'n':
>					dx = 0;
>					dy = -1;
>					action = 1;
>					break;
>			case 's':
>.
>.
>.
>.
>.
Note:  case 's' falls through to the default: case as it is written
here.

>			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).

Newline is a real character.  You typed it, right?

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

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

Gordon L. Burditt

 0

12 Replies
37 Views

Similar Articles

12/21/2013 10:55:34 PM
[PageSpeed]

Similar Artilces:

switch case statement
Hi All, I have a question regarding structuring my servlet. I have a couple of if conditions like this if((String)request.getParameter("test").equals("a")) {do something .........} if((String)request.getParameter("test").equals("b")) {do something .........} if((String)request.getParameter("test").equals("c")) {do something .........} if((String)request.getParameter("test").equals("d")) {do something .........} if((String)request.getParameter("test").equals("e")) {do something .........} how ...

Switch..Case Statement Question.
Can someone tell me if the following Switch...Case construct is valid? I'm wanting to check for multiple values in the Case statement without explicitly listing each values. So for example, will case 1-35: work? If this would work, will it consider all numbers between 1 and 35 inclusive of 1 and 35? Please let me know if the following will work below: switch(state){ case 1-35: case 37: do something_1; break; case 36: do something_2; break; case 38-50: do something_3; break; } Thank you. Andy. Andy said: > >Can someone tell me if the following Switch...Cas...

Alternate to switch case statement
Hi everyone, This is the first time iam posting excuse me if iam making any mistake. My question is iam using a switch case statement in which i have around 100 case statements to compare. so just curious to find out is it effective to use this method?? or is there is any other alternative method present so that execution time and code size can be reduced?? Thanks in advance. Regards, Satya >This is the first time iam posting excuse me if iam making any >mistake. My question is iam using a switch case statement in which i >have around 100 case statements to compare. so just curiou...

Implementation of Switch-Case Statement in TeX
Hi, I recently had the idea about a switch case statement for use in LaTeX packages. I needed to check user input (a string) and execute different macros on different inputs. of a list. Because I could not find a switch-case statement I implemented it using code like this: \def\@tempa{foo} \ifx\@tempa\user@input ... \else \def\@tempa{bar} \ifx\@tempa\user@input ... \fi\fi Now I found the time to code a switch-case statement in plainTeX: My idea about the syntax is: \switch{<input value>} \case{<case 1 value>}{<case 1 code} \case{<case 2 value>}{<case 2 code} ...

'if' statement to control switch case
Hi Folks, I'm experimenting a little with creating a custom CEdit control so that I can decide on what the user is allowed to type into the control. I started off only allowing floating point numbers then added support for putting in lat/lon coordinates. I tried this little piece of code inside the OnChar function but compiler complained about missing ';' after "case _T('W'):" switch(nChar) { if(m_bLATLON) // if latlon then no negs and 4 extra chars. { case _T('N'): case _T('E'): case _T('S'): case _T(...

Latch inference when default is missing in case statement
Dear Group, It is said that if default statement is missing in case statement, then a latch is inferred. But I am not able to understand this. What is meant by latch inference? and why would a latch be inferred if case statement does not have default statement. If some cases are missed and default is also not there in a case statement, then it should simply read 'x' or '-' for those cases. Why is this latch inference coming into picture? Please help. Thanks I also found a related article : http://www.asic-world.com/verilog/verilog_one_day2.html But it does not explain WHY...

FAQ 7.23 How do I create a switch or case statement?
This is an excerpt from the latest version perlfaq7.pod, which comes with the standard Perl distribution. These postings aim to reduce the number of repeated questions as well as allow the community to review and update the answers. The latest version of the complete perlfaq is at http://faq.perl.org . -------------------------------------------------------------------- 7.23: How do I create a switch or case statement? In Perl 5.10, use the "given-when" construct described in perlsyn: use 5.010; given ( $string ) { ... changing the value of "case" in a switch statement When using the switch / case construct I have found it necessary (desirable?) to be able to change the "case" on the fly. For example (this is a typed in example, not the true code): switch ($action) { case "save" { # save the new information $action = "list"; # show them all the information available including what was just saved using the next case } case "list" { # list the information available } } Changing$action in the "save" portion doesnt alter the switch / case (unless I am doing something very wrong). The only remedy I...

Depending between primary key in database and switch case statement
Hello,I have a bit of a design issue around this application I amdeveloping, and I just want to run it through some of the brains outhere.So I have a table called ErrorCheck which contains fields ErrorID (PK)and ErrorName. There is another table called Client which containsfields ClientID (PK) and ClientName. Then there is a relationshiptable called ClientErrorCheck which contains foreign keys ErrorID andClientID.The ErrorCheck table contains names and ids of checks that need to beperformed for clients.In my code, based on the client that the user selects in a listbox, Igrab all the correspond...

FAQ 7.23 How do I create a switch or case statement? #17
This is an excerpt from the latest version perlfaq7.pod, which comes with the standard Perl distribution. These postings aim to reduce the number of repeated questions as well as allow the community to review and update the answers. The latest version of the complete perlfaq is at http://faq.perl.org . -------------------------------------------------------------------- 7.23: How do I create a switch or case statement? In Perl 5.10, use the "given-when" construct described in perlsyn: use 5.010; given ( \$string ) { when( 'Fred...