Menu printed twice in calc prog

A

Andy

Hi

I am writing a small calculator program using switch() for a menu. The
menu is presented at first, selection read in via scanf(), and
calculation is executed. At the end of the operation, the menu is
presented again. When it is presented again however, it is printed
twice. I've been through the code and cannot spot any obvious errors,
but hey ... more eyes are better than one. I don't particularly want to
revamp my code too much nor use sophisticated hacks since I am a student
relatively new to C and programming and a lot of that advanced stuff
would be way over my head :)

I have copied the code for reference. Does it have something with not
flushing the buffers from the first stdin read by scanf()? Suggestions
please:

----------code begin--------------------

/****************************************************************
* *
* Program: Calk-U-l8r.c *
* *
* Written by: xxxxxxxxxxxx *
* *
* 30/10/03; <version number> *
* *
*****************************************************************/


#include <stdio.h>

/* Menu-driven Calculator program: */


main()

{
float i, z, tmp;
char x;

tmp = 0;

puts("\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
puts("\n Calk-U-l8r\n");
puts("\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");

puts("\nPlease select an operation. Enter 'q' to quit:"); /* menu */
printf("\nAdd: %10c\n", 'a');
printf("Divide: %7c\n", 'd');
printf("Multiply: %5c\n", 'm');
printf("Subtract: %5c\n", 's');

scanf("%c", &x);

while ( x != 'q'){
switch(x){
case 'a': /* add function */
puts("\nAddition\n");
printf("\nEnter digit:>");
scanf("%f", &i);
tmp += i;
printf("\nEnter next digit:>");
scanf("%f", &i);
tmp += i;

printf("\nThe answer is: %.2f", tmp);
break;

case 'd': /* divide function */
puts("\nDivision\n");
puts("\nEnter a digit:");
scanf("%f", &i);
puts("\nEnter the dividend:");
scanf("%f", &z);

printf("\nThe answer is: %.2f", i / z);
break;

case 'm': /* multiplication */
puts("\nMultiplication\n");
printf("\nEnter a digit:>");
scanf("%f", &i);
printf("\nEnter a second digit:>");
scanf("%f", &z);

printf("\nThe answer is: %.2f", i * z);
break;

case 's': /* subtraction */
puts("\nSubtraction\n");
puts("\nEnter a digit:");
scanf("%f", &i);
puts("\nEnter second digit:");
scanf("%f", &z);

printf("\nThe answer is: %.2f", i - z);
break;

}


puts("\nPlease select an operation. Enter 'q' to quit:");
printf("\nAdd: %10c\n", 'a');
printf("Divide: %7c\n", 'd');
printf("Multiply: %5c\n", 'm');
printf("Subtract: %5c\n", 's');

scanf("%c", &x);

}

puts("\n\nThank-you for using Calk-U-l8r!\n");

return 0;

}


----------code end------------------------

Thanks

Andy
 
E

Eric Sosman

Andy said:
Hi

I am writing a small calculator program using switch() for a menu. The
menu is presented at first, selection read in via scanf(), and
calculation is executed. At the end of the operation, the menu is
presented again. When it is presented again however, it is printed
twice. I've been through the code and cannot spot any obvious errors,
but hey ... more eyes are better than one. I don't particularly want to
revamp my code too much nor use sophisticated hacks since I am a student
relatively new to C and programming and a lot of that advanced stuff
would be way over my head :)

I have copied the code for reference. Does it have something with not
flushing the buffers from the first stdin read by scanf()? Suggestions
please:
[code snipped; see up-thread]

Your suspicion is close to the mark, and your problem
is pretty close to that of Question 12.18 in the comp.lang.c
Frequently Asked Questions (FAQ) list

http://www.eskimo.com/~scs/C-faq/top.html

.... but perhaps just enough different to warrant extra
explanation. Here's a synopsis of what's happening:

- You print the menu, and then call scanf() to get
the user's choice.

- scanf() converts one character, and you add or
subtract or whatever in response.

