Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Newbie C programming question - "Press any key to continue"

Reply
Thread Tools

Newbie C programming question - "Press any key to continue"

 
 
Andrew Robert
Guest
Posts: n/a
 
      11-09-2003
Hi Everyone,

I am trying to develop a simple menu using switch/case statements and I
want to be able to have the user "Press any key to continue".

It seems that the main problem is with the initial scanf choice part of
the menu (see code below).

I first looked at scanf and gets but they delete the terminal \n and
that would mess up pressing the carraige return key.

The function fgets seems to do what I need but man pages and on-line
references to fgets seem to indicate it should be used strictily for files

The idea of a "Press any key to continue" should be pretty common but
the logic seems to be elusive.

Does anyone have any ideas about this?

Any help you can provide would be greatly appreciated.


Thanks



/*

program: stu_menu.c

Function: Display student registration menu to screen, retrieve/validate
choice and pass control to sub-program. Code includes standard
elements to comply as c++ code.

Modification History

Date Programmer Modification
11/06/03 AAR Initial creation
Added statement to initialize choice variable
Added scanf/flushf statement to get user choice
Added switch case handles to determine user
choice
Added mode to clear screen and warn of bad
choice

11/06/03 AAR Test compiled on Fedora Linux CORE 9.1 using
gcc 2.96 compiler

11/07/03 AAR Ported to Alpha OpenVMS v7.3-1 and compiled
using Compaq C v6.5-001. Code successfully
tested

11/07/03 AAR Ported to Solaris v5.8 and compiled


*/

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

int main()
{
int choice;
char string[1];
system("clear");

while (1)
{
system("clear");
printf("\n\t\tSTUDENT REGISTRATION/COURSE GRADE\n");
printf("\t\t DATABASE MANAGEMENT SYSTEM\n\n");
printf("\t\t1. Register a new student\n");
printf("\t\t2. Delete a student\n");
printf("\t\t3. Enter grades for a student\n");
printf("\t\t4. Display student grade report\n");
printf("\t\t5. Display class grade averages\n");
printf("\t\t6. Exit\n\n\n");
printf("\t\t\tChoice: ");
scanf("%d",&choice);
fflush(stdin);




switch (choice)
{
case 1: system("clear");
printf ("\n\n\t\tOption Selected 1.\n");
printf ("\n\n\t\tPress any key to continue");
scanf("%s",string);
break;

case 2: system("clear");
printf ("\n\n\t\tOption Selected 2.\n");
printf ("\n\n\t\tPress any key to continue");
scanf("%s",string);
break;

case 3: system("clear");
printf ("\n\n\t\tOption Selected 3.\n");
printf ("\n\n\t\tPress any key to continue");
scanf("%s",string);
break;

case 4: system("clear");
printf ("\n\n\t\tOption Selected 4.\n");
printf ("\n\n\t\tPress any key to continue");
scanf("%s",string);
break;

case 5: system("clear");
printf ("\n\n\t\tOption Selected 5.\n");
printf ("\n\n\t\tPress any key to continue");
scanf("%s",string);
break;

case 6: printf ("Program Over.\n");
exit (0);

default: system("clear");
printf ("\n\n\t\t Invalid choice.\n");
printf ("\n\n\t\t Press any key to continue");
scanf("%s",string);
system("clear");
break;

} /* end switch */
} /* end while */
return 0;
}


 
Reply With Quote
 
 
 
 
Joona I Palaste
Guest
Posts: n/a
 
      11-09-2003
Andrew Robert <(E-Mail Removed)> scribbled the following:
> Hi Everyone,


> I am trying to develop a simple menu using switch/case statements and I
> want to be able to have the user "Press any key to continue".


> It seems that the main problem is with the initial scanf choice part of
> the menu (see code below).


> I first looked at scanf and gets but they delete the terminal \n and
> that would mess up pressing the carraige return key.


> The function fgets seems to do what I need but man pages and on-line
> references to fgets seem to indicate it should be used strictily for files


Those man pages and on-line references are wrong. fgets, despite its
name, works on streams, not files. You can pass any input stream to it.
Try passing stdin.

> The idea of a "Press any key to continue" should be pretty common but
> the logic seems to be elusive.


> Does anyone have any ideas about this?


> Any help you can provide would be greatly appreciated.



