Menu looping

S

sk

Hi everyone, I'm kind of new to C programming, so I thought that a
newsgroup would be the best place to ask a question about this.

I'm trying to write a small program that displays a menu and has the
user input a value(int). I'm only using getchar and printf to make
things simple.

I have the menu printing part down pretty well, but I'm getting an error
where the entire menu will print n+1 number of times when you input a
value with n-digits. I asked around a little, and some others said that
it was because getchar is buffered, and will just print for every char
that is passed. I'm stuck on how to make it so that the menu will only
print once, then ask the use for input.

This is how it is set up right now:

prints menu
getchar
while (getchar variable is not EOF)
{
prints menu
(conditionals for menu...)
getchar
}

Can anyone give me any ideas on how to fix this? Sorry if this is a
stupid question. Thanks in advance!
 
S

stathis gotsis

sk said:
Hi everyone, I'm kind of new to C programming, so I thought that a
newsgroup would be the best place to ask a question about this.

I'm trying to write a small program that displays a menu and has the
user input a value(int). I'm only using getchar and printf to make
things simple.

I have the menu printing part down pretty well, but I'm getting an error
where the entire menu will print n+1 number of times when you input a
value with n-digits. I asked around a little, and some others said that
it was because getchar is buffered, and will just print for every char
that is passed. I'm stuck on how to make it so that the menu will only
print once, then ask the use for input.

This is how it is set up right now:

prints menu
getchar
while (getchar variable is not EOF)
{
prints menu
(conditionals for menu...)
getchar
}

Can anyone give me any ideas on how to fix this? Sorry if this is a
stupid question. Thanks in advance!

You may consider using a do-while loop since it may suit your needs better.
As far as the implementation is concerned, you can try reading the first
character of the user input and discard the rest of the input line. The end
of a line is signaled with getchar() returning '\n'. In any case you should
always look out for EOF as you already have. Do not forget to store the
getchar() return in an int. Feel free to post your code here in your
attempts towards the desired behaviour.
 
S

sk

stathis said:
You may consider using a do-while loop since it may suit your needs better.
As far as the implementation is concerned, you can try reading the first
character of the user input and discard the rest of the input line. The end
of a line is signaled with getchar() returning '\n'. In any case you should
always look out for EOF as you already have. Do not forget to store the
getchar() return in an int. Feel free to post your code here in your
attempts towards the desired behaviour.

Thank you for your quick reply!

I tried to use the do while, but it's still printing n+1 times...
I'm trying to make something like a stripped down calculator where it
will print a menu, ask for input, print out data, then loops over again.
It will stop when the user pushes ctrl-d or inputs a '0';

Just another quick question. What is the difference between storing the
getchar() return to an int instead of a char?
 
I

Ian Collins

sk said:
Thank you for your quick reply!

I tried to use the do while, but it's still printing n+1 times...
I'm trying to make something like a stripped down calculator where it
will print a menu, ask for input, print out data, then loops over again.
It will stop when the user pushes ctrl-d or inputs a '0';

Just another quick question. What is the difference between storing the
getchar() return to an int instead of a char?

Did you remove the first prints menu before the loop?
 
S

sk

Ian said:
Did you remove the first prints menu before the loop?