- You print the menu again, and call scanf() to get
the user's choice.

- scanf() again converts one character -- but what
character is that, exactly? Why, it's the newline
that ended the user's first line of input. This
'\n' character doesn't match anything in your big
switch() statement, so you take no action on it.

- After having done nothing, you print the menu
and call scanf() a third time.

- This time, scanf() consumes the character after
the newline, namely, the user's actual response,
and you process it.

- ... and then you print the menu, consume and ignore
the newline, print the menu again, consume and act
upon the user's choice, and so on.

See Questions 12.17 through 12.20 for some ideas of
what you might do differently. My preference is not to use
scanf() at all for interactive input; when data comes from
an "uncontrolled" source, I prefer to read an entire line
at a time with fgets() or something similar, and then pick
the line apart without further I/O. fgets() plus sscanf()
makes a pretty good pairing, combining the apparent ease of
plain scanf() with a more predictable I/O behavior.
 
A

Andy

Eric said:
Your suspicion is close to the mark, and your problem
is pretty close to that of Question 12.18 in the comp.lang.c
Frequently Asked Questions (FAQ) list

http://www.eskimo.com/~scs/C-faq/top.html

.... but perhaps just enough different to warrant extra
explanation. Here's a synopsis of what's happening:

- You print the menu, and then call scanf() to get
the user's choice.

- scanf() converts one character, and you add or
subtract or whatever in response.

- You print the menu again, and call scanf() to get
the user's choice.

- scanf() again converts one character -- but what
character is that, exactly? Why, it's the newline
that ended the user's first line of input. This
'\n' character doesn't match anything in your big
switch() statement, so you take no action on it.

- After having done nothing, you print the menu
and call scanf() a third time.

- This time, scanf() consumes the character after
the newline, namely, the user's actual response,
and you process it.

- ... and then you print the menu, consume and ignore
the newline, print the menu again, consume and act
upon the user's choice, and so on.

See Questions 12.17 through 12.20 for some ideas of
what you might do differently. My preference is not to use
scanf() at all for interactive input; when data comes from
an "uncontrolled" source, I prefer to read an entire line
at a time with fgets() or something similar, and then pick
the line apart without further I/O. fgets() plus sscanf()
makes a pretty good pairing, combining the apparent ease of
plain scanf() with a more predictable I/O behavior.
Eric
Thanks for your response - that was nicely explained and useful. I would
have googled for the solution but to be honest didn't really know what
to put in the search string over and above any generality (like scanf())
that would have generated x number of hits. I will look at the FAQ you
mention and see what I can come up with. I've never used fgets() before,
so that will be a useful technique to examine.

Much obliged.

- Andy
 
S

sahukar praveen

Andy said:
Eric
Thanks for your response - that was nicely explained and useful. I would
have googled for the solution but to be honest didn't really know what
to put in the search string over and above any generality (like scanf())
that would have generated x number of hits. I will look at the FAQ you
mention and see what I can come up with. I've never used fgets() before,
so that will be a useful technique to examine.

Much obliged.

- Andy

You could use a 'default' case in the switch to get rid of printing the menu
twice.

something like this....

default:
scanf("%c", &x);
continue;

Thanks,
Praveen Kumar
 
S

Sheldon Simms

You could use a 'default' case in the switch to get rid of printing the menu
twice.

something like this....

default:
scanf("%c", &x);
continue;

What if the user types 'h' 'e' 'l' 'l' 'o' to the program?
How many menus would he see then?

It takes more than your suggestion to solve the real problem.

-Sheldon
 
S

Sheldon Simms

You could use a 'default' case in the switch to get rid of printing the menu
twice.

something like this....

default:
scanf("%c", &x);
continue;

Let me respond again, since the first response was bogus, although the
basic idea I was trying to get across is the same as what I want to say
now.

The problem with this suggestion is that it is designed to eliminate
the symptom without actually fixing the problem.

If you add this code to the sample program given, the extra menu isn't
printed, but the behavior of the program is still not what one would
expect.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top