> Thanks




> /*


(snip)

> */


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


> int main()
> {
> int choice;
> char string[1];
> system("clear");


This command "clear" is non-portable. (Pretty much any command passed
to system() is.) Why do you want to clear the screen in the first
place?

> while (1)
> {
> system("clear");
> printf("\n\t\tSTUDENT REGISTRATION/COURSE GRADE\n");
> printf("\t\t DATABASE MANAGEMENT SYSTEM\n\n");
> printf("\t\t1. Register a new student\n");
> printf("\t\t2. Delete a student\n");
> printf("\t\t3. Enter grades for a student\n");
> printf("\t\t4. Display student grade report\n");
> printf("\t\t5. Display class grade averages\n");
> printf("\t\t6. Exit\n\n\n");
> printf("\t\t\tChoice: ");
> scanf("%d",&choice);
> fflush(stdin);


Undefined behaviour. This might do anything from segfaulting your
program to calling up George W Bush and telling him you're hiding
those elusive WMDs.

> switch (choice)
> {
> case 1: system("clear");
> printf ("\n\n\t\tOption Selected 1.\n");
> printf ("\n\n\t\tPress any key to continue");
> scanf("%s",string);


It's a bad idea to scanf() into a 1-character array this way. If
the user types more than one character, you overflow the buffer,
causing undefined behaviour. Try the "%c" specifier for scanf()
or switch to fgets(). fgets() does work on stdin.

> break;


(snip)

> case 6: printf ("Program Over.\n");
> exit (0);


> default: system("clear");
> printf ("\n\n\t\t Invalid choice.\n");
> printf ("\n\n\t\t Press any key to continue");
> scanf("%s",string);
> system("clear");
> break;


> } /* end switch */
> } /* end while */
> return 0;
> }


It's true that when you type for example '1' in response to your
prompt, you have to press Return, and such your program receives
"1\n". You need some "draining" logic to get rid of the '\n'. This
is very simple, the comp.lang.c FAQ contains some sample code.
Generally, once you get your character, you want to discard any
subsequent characters up to and including the first '\n'. Then process
the rest as normal.

--
/-- Joona Palaste ((E-Mail Removed)) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"To doo bee doo bee doo."
- Frank Sinatra
 
Reply With Quote
 
 
 
 
Malcolm
Guest
Posts: n/a
 
      11-09-2003

"Andrew Robert" <(E-Mail Removed)> wrote in message
>
> I am trying to develop a simple menu using switch/case statements and > I

want to be able to have the user "Press any key to continue".
>

ANSI C is the wrong language for this. It provides extremely limited
facilities for the user to input, a line at time, into stdin. If the user
types 'x' followed by 'return' you can read the 'x' with scanf() or similar.
However there is no way of detecting the actual keypress of the 'x'.