Yes, I have. I've also tried many combinations of while loops/print
statements, and it still prints too many times. :(
 
X

Xavier

sk said:
Hi everyone, I'm kind of new to C programming, so I thought that a
newsgroup would be the best place to ask a question about this.

I'm trying to write a small program that displays a menu and has the
user input a value(int). I'm only using getchar and printf to make
things simple.

I have the menu printing part down pretty well, but I'm getting an error
where the entire menu will print n+1 number of times when you input a
value with n-digits. I asked around a little, and some others said that
it was because getchar is buffered, and will just print for every char
that is passed. I'm stuck on how to make it so that the menu will only
print once, then ask the use for input.

This is how it is set up right now:

prints menu
getchar
while (getchar variable is not EOF)
getchar takes char by char buffering chars ...
and you want a multiple char entry...
Don't you want to use fgets, sscanf ? then test on strlen (buf) == 0 to exit
 
F

Frank Schmidt

read this part again...

getchar() will buffer your input until you press enter.
then the next calls will return each character, including a '\n' for enter.

some loop {
menu();

c = getchar();

/* do something */

/* forget the rest of the line */
while (c != '\n' && c != EOF)
c = getchar();
}


EOF (end of file/no more input) is no regular character and if you put the
result in a char... then there will be a character and a eof that you cant
distinguish.
Yes, I have. I've also tried many combinations of while loops/print
statements, and it still prints too many times. :(

or look what xavier wrote...

f~
 
P

Pedro Graca

sk said:
What is the difference between storing the
getchar() return to an int instead of a char?

EOF is not a char.

if ((char)getchar() == EOF) /* is *never* true */
 
K

Keith Thompson

Pedro Graca said:
EOF is not a char.

if ((char)getchar() == EOF) /* is *never* true */

Not quite. EOF is guaranteed to have a negative value of type int
(it's typically -1). If plain char happens to be signed, the
condition can be true *either* if getchar() returns EOF (and EOF is
within the range of signed char) *or* if getchar() returns a valid
character whose value happens matches the value of EOF. On many
systems, the latter will occur if the input character is character
255, which is a y with an umlaut ('ÿ') in Latin-1 (a common extension
of ASCII).

getchar() returns either the value EOF, or the next character from
stdin converted to unsigned char and then converted to int. Storing
the value in an int rather than a char lets you distinguish between
character 255 and -1.
 
C

CBFalconer

sk said:
.... snip ...

I have the menu printing part down pretty well, but I'm getting an
error where the entire menu will print n+1 number of times when
you input a value with n-digits. I asked around a little, and some
others said that it was because getchar is buffered, and will just
print for every char that is passed. I'm stuck on how to make it
so that the menu will only print once, then ask the use for input.

This is how it is set up right now:
.... snip non-compilable code ...
Can anyone give me any ideas on how to fix this? Sorry if this is
a stupid question. Thanks in advance!

Show us compilable code, and tell us what problems you have with
it. At any rate, the following is an expansion of something I
explained in another thread a few days ago. It compiles, but has
not been tested.

#include <stdio.h>
#include <ctype.h>
#include <string.h>

/* ------------------ */

int skipblanks(FILE *f)
{
int ch;

while (' ' == (ch = getc(f))) continue;
return ch;
} /* skipblanks */

/* ------------------ */

int flushln(FILE *f)
{
int ch;

while (('\n' != (ch = getc(f))) && (EOF != ch)) continue;
return ch;
} /* flushln */

/* ------------------ */

/* Print optional menu and get a single char response. Repeat
as needed until the response is in the acceptable string.
If the first char in acceptable is uppercase, use that as
a default response when a blank line is entered.
Returns response initial char or EOF.
*/
int menuget(const char *prompt, /* whatever prompt is needed */
const char *acceptable) /* list of acceptable ans */
{
int ch;

do {
if (prompt) {
printf("%s", prompt); fflush(stdout);
}
/* Now get a reply */
ch = skipblanks(stdin); /* get first non-blank char */
if ('\n' != ch) flushln(stdin); /* set up to try again */
else if (isupper(acceptable[0])
ch = acceptable[0]; /* 1st is default entry */
} while (!strchr(acceptable, ch) && (EOF != ch));
return ch;
} /* menuget (untested) */

You could call this with something like:

ch = menuget("Enter your desire\n"
" A or a for all\n"
" b for botheration\n"
" x for quit : ",
"Aabx";

Notice the merged strings for the prompt.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
O

Old Wolf

sk said:
I have the menu printing part down pretty well, but I'm getting an error
where the entire menu will print n+1 number of times when you input a
value with n-digits.

prints menu
getchar
while (getchar variable is not EOF)
{
prints menu
(conditionals for menu...)
getchar
}

getchar() gets a char. If you enter 10 chars then it your
loop will obviously execute 10 times, once for each char.

It sounds like what you want to do is discard all input up
until the '\n' (enter key), each time you have successfully
read a char. (Another option would be to use a platform-
specific function that returns immediately upon keypress).

Also, if you make the getchar() part of the loop condition
then you don't have to duplicate it.

For example:

int ch;
while ( EOF != (ch = getchar()) )
{
/* consume extra input */
if ( ch != '\n' )
while ( getchar() != '\n' );

do_stuff();
}
 

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,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top