A basic primitive interactive system

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • sugaray

    #1

    A basic primitive interactive system

    Right now, the code I wrote below seems works fine, i know it's definitely
    not the best solution, so if there are better solutions to
    eschew from using goto statements to jump out of multiple loops ?
    and any other suggestions or good ideas that are pertain to construct
    a more powerful and common interactive menu system is also welcomed,
    and if there's any primitive but better interactive system that is
    written in C suitable for educational purpose you happen to know of,
    let me know please, i need a good and relatively easy one to tamper
    with in order to build my skill, thanx in advance for your help.

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

    static const char prompt = '#';
    int prompt_mode = 0;

    static void
    promptmode (void)
    {
    int i;
    for (i = 0; i < prompt_mode; ++i)
    printf ("%c", prompt);
    printf (">");
    }

    static void
    level1menu (void)
    {
    printf ("\n======== === LEVEL-1 MENU ============\n" );
    printf ("| 1. HELP MESSAGES |\n");
    printf ("| 2. ENTER LEVEL-2 |\n");
    printf ("| 3. DISPLAY THIS MENU |\n");
    printf ("| 4. QUIT THE SYSTEM |\n");
    printf ("============= =============== =========\n\n") ;
    }

    static void
    level2menu (void)
    {
    printf ("\n******** *** LEVEL-2 MENU ************\n" );
    printf ("| 1. HELP MESSAGES |\n");
    printf ("| 2. FUNCTIONALITIES |\n");
    printf ("| 3. DISPLAY THIS MENU |\n");
    printf ("| 4. BACK TO THE UPPER LEVEL |\n");
    printf ("************* *************** *********\n\n") ;
    }

    static int
    getchoice (void)
    {
    char input[4];

    fgets (input, sizeof input, stdin);
    fflush (stdout);
    input[strlen (input) - 1] = '\0';
    return atoi (input);
    }


    int
    main (void)
    {
    int choice;

    level1:
    level1menu ();
    for (;;)
    {
    prompt_mode = 1;
    fflush(stdin);
    promptmode ();

    choice = getchoice ();

    if (choice < 1 || choice > 4)
    continue;

    switch (choice)
    {
    case 1:
    printf ("help messages for level 1.\n");
    break;
    case 2:
    prompt_mode = 2;
    level2menu ();
    for (;;)
    {
    fflush(stdin);
    promptmode ();

    choice = getchoice ();

    if (choice < 1 || choice > 4)
    continue;

    switch (choice)
    {
    case 1:
    printf ("display help messages for level 2.\n");
    break;
    case 2:
    printf ("implement functionalities .\n");
    break;
    case 3:
    level2menu ();
    break;
    case 4:
    printf ("back to the upper level.\n");
    goto level1;
    default:
    printf ("invalid option in level 2.\n");
    }
    }
    break;
    case 3:
    level1menu ();
    break;
    case 4:
    goto end;
    default:
    printf ("invalid option in level 1.\n");
    }

    }
    end:
    printf ("\nsee ya ;)\n");

    return 0;
    }
  • Darrell Grainger

    #2
    Re: A basic primitive interactive system

    On Tue, 8 Jun 2004, sugaray wrote:
    [color=blue]
    > Right now, the code I wrote below seems works fine, i know it's definitely
    > not the best solution, so if there are better solutions to
    > eschew from using goto statements to jump out of multiple loops ?
    > and any other suggestions or good ideas that are pertain to construct
    > a more powerful and common interactive menu system is also welcomed,
    > and if there's any primitive but better interactive system that is
    > written in C suitable for educational purpose you happen to know of,
    > let me know please, i need a good and relatively easy one to tamper
    > with in order to build my skill, thanx in advance for your help.
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <string.h>
    >
    > static const char prompt = '#';
    > int prompt_mode = 0;
    >
    > static void
    > promptmode (void)
    > {
    > int i;
    > for (i = 0; i < prompt_mode; ++i)
    > printf ("%c", prompt);
    > printf (">");[/color]

    You want to have a fflush(stdout) here. Without it, you might not see this
    prompt.
    [color=blue]
    > }
    >
    > static void
    > level1menu (void)
    > {
    > printf ("\n======== === LEVEL-1 MENU ============\n" );
    > printf ("| 1. HELP MESSAGES |\n");
    > printf ("| 2. ENTER LEVEL-2 |\n");
    > printf ("| 3. DISPLAY THIS MENU |\n");
    > printf ("| 4. QUIT THE SYSTEM |\n");
    > printf ("============= =============== =========\n\n") ;
    > }
    >
    > static void
    > level2menu (void)
    > {
    > printf ("\n******** *** LEVEL-2 MENU ************\n" );
    > printf ("| 1. HELP MESSAGES |\n");
    > printf ("| 2. FUNCTIONALITIES |\n");
    > printf ("| 3. DISPLAY THIS MENU |\n");
    > printf ("| 4. BACK TO THE UPPER LEVEL |\n");
    > printf ("************* *************** *********\n\n") ;
    > }
    >
    > static int
    > getchoice (void)
    > {
    > char input[4];
    >
    > fgets (input, sizeof input, stdin);
    > fflush (stdout);[/color]

    Why are you flushing stdout here? You have not output anything so this
    seems pointless. I'd remove this.
    [color=blue]
    > input[strlen (input) - 1] = '\0';[/color]

    This line assumes you want to get rid of the last character. Are you
    assuming the user input less than 3 characters plus the newline? With
    input holding 4 elements you will have 2 significant characters, the
    newline and the terminating null character. What if the user inputs a long
    string of text? I'm not clear on what you want to do here so I'm wondering
    if this will handle the negative test scenarios.
    [color=blue]
    > return atoi (input);[/color]

    You understand that if the user inputs "hohoho" this function will return
    zero.
    [color=blue]
    > }
    >
    >
    > int
    > main (void)
    > {
    > int choice;
    >
    > level1:
    > level1menu ();
    > for (;;)
    > {
    > prompt_mode = 1;
    > fflush(stdin);[/color]

    Undefined behaviour. Don't flush input streams. There is no guarantee what
    this will do.
    [color=blue]
    > promptmode ();
    >
    > choice = getchoice ();
    >
    > if (choice < 1 || choice > 4)
    > continue;[/color]

    This makes the default case in the switch unreachable.
    [color=blue]
    > switch (choice)
    > {
    > case 1:
    > printf ("help messages for level 1.\n");
    > break;
    > case 2:
    > prompt_mode = 2;
    > level2menu ();
    > for (;;)
    > {
    > fflush(stdin);[/color]

    Undefined behaviour.
    [color=blue]
    > promptmode ();
    >
    > choice = getchoice ();
    >
    > if (choice < 1 || choice > 4)
    > continue;[/color]

    This makes the default case in the switch unreachable.
    [color=blue]
    > switch (choice)
    > {
    > case 1:
    > printf ("display help messages for level 2.\n");
    > break;
    > case 2:
    > printf ("implement functionalities .\n");
    > break;
    > case 3:
    > level2menu ();
    > break;
    > case 4:
    > printf ("back to the upper level.\n");
    > goto level1;
    > default:
    > printf ("invalid option in level 2.\n");
    > }
    > }
    > break;
    > case 3:
    > level1menu ();
    > break;
    > case 4:
    > goto end;
    > default:
    > printf ("invalid option in level 1.\n");
    > }
    >
    > }
    > end:
    > printf ("\nsee ya ;)\n");
    >
    > return 0;
    > }[/color]

    First, the formatting is a bother. I like to have all the text on one
    screen. Having to scroll up and down in the main function makes it a little
    difficult to read.

    Even when I do reformat it, I look at it and think this is still not the
    easiest thing to read. Obviously, you are thinking about the use of goto.
    You cannot 'break' out of the inner for loop because you are using switch
    statements.

    I tend to use switch statements if they make the code more readable. To
    most compilers a set of if/else if/else statements and a switch statement
    are not going to be a huge different. Even if they are, you can change it
    later (after profiling). When I have something like:

    if(n == 1 || n == 7 || n == 9 || n == 11 || n == 16 || n == 21)
    /* do something */

    and the number of 'expr#' is actually much longer, this can get a little
    ugly to read. It reads better, to me, as:

    switch(n) {
    case 1:
    case 7:
    case 9:
    case 11:
    case 16:
    case 21:
    /* do something */
    break;
    }

    In your case, using the switch statement does not seem to help readability
    and it is actually causing problems when you want to break out of the
    loops. Just switch to if statements.

    --
    Send e-mail to: darrell at cs dot toronto dot edu
    Don't send e-mail to vice.president@ whitehouse.gov

    Comment

    • Karthik

      #3
      Re: A basic primitive interactive system

      sugaray wrote:
      [color=blue]
      > Right now, the code I wrote below seems works fine, i know it's definitely
      > not the best solution, so if there are better solutions to
      > eschew from using goto statements to jump out of multiple loops ?
      > and any other suggestions or good ideas that are pertain to construct
      > a more powerful and common interactive menu system is also welcomed,
      > and if there's any primitive but better interactive system that is
      > written in C suitable for educational purpose you happen to know of,
      > let me know please, i need a good and relatively easy one to tamper
      > with in order to build my skill, thanx in advance for your help.
      >
      > #include <stdio.h>
      > #include <stdlib.h>
      > #include <string.h>
      >
      > static const char prompt = '#';
      > int prompt_mode = 0;
      >
      > static void
      > promptmode (void)
      > {
      > int i;
      > for (i = 0; i < prompt_mode; ++i)
      > printf ("%c", prompt);
      > printf (">");
      > }
      >
      > static void
      > level1menu (void)
      > {
      > printf ("\n======== === LEVEL-1 MENU ============\n" );
      > printf ("| 1. HELP MESSAGES |\n");
      > printf ("| 2. ENTER LEVEL-2 |\n");
      > printf ("| 3. DISPLAY THIS MENU |\n");
      > printf ("| 4. QUIT THE SYSTEM |\n");
      > printf ("============= =============== =========\n\n") ;
      > }
      >
      > static void
      > level2menu (void)
      > {
      > printf ("\n******** *** LEVEL-2 MENU ************\n" );
      > printf ("| 1. HELP MESSAGES |\n");
      > printf ("| 2. FUNCTIONALITIES |\n");
      > printf ("| 3. DISPLAY THIS MENU |\n");
      > printf ("| 4. BACK TO THE UPPER LEVEL |\n");
      > printf ("************* *************** *********\n\n") ;[/color]

      Generally printfs are costly. So you need to avoid the number of
      times it is invoked.
      printf ("\n******** *** LEVEL-2 MENU ************\n"
      "| 1. HELP MESSAGES |\n"
      "| 2. FUNCTIONALITIES |\n"
      "| 3. DISPLAY THIS MENU |\n"
      "| 4. BACK TO THE UPPER LEVEL |\n" );

      is way ahead, in terms of performance compared to the previous code.

      Smarter programmers use macros , whenever they need to write constants
      in the code ( as above ).
      [color=blue]
      > }
      >
      > static int
      > getchoice (void)
      > {
      > char input[4];
      >
      > fgets (input, sizeof input, stdin);[/color]

      What happens, if i enter more than 3 chars.
      [color=blue]
      > fflush (stdout);
      > input[strlen (input) - 1] = '\0';
      > return atoi (input);
      > }
      >
      >
      > int
      > main (void)
      > {
      > int choice;
      >
      > level1:
      > level1menu ();
      > for (;;)[/color]

      Some people prefer a while (1) loop , though it is more a matter of
      style.
      [color=blue]
      > {
      > prompt_mode = 1;
      > fflush(stdin);
      > promptmode ();
      >
      > choice = getchoice ();
      >
      > if (choice < 1 || choice > 4)
      > continue;
      >
      > switch (choice)
      > {
      > case 1:
      > printf ("help messages for level 1.\n");
      > break;
      > case 2:
      > prompt_mode = 2;
      > level2menu ();
      > for (;;)
      > {
      > fflush(stdin);
      > promptmode ();
      >
      > choice = getchoice ();
      >
      > if (choice < 1 || choice > 4)
      > continue;
      >
      > switch (choice)
      > {
      > case 1:
      > printf ("display help messages for level 2.\n");
      > break;
      > case 2:
      > printf ("implement functionalities .\n");
      > break;
      > case 3:
      > level2menu ();
      > break;
      > case 4:
      > printf ("back to the upper level.\n");
      > goto level1;
      > default:
      > printf ("invalid option in level 2.\n");
      > }
      > }
      > break;
      > case 3:
      > level1menu ();
      > break;
      > case 4:
      > goto end;[/color]

      gotos are evil. That should be your last resort , really when
      nothing else on earth works for you.

      [color=blue]
      > default:
      > printf ("invalid option in level 1.\n");
      > }
      >
      > }
      > end:
      > printf ("\nsee ya ;)\n");
      >
      > return 0;
      > }[/color]


      --
      Karthik.
      Humans please 'removeme_' for my real email.

      Comment

      • Thomas Matthews

        #4
        Re: A basic primitive interactive system

        sugaray wrote:
        [color=blue]
        > Right now, the code I wrote below seems works fine, i know it's definitely
        > not the best solution, so if there are better solutions to
        > eschew from using goto statements to jump out of multiple loops ?
        > and any other suggestions or good ideas that are pertain to construct
        > a more powerful and common interactive menu system is also welcomed,
        > and if there's any primitive but better interactive system that is
        > written in C suitable for educational purpose you happen to know of,
        > let me know please, i need a good and relatively easy one to tamper
        > with in order to build my skill, thanx in advance for your help.[/color]
        [Sound of knuckles crackling as I stretch out my fingers]
        [color=blue]
        >
        > #include <stdio.h>
        > #include <stdlib.h>
        > #include <string.h>
        >
        > static const char prompt = '#';[/color]
        You may be performing "premature optimization" with this one.
        One byte may not be enough reason to declare it as a constant.
        Check with you compiler for that.

        [color=blue]
        > int prompt_mode = 0;[/color]
        Global variable. Get rid of it.
        If you can't get rid of it, make it static, to hide it from
        other modules.

        [color=blue]
        >
        > static void
        > promptmode (void)
        > {
        > int i;
        > for (i = 0; i < prompt_mode; ++i)
        > printf ("%c", prompt);
        > printf (">");
        > }[/color]
        static void display_prompt( unsigned int prompt_level)
        {
        unsigned int i;
        for (i = 0; i < prompt_level; ++i)
        {
        putchar('#');
        }
        putchar('>');
        return;
        }

        The above function eliminates the dependency on a global
        variable, and also doesn't use "printf" because there
        is no need for the output to be formatted.

        [color=blue]
        >
        > static void
        > level1menu (void)
        > {
        > printf ("\n======== === LEVEL-1 MENU ============\n" );
        > printf ("| 1. HELP MESSAGES |\n");
        > printf ("| 2. ENTER LEVEL-2 |\n");
        > printf ("| 3. DISPLAY THIS MENU |\n");
        > printf ("| 4. QUIT THE SYSTEM |\n");
        > printf ("============= =============== =========\n\n") ;
        > }[/color]
        A direct replacement:
        static void level1menu(void )
        {
        static const char menu_text[] =
        "\n"
        "========== = LEVEL-1 MENU ============\n"
        "| 1. HELP MESSAGES |\n"
        "| 2. ENTER LEVEL-2 |\n"
        "| 3. DISPLAY THIS MENU |\n"
        "| 4. QUIT THE SYSTEM |\n"
        "============== =============== ========\n"
        "\n";
        fwrite(menu_tex t,
        sizeof(char),
        sizeof(menu_tex t) - 1,
        stdout);
        return;
        }

        I would prefer to make this as static data local to the module,
        and use a table driven system to print them out (discussed below).

        [color=blue]
        >
        > static void
        > level2menu (void)
        > {
        > printf ("\n******** *** LEVEL-2 MENU ************\n" );
        > printf ("| 1. HELP MESSAGES |\n");
        > printf ("| 2. FUNCTIONALITIES |\n");
        > printf ("| 3. DISPLAY THIS MENU |\n");
        > printf ("| 4. BACK TO THE UPPER LEVEL |\n");
        > printf ("************* *************** *********\n\n") ;
        > }[/color]
        static void level2menu(void )
        {
        static const char menu_text[] =
        "\n"
        "********** * LEVEL-2 MENU ************\n"
        "| 1. HELP MESSAGES |\n"
        "| 2. FUNCTIONALITIES |\n"
        "| 3. DISPLAY THIS MENU |\n"
        "| 4. BACK TO THE UPPER LEVEL |\n"
        "************** *************** ********\n"
        "\n"
        fwrite(menu_tex t,
        sizeof(char),
        sizeof(menu_tex t) - 1,
        stdout);
        return;
        }

        Note how the code of the two above functions is the
        same, but only the data changes. Hmmmm....

        [color=blue]
        >
        > static int
        > getchoice (void)
        > {
        > char input[4];
        >
        > fgets (input, sizeof input, stdin);
        > fflush (stdout);
        > input[strlen (input) - 1] = '\0';
        > return atoi (input);
        > }[/color]
        This doesn't return any kind of error, especially
        if the user types in text rather than numbers.

        [color=blue]
        >
        >
        > int
        > main (void)
        > {
        > int choice;
        >
        > level1:
        > level1menu ();
        > for (;;)
        > {
        > prompt_mode = 1;
        > fflush(stdin);
        > promptmode ();
        >
        > choice = getchoice ();
        >
        > if (choice < 1 || choice > 4)
        > continue;
        >
        > switch (choice)
        > {
        > case 1:[/color]
        "help messages for level 1.\n"[color=blue]
        > break;
        > case 2:
        > prompt_mode = 2;
        > level2menu ();
        > for (;;)
        > {
        > fflush(stdin);
        > promptmode ();
        >
        > choice = getchoice ();
        >
        > if (choice < 1 || choice > 4)
        > continue;
        >
        > switch (choice)
        > {
        > case 1:[/color]
        "display help messages for level 2.\n"[color=blue]
        > break;
        > case 2:[/color]
        "implement functionalities .\n"[color=blue]
        > break;
        > case 3:
        > level2menu ();
        > break;
        > case 4:[/color]
        "back to the upper level.\n"[color=blue]
        > goto level1;
        > default:[/color]
        "invalid option in level 2.\n"[color=blue]
        > }
        > }
        > break;
        > case 3:
        > level1menu ();
        > break;
        > case 4:
        > goto end;
        > default:[/color]
        "invalid option in level 1.\n"[color=blue]
        > }
        >
        > }
        > end:[/color]
        "\nsee ya ;)\n"[color=blue]
        >
        > return 0;
        > }[/color]
        Arrrrgggghhh: labels, gotos and switch statement.

        /* Create a typedef for a pointer to a function that
        * will process a menu selection.
        */
        typedef (void) (*Ptr_Menu_Proc _Func)(void);

        struct MenuItem
        {
        unsigned int number;
        Ptr_Menu_Proc_F unc processing_func tion;
        };

        void Level1_Help_Mes sages(void)
        {
        puts("Processed Level 1 Help Messages.\n");
        return;
        }

        void Enter_Level_2(v oid)
        {
        puts("Level 2 requested.\n");
        return;
        }

        void Null_Entry(void )
        {
        return;
        }

        static struct MenuItem menu_choices[] =
        {
        {0, Null_Entry},
        {1, Level1_Help_Mes sages},
        {2, Enter_Level_2},
        {3, Null_Entry},
        {4, Null_Entry}
        };
        static const unsigned int NUM_CHOICES =
        sizeof(menu_cho ices) / sizeof(menu_cho ices[0]);

        static const char menu_text[] =
        "\n"
        "========== = LEVEL-1 MENU ============\n"
        "| 1. HELP MESSAGES |\n"
        "| 2. ENTER LEVEL-2 |\n"
        "| 3. DISPLAY THIS MENU |\n"
        "| 4. QUIT THE SYSTEM |\n"
        "============== =============== ========\n"
        "\n";


        #define MAX_LENGTH_OF_C HOICE 16

        int main(void)
        {
        unsigned long choice;
        char choice_text[MAX_LENGTH_OF_C HOICE];
        char * s;

        do
        {
        do
        {
        /* display the menu */
        fwrite(menu_tex t,
        sizeof(char),
        sizeof(menu_tex t) - 1,
        stdout);

        /* display prompt */
        display_prompt( 1);

        /* Get user selection */
        fgets(choice_te xt, MAX_LENGTH_OF_C HOICE, stdin);
        choice = strtoul(choice_ text, &s, 10);
        } while ((choice < 1) || (choice >= NUM_CHOICES));

        /* Execute menu processing function */
        menu_choices[choice].processing_fun ction();

        } while (choice != 4);

        return EXIT_SUCCESS;
        }

        This could be upgraded so that the menu displaying
        function uses the numbers in the menu_choices. One
        could also expand the Menu_Item structure to contain
        the selection text. Thus this task would be data
        driven. Just pass in a pointer to an array of
        Menu_Item and the number of items.


        --
        Thomas Matthews

        C++ newsgroup welcome message:

        C++ Faq: http://www.parashift.com/c++-faq-lite
        C Faq: http://www.eskimo.com/~scs/c-faq/top.html
        alt.comp.lang.l earn.c-c++ faq:

        Other sites:
        http://www.josuttis.com -- C++ STL Library book

        Comment

        • Arthur J. O'Dwyer

          #5
          Re: A basic primitive interactive system


          On Tue, 8 Jun 2004, Karthik wrote:[color=blue]
          >
          > sugaray wrote:[color=green]
          > >
          > > static void
          > > level2menu (void)
          > > {
          > > printf ("\n******** *** LEVEL-2 MENU ************\n" );
          > > printf ("| 1. HELP MESSAGES |\n");
          > > printf ("| 2. FUNCTIONALITIES |\n");
          > > printf ("| 3. DISPLAY THIS MENU |\n");
          > > printf ("| 4. BACK TO THE UPPER LEVEL |\n");
          > > printf ("************* *************** *********\n\n") ;[/color]
          >
          > Generally printfs are costly. So you need to avoid the number of
          > times it is invoked.
          > printf ("\n******** *** LEVEL-2 MENU ************\n"
          > "| 1. HELP MESSAGES |\n"
          > "| 2. FUNCTIONALITIES |\n"
          > "| 3. DISPLAY THIS MENU |\n"
          > "| 4. BACK TO THE UPPER LEVEL |\n" );
          >
          > is way ahead, in terms of performance compared to the previous code.[/color]

          You might be interested to know that the *reason* printfs are
          costly is because the 'printf' function has to parse through the
          whole string looking for format specifiers before it can print
          any of it (format specifiers being things like "%s" and "%d").[1]
          So you'll find an even bigger performance advantage to just write
          what you mean:

          puts("");
          puts("********* ** LEVEL-2 MENU ************");
          puts("| 1. HELP MESSAGES |");
          puts("| 2. FUNCTIONALITIES |");
          puts("| 3. DISPLAY THIS MENU |");
          puts("| 4. BACK TO THE UPPER LEVEL |");
          puts("********* *************** *************") ;
          puts("");

          Merging all your strings into one big string might save you a couple
          of cycles, but it tends to hurt readability more.
          [color=blue]
          > Smarter programmers use macros , whenever they need to write constants
          > in the code ( as above ).[/color]

          Do you mean this line?
          [color=blue][color=green]
          > > static const char prompt = '#';[/color][/color]

          Using my current style, I'd have made that

          static const char *PromptIndent = "#";

          and made the appropriate changes elsewhere, thus setting the
          program up to allow the user to change the prompt-indent string
          to something other than "#". The macro solution, FWIW, might be

          #define PROMPT '#'

          with appropriate changes elsewhere.

          [color=blue][color=green]
          > > static int
          > > getchoice (void)
          > > {
          > > char input[4];
          > > fgets (input, sizeof input, stdin);[/color]
          >
          > What happens, if i enter more than 3 chars.
          >[color=green]
          > > fflush (stdout);
          > > input[strlen (input) - 1] = '\0';
          > > return atoi (input);[/color][/color]

          And if all you're doing is trying to read an integer, without
          caring about error-checking or anything else (which seems to be
          the case), then

          int input = -1;
          scanf("%d", &input);
          while (getchar() != '\n');
          return input;

          seems like the way to go. No muss, no fuss.

          -Arthur

          [1] - FWIW, 'gcc' is smart enough to use 'puts' in place of
          'printf' whenever the latter is called with only one argument.
          Other compilers *may* not be so smart, though.

          Comment

          • sugaray

            #6
            Re: A basic primitive interactive system

            Thomas Matthews <Thomas_Matthew sSpitsOnSpamBot s@sbcglobal.net > wrote in message news:<nhkxc.639 0$n65.1890@news svr33.news.prod igy.com>...[color=blue]
            > /* Create a typedef for a pointer to a function that
            > * will process a menu selection.
            > */
            > typedef (void) (*Ptr_Menu_Proc _Func)(void);
            >
            > struct MenuItem
            > {
            > unsigned int number;
            > Ptr_Menu_Proc_F unc processing_func tion;
            > };
            >
            > void Level1_Help_Mes sages(void)
            > {
            > puts("Processed Level 1 Help Messages.\n");
            > return;
            > }
            >
            > void Enter_Level_2(v oid)
            > {
            > puts("Level 2 requested.\n");
            > return;
            > }
            >
            > void Null_Entry(void )
            > {
            > return;
            > }
            >
            > static struct MenuItem menu_choices[] =
            > {
            > {0, Null_Entry},
            > {1, Level1_Help_Mes sages},
            > {2, Enter_Level_2},
            > {3, Null_Entry},
            > {4, Null_Entry}
            > };
            > static const unsigned int NUM_CHOICES =
            > sizeof(menu_cho ices) / sizeof(menu_cho ices[0]);
            >
            > static const char menu_text[] =
            > "\n"
            > "========== = LEVEL-1 MENU ============\n"
            > "| 1. HELP MESSAGES |\n"
            > "| 2. ENTER LEVEL-2 |\n"
            > "| 3. DISPLAY THIS MENU |\n"
            > "| 4. QUIT THE SYSTEM |\n"
            > "============== =============== ========\n"
            > "\n";
            >
            >
            > #define MAX_LENGTH_OF_C HOICE 16
            >
            > int main(void)
            > {
            > unsigned long choice;
            > char choice_text[MAX_LENGTH_OF_C HOICE];
            > char * s;
            >
            > do
            > {
            > do
            > {
            > /* display the menu */
            > fwrite(menu_tex t,
            > sizeof(char),
            > sizeof(menu_tex t) - 1,
            > stdout);
            >
            > /* display prompt */
            > display_prompt( 1);
            >
            > /* Get user selection */
            > fgets(choice_te xt, MAX_LENGTH_OF_C HOICE, stdin);
            > choice = strtoul(choice_ text, &s, 10);
            > } while ((choice < 1) || (choice >= NUM_CHOICES));
            >
            > /* Execute menu processing function */
            > menu_choices[choice].processing_fun ction();
            >
            > } while (choice != 4);
            >
            > return EXIT_SUCCESS;
            > }
            >
            > This could be upgraded so that the menu displaying
            > function uses the numbers in the menu_choices. One
            > could also expand the Menu_Item structure to contain
            > the selection text. Thus this task would be data
            > driven. Just pass in a pointer to an array of
            > Menu_Item and the number of items.
            >
            >
            > --
            > Thomas Matthews[/color]

            Thanx for your suggestions and code samples, Tom ! ;-)

            Comment

            Working...