What you need to do is use some extension. There is often a library provided
called conio (#include conio.h) with PCs, or curses with UNIX. This provides
functions for scanning the keyborad and printing nice screens. Obviously the
program is then not portable, but few real programs are.
>
> The function fgets seems to do what I need but man pages and on-line
> references to fgets seem to indicate it should be used strictily for files
>

stdin is a FILE *, as is stdout and stderr. stdin is usually the keyboard.
>
> #include <stdio.h>
> #include <stdlib.h>
>
> int main()
> {
> int choice;
> char string[1];
>

This looks like you don't understand what you are doing. Why an array of
only one element ?
>
> system("clear");
>
> while (1)
> {
> system("clear");
> printf("\n\t\tSTUDENT REGISTRATION/COURSE GRADE\n");
> printf("\t\t DATABASE MANAGEMENT SYSTEM\n\n");
> printf("\t\t1. Register a new student\n");
> printf("\t\t2. Delete a student\n");
> printf("\t\t3. Enter grades for a student\n");
> printf("\t\t4. Display student grade report\n");
> printf("\t\t5. Display class grade averages\n");
> printf("\t\t6. Exit\n\n\n");
> printf("\t\t\tChoice: ");
> scanf("%d",&choice);
> fflush(stdin);
>

fflush is only defined for output files.

> switch (choice)
> {
> case 1: system("clear");
> printf ("\n\n\t\tOption Selected 1.\n");
> printf ("\n\n\t\tPress any key to continue");
> scanf("%s",string);
>

string is only one element long, and C strings are NUL-terminated. This
means that you will always overflow your buffer when the user enters a
character. You mean char ch; scanf("%c", &ch);



 
Reply With Quote
 
Andrew Robert
Guest
Posts: n/a
 
      11-09-2003
Hi Joona,

I appreciate your response to my questions.

The system clear statements are understood to be non-portable but they
do work on Linux, Solaris v5.8, and VMS 7.3-1 which are the environments
I am concerned about so I left it in strictly for neatness.

In response to your statement about drainage logic, I developed the
function listed below:

I guess my primary concern is in proper usage of fgets from stdin and
translation of the return value to integer so that the switch/case
statement functions correctly.

Should I replace the code statements

scanf("%d",&choice);
fflush(stdin);

with

char c[10];

...
code to display menu
...

fgets(c, 10, stdin) !NULL;
choice=atoi(c);


or should I do something else entirely?




Drainage function:


char *getsafe(char *buffer, int count)
{
char *result = buffer, *np;
printf("count=%d.\n",count);
printf("buffer=%x.\n",buffer);

if ((buffer == NULL) || (count < 1))
{
result = NULL;
}
else if (count == 1)
{
*result = '\0';
}
else if ((result = fgets(buffer, count, stdin)) != NULL)
{
printf ("Got here 1.\n");
}

if (np = strchr(buffer, '\n'))
{
*np = '\0';
printf ("Got here 2.\n");
}

return result;
}


 
Reply With Quote
 
Martin Ambuhl
Guest
Posts: n/a
 
      11-09-2003
Andrew Robert wrote:

> Should I replace the code statements
>
> scanf("%d",&choice);
> fflush(stdin);


Since 'fflush(stdin);' has no meaning, you could improve your code by
replacing it with whitespace.

>
> with
>
> char c[10];
>
> ...
> code to display menu
> ...
>
> fgets(c, 10, stdin) !NULL;
> choice=atoi(c);


char c[NUMBER_MUCH_BIGGER_THAN_10], *endp;
while (fgets(c, sizeof c, stdin))
{
choice = strtol(c, &endp, 10);
/* check *endp, etc. for successful operation */
/* ... */
}




--
Martin Ambuhl

 
Reply With Quote
 
Irrwahn Grausewitz
Guest
Posts: n/a
 
      11-09-2003
Martin Ambuhl <(E-Mail Removed)> wrote:

> Andrew Robert wrote:
>
> > Should I replace the code statements
> >
> > scanf("%d",&choice);
> > fflush(stdin);

>
> Since 'fflush(stdin);' has no meaning,


Oh, it has: "Make the demons fly!"

> you could improve your code by
> replacing it with whitespace.


Which would be a great improvement, as it avoids undefined behaviour.

<snip>

--
Irrwahn
((E-Mail Removed))
 
Reply With Quote
 
Gordon Burditt
Guest
Posts: n/a
 
      11-10-2003
>I am trying to develop a simple menu using switch/case statements and I
>want to be able to have the user "Press any key to continue".


I hope YOU have to pay for the tech support calls when they call
and ask where the "Any" key is. No, I'm not kidding.

Also be aware that "any key" includes a number of things that
do not generally generate characters:

- Shift (either one)
- Alt (either one)
- Control (either one)
- RESET
- Caps Lock
- Power Off, Standby, or Sleep
- The eject button on the cup holder, er, CD-ROM drive
- A house key, car key, etc. in the user's pocket.
- A PGP encryption key.
- A key on a telephone

and even those who eventually press an appropriate key may spend
half an hour doing "eeney, meeney, miney, moe" to decide which key
to press while on hold with tech support.

>It seems that the main problem is with the initial scanf choice part of
>the menu (see code below).


The main problem is that "press any key" is a poor user interface,
no matter how it is implemented. And there's NO WAY to do it
in standard ANSI C, unless you define "any key" as the one with
the label "Return" or "Enter" or the corresponding funny-looking arrow.

>The function fgets seems to do what I need but man pages and on-line
>references to fgets seem to indicate it should be used strictily for files


There is nothing wrong with using fgets on stdin. I consider it
the FIRST function to think about when getting input from what's
likely to be an actual user with a keyboard.

gets() suffers from unfixable buffer overflow problems. scanf()
and fscanf(stdin, ...) suffer from poor behavior when a user enters
data in a wrong format or leaves some out. getchar() and fgetc()
are possible, but if you're using it to parse as you read, you often
cannot back out of a syntax error easily. They are useful if you
really have to accept unlimited-length lines (although the OS is
likely to intrude here with a limit). fread() expects the user to
enter something in a fixed size, which is usually unreasonable to
expect.


>The idea of a "Press any key to continue" should be pretty common but
>the logic seems to be elusive.


The idea of a self-destruct button next to the one to turn on the headlights
should be pretty commonly considered a BAD idea.

Gordon L. Burditt
 
Reply With Quote
 
Alan Connor
Guest
Posts: n/a
 
      11-10-2003
On 10 Nov 2003 03:20:23 GMT, Gordon Burditt <(E-Mail Removed)> wrote:
>


Your funny, and right I'm sure, yet I run into the "press any key to continue"
option fairly often. All the time in mc. (that would be Norton Commander on
Windows). I've even played around with testing it and so far have not
encountered a key that would not work. Havent't been systematic, though.

What gives?

I thought there was just a function that looked for ANY response from the
keyboard, ANY scancode, and then executed another function.

In sh it could be written like so:

input ()

{

read x

case "$x" in

* ) do foo ;;

esac

}


In fact, I have used that very function in scripts for just this purpose.

Hard to imagine that C doesn't have the same functionality (sorry .

--
Alan C this post ends with w
q
 
Reply With Quote
 
Richard Bos
Guest
Posts: n/a
 
      11-10-2003
Alan Connor <(E-Mail Removed)> wrote:

> On 10 Nov 2003 03:20:23 GMT, Gordon Burditt <(E-Mail Removed)> wrote:
>
> Your funny, and right I'm sure, yet I run into the "press any key to continue"
> option fairly often. All the time in mc. (that would be Norton Commander on
> Windows). I've even played around with testing it and so far have not
> encountered a key that would not work. Havent't been systematic, though.
>
> What gives?


You are not an averagely stupid user, that gives. Believe you me, there
_are_ people who look for a key labeled "any".

> I thought there was just a function that looked for ANY response from the
> keyboard, ANY scancode, and then executed another function.


Not in ISO C. On many systems (sometimes including an otherwise standard
desktop computer being spoken to through a modem line), looking for any
scancode isn't possible, or indeed even a plausible thing to ask for
(Modem: "Scan code? What's that, a scan code? I can give you a line
typed at the other end of the phone line, is that OK?").

Richard
 
Reply With Quote
 
Nils Petter Vaskinn
Guest
Posts: n/a
 
      11-10-2003
On Mon, 10 Nov 2003 03:59:02 +0000, Alan Connor wrote:

> On 10 Nov 2003 03:20:23 GMT, Gordon Burditt
> <(E-Mail Removed)> wrote:
>>
>>

> Your funny, and right I'm sure, yet I run into the "press any key to
> continue" option fairly often. All the time in mc. (that would be Norton
> Commander on Windows). I've even played around with testing it and so
> far have not encountered a key that would not work. Havent't been
> systematic, though.
>
> What gives?
>
> I thought there was just a function that looked for ANY response from
> the keyboard, ANY scancode, and then executed another function.


A program (C or script) doesn't see the scancodes (usually), they see
characters after the OS has translated the scancodes. And some key doesn't
generate characters when pressed alone.

The problem will be (in programs as well as in your script) when you
encounter the mythical "completely clueless user" that thinks the shift
key is suitable when they say to press ANY key. (or perhaps that fn key
that's so common on laptops)

"Press enter to continue" is less likely to fail due to clueless users.

--
NPV

"the large print giveth, and the small print taketh away"
Tom Waits - Step right up

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
501 PIX "deny any any" "allow any any" Any Anybody? Networking Student Cisco 4 11-16-2006 10:40 PM
Replace Tab Key to Return Key (Enter Key) from Web Forms? M P ASP General 1 08-06-2004 08:32 AM
Re: Newbie question: Any good resources on Java programming? Hugo Pragt Java 2 09-15-2003 05:15 PM
Newbie question: Any good resources on Java programming? Timberwolf Java 0 09-15-2003 02:19 PM



Advertisments