Proper way to wait for menu command and return?

R

RajW

Disclaimer: I'm new to C.

I'm building a simple text based program and I'm not sure I'm
designing it correctly. What I have is simple and it works but it just
seems weird. Is there a better way? I do still have some debugging
code in the subroutine to print out the key pressed.

Basically menuinput() waits for the key press, and passes it to the
switch below. What I'm confused about is, what is the best way to get
back to the menu input subroutine? At the end of the routine that was
called, should I just call menuinput() again?

Thanks,
/*Raj*/

--------------------

Here is the menu input subroutine:

<code>

int menuinput() {
unsigned char menukey;
fflush (stdout);
menukey = getc();

gotoxy (12,18);
printf("key pressed: %c", menukey);
sleep(3);
clearxy(12,18, 16);

switch(menukey)
{
case 'a':
drstatus();
break;
case 'b':
resetdr();
break;
default:
putsxy(1, 20, "invalid menu option");
sleep(3);
clearxy(1, 20, 20);
menuinput();
break;
}
}

</code>
 
R

RajW

You can use a while loop and put the switch in it.


That is also an idea. What about the way back to the menu input
subroutine? Would you call it directly as I have done here or is there
some better way to return?

Thanks,
/*Raj*/
 
W

Walter Roberson

RajW said:
Disclaimer: I'm new to C.
Basically menuinput() waits for the key press, and passes it to the
switch below.
int menuinput() {
unsigned char menukey;
fflush (stdout);
menukey = getc();

gotoxy (12,18);

gotoxy(), clearxy(), and putsxy() are not part of standard C.
printf("key pressed: %c", menukey);

I get the impression that you are expecting that key presses
will be available "immediately" (or nearly so) to the program --
that the program will be able to read off the keys as the user
enters them.

In standard C, there is no way of configuring for "immediate"
input: there is no way that one can be sure that the input will
be available to the program until the user enters the end-of-line
sequence (e.g., often a carriage return that gets translated
to newline by the line protocol layer.)

If you are using gotoxy() and kin, you are using extensions to
standard C and those extensions probably provide a mechanism to
configure single-character I/O -- but it isn't portable to
other systems that do not have the same extension.
 
R

Rod Pemberton

RajW said:
Disclaimer: I'm new to C.

I'm building a simple text based program and I'm not sure I'm
designing it correctly. What I have is simple and it works but it just
seems weird. Is there a better way? I do still have some debugging
code in the subroutine to print out the key pressed.

Basically menuinput() waits for the key press, and passes it to the
switch below. What I'm confused about is, what is the best way to get
back to the menu input subroutine? At the end of the routine that was
called, should I just call menuinput() again?

Since this seems OS specific (DOS?), some people aren't responding...

You want to call menuinput() again but not from within menuinput() (i.e.,
delete that line). It would be best if in a loop. Menuinput probably should
return a non-zero value when you want to exit the loop:

int main(void)
{
int status;
do {
/* ... */
status=menuinput();
/* ... */
} while(!status);
}

I don't know which OS your using (looks like DOS), you might want use
non-blocking functions. A non-blocking function doesn't wait for a
response. This allows your loop to keep executing and polling other events,
like a mouse:

int main(void)
{
int status;
do {
/* ... */
status=menuinput();
status|=mouseinput();
/* ... */
} while(!status);
}

As soon as the non-blocking mouse or keyboard returns a "event," your loop
exits.


Rod Pemberton
 
C

CBFalconer

RajW said:
Disclaimer: I'm new to C.

I'm building a simple text based program and I'm not sure I'm
designing it correctly. What I have is simple and it works but it just
seems weird. Is there a better way? I do still have some debugging
code in the subroutine to print out the key pressed.

Basically menuinput() waits for the key press, and passes it to the
switch below. What I'm confused about is, what is the best way to get
back to the menu input subroutine? At the end of the routine that was
called, should I just call menuinput() again?

Try this routine. It is portable, unlike the <snipped> code you
posted. Compile with -DTESTING (under gcc) for a test program.

/* -------------------- file menuget.h -------------------- */
/* public domain, by C.B. Falconer. Attribution appreciated */

#ifndef H_menuget_h
# define H_menuget_h

# ifdef __cplusplus
extern "C" {
# endif

#include <stdio.h>

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

int skipblanks(FILE *f);

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

int flushln(FILE *f);

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

/* 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
*/
int menuget(const char *prompt, /* whatever prompt is needed */
const char *acceptable); /* list of acceptable ans */

# ifdef __cplusplus
}
# endif

#endif
/* ----------- file menuget.h ------------ */

/* -------------------- file menuget.c -------------------- */
/* public domain, by C.B. Falconer. Attribution appreciated */

#include <ctype.h>
#include <string.h>
#include "menuget.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
*/
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 */

#ifdef TESTING

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

int main(void)
{
int ch;

do {
ch = menuget("\nA a all cases\n"
"n nonsense\n"
"x exit : ",
"Aanx");
switch (ch) {
case 'a':
case 'A': puts("All cases"); break;
case 'n': puts("nonsense"); break;
case 'x':
case EOF: /* ignore here */ break;
default: puts("Ooops"); break;
}
} while (('x' != ch) && (EOF != ch));

if (EOF == ch) puts("EOF encountered");
return 0;
} /* main */

#endif
/* ----------- file menuget.c ------------ */

--
"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/>
 
R

RajW

Since this seems OS specific (DOS?), some people aren't responding...

You'll get a laugh when I tell what I'm programming this for...

You ready?

A Commodore 64! I'm using CC65 (6502 cross compiler) to create a
program to help me troubleshoot 1541 disk drives.

Thanks,
/*Raj*/
 
R

Rod Pemberton

RajW said:
You'll get a laugh when I tell what I'm programming this for...

You ready?

A Commodore 64! I'm using CC65 (6502 cross compiler) to create a
program to help me troubleshoot 1541 disk drives.

No I won't. I've got a stack of them in the basement, various disks, C64
Programmers Reference with schematics, ABACUS books with dissassembled C64
and 1541 roms, the Howard W. Sams schematics for the 1541, original MOS
Technologies 6502 manual etc., etc... I think they were last fired up
around 92-94...(Ironic, I was programming on VAXen then...But, of course the
PC didn't get a decent color video card until 94 either...The Amiga's had
that in 86)

Saving some games? Certain copyrighted 5 1/4 disks had a visible dot on the
bottom side, called a 'laser dot' where the disk wouldn't store data. The
track would return an error it you attempted to read it and wouldn't save
data if you attempted to write to it.

The early (brown) 1541's had a low quality metal frame which expanded too
much when heated. So some disks are only readable when the drive is cool
and others only when hot. They also had problems maintaining alignment of
track zero. IIRC, all but the last version of the brown 1541's had a trim
pot inside that could be used to adjust this but you needed the Sams
schematics and an oscilloscope. The final version of the brown drives they
changed and reduced the circuitry. The later (light tan, or was it white?)
drives worked properly. You may still be able to find the C64 Hacking zine
which was available from around 92-94. There were schematics of 1541 to PC
interface cables which were pretty simple. A number of decent emulators for
the PC popped up a few years later. You might want to check to see if the
MAME arcade emulator runs C64 games now...

The 1541 had it's own cpu, ram, and bios with bunch of commands that you
could send from the C64 to program it. Let's see, track 18 was the
directory right? For files, the first two bytes of each sector was a
pointer to the next sector in the file chain. Sort of like, a distributed
FAT table. It used a layout that was a holdover from the CBM mainframes.

At one point in time I had written a 6510 disassembler which showed how each
instruction affected each flag. I used this to allow me to write pieces of
code, each of which only modified a certain flag. Essentially, this was
extremely primitive multitasking or threading.


Rod Pemberton
 
R

RajW

No I won't. I've got a stack of them in the basement, various disks, C64
Programmers Reference with schematics, ABACUS books with dissassembled C64
and 1541 roms, the Howard W. Sams schematics for the 1541, original MOS
Technologies 6502 manual etc., etc... I think they were last fired up
around 92-94...(Ironic, I was programming on VAXen then...But, of course the
PC didn't get a decent color video card until 94 either...The Amiga's had
that in 86)


Impressive! You should come over to comp.sys.cbm ... quite a few of us
still left.

I've been repairing 1541's and other Commodore equipment for quite a
while now. I just needed a tool to help me which I had not seen
anywhere before... So I wrote it. :)

Thanks,
/*Raj*/
 
R

RajW

int main(void)
{
int status;
do {
/* ... */
status=menuinput();
status|=mouseinput();
/* ... */
} while(!status);
}

Good idea (and programming methodology). :) I'll rewrite that portion
of my program.

Thanks!
/*Raj*/
 

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,756
Messages
2,569,533
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top