Thread: Making menu

  1. #1
    Registered User
    Join Date
    Mar 2013
    Posts
    6

    Making menu

    Hi,
    I'm trying to do something like menu. my goal is to make it work using only w/s/up/down. But first i have to face some problems with "jumping" between screens.
    My entire menu is a function, and i created 3 different "skins". "Player" must click for example "s" on keyboard(without confirmation) and the skin will jump to another one. here starts my problem. First i'd like to just allow it jump. here's my code:

    Code:
    void menu(void)
    {
            system("cls");//to clear previous screen
            printf("===========================  1.>>NEW GAME<< ===================================\n");
            printf("===========================  2.    HELP     ===================================\n");
            printf("===========================  3.    QUIT     ===================================\n");
            char c;
            c=getch();
            if((int)c==83) //asci number for s
            {fflush(stdin); //it should clear previous choice
            printf("===========================  1.  NEW GAME   ===================================\n");
            printf("===========================  2.  >>HELP<<   ===================================\n");
            printf("===========================  3.    QUIT     ===================================\n");
            c=getch();
            if((int)c==83)
            {printf("===========================  1.  NEW GAME   ===================================\n");
            printf("===========================  2.    HELP     ===================================\n");
            printf("===========================  3.  >>QUIT<<   ===================================\n");}}
    }
    It compiles but it doesn't work. The program quits after i hit "s". But it shouldn't. it should jump down to second "screen"(where help is between >> <<) and after another click it should jump to last "screen".
    I'm also not sure what should i use to work it forever. Loop or goto: ?

    Any help would be highly appreciated.

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    You do know that the ASCII Value for 's' is not 83, correct? That is the value for 'S'. Why are you even casting the char to an int? Why not just compare it to the char?

    Code:
    if(c == 'S')
    Also fflush() is not defined to work on input streams, only output streams.

    Jim

  3. #3
    Registered User
    Join Date
    Mar 2013
    Posts
    6
    Thanks for pointing me out my mistakes. So what should i use instead of fflush(), or how i should use it?
    I've already tried something like that:
    Code:
    char c;
    scanf("%c",&c);
    getchar();
    i've read somwhere that this is the way to replace fflush(), but it doesn't work.
    Btw. Everything work just fine, but i need to clear the buffer because program doesn't wait for getchar, instead of it uses char from kbhit() i used in another function.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    You may to reverse the function calls, the way it is now setup the scanf() will retrieve what ever character you pressed in your kbhit(). Then wait for another value to be entered for the getchar().

    Code:
    char c;
    getchar();  // Retrieve the previous character left by your kbit() call.
    scanf("%c",&c);
    I myself would remove the character in the offending function so you don't have this problem here.


    Jim

  5. #5
    Registered User
    Join Date
    Mar 2013
    Posts
    6
    well. i still have some problems. So this is my program. or at least parts which makes troubles(think i cut everything that isn't usefull here. nobody wants to read 500 lines).

    Code:
    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <windows.h>
    
    void powitanie(void)
    {
        while(1)
        {   if (kbhit()) //break after first hit
                {
                    break;
                }
            system("cls");
            printf("==============================  WELCOME  ======================================\n");
            printf("                                                                               \n");
            Sleep(800);
            system("cls");
            printf("==============================  WELCOME  ======================================\n");
            printf("                            <press any key>                                    \n");
            Sleep(800);
        }
    }
    
    void menu(void)
    {
            char c;
            system("cls");
            printf("================================  MENU  =======================================\n");
            printf("===========================  1.>>NEW GAME<< ===================================\n");
            printf("===========================  2.    HELP     ===================================\n");
            printf("===========================  3.    QUIT     ===================================\n");
            getch();
            scanf("%c",&c);
            if((int)c == 83)
            {system("cls");
            printf("================================  MENU  =======================================\n");
            printf("===========================  1.  NEW GAME   ===================================\n");
            printf("===========================  2.  >>HELP<<   ===================================\n");
            printf("===========================  3.    QUIT     ===================================\n");
            getch();
            scanf("%c",&c);
            if ((int)c == 83)
            {system("cls");
            printf("================================  MENU  =======================================\n");
            printf("===========================  1.  NEW GAME   ===================================\n");
            printf("===========================  2.    HELP     ===================================\n");
            printf("===========================  3.  >>QUIT<<   ===================================\n");}}
    }
    
    main()
    {
        powitanie();
        menu();
        getch();
    }
    I'm still using (int)c because i'll need this later.
    But i'm facing 2 problems here:
    1) well. it needs confirmation...
    2) works fine until second scaning. so i have "screen" with >>Help<< but then imediately program ends.

    And I've noticed that if i press "SS" on first scanning and accept it
    it jumps to >>Help<< and then scan next time and if i press "S" it immediately jumps to >>QUIT<< without needing confirmation.

  6. #6
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    I'm still using (int)c because i'll need this later.
    What? Why? You haven't saved anything for later use.

    Why don't you just remove the offending character in the function that is causing the problem?

    Code:
    void powitanie(void)
    {
        while(1)
        {   if (kbhit()) //break after first hit
                {
                    break;
                }
            system("cls");
            printf("==============================  WELCOME  ======================================\n");
            printf("                                                                               \n");
            Sleep(800);
            system("cls");
            printf("==============================  WELCOME  ======================================\n");
            printf("                            <press any key>                                    \n");
            Sleep(800);
        }
        getch(); // throw away the character since it's not needed.
    }
    You may also want to consider having your scanf() skip leading whitespace:

    Code:
    scanf(" %c", c);
    Notice the leading space.

    Jim

  7. #7
    Registered User
    Join Date
    Mar 2013
    Posts
    6
    Ok. It works now. unfortunately not exactly as i planned. i still need confirm after S, and i'd prefer not to.
    Well i'm using (int) because i'd like my program work on arrows. and i've read that you only can use them as the int(). Though i still haven't write a program wich will tell me what's the magic numbers for arrows but i'll work on it later. first i'd like to make it work with W/S

  8. #8
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    If you really want to try to capture the arrow keys I suggest you start thinking about using some kind of graphics library instead to the conio/stdio functions. You may want to investigate SDL, Allegro, etc.

    Jim

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    By arrows you mean arrow keys? It's correct for the input to be read as an int then because an arrow is actually two characters. Look at this:
    Code:
    #include <stdio.h>
    #include <conio.h>
    #include <ctype.h>
    
    int main()
    {
      int ch;
    
      puts ("Press any key, q to quit");
    
      while ((ch = getch()) != EOF && ch != 'q') {
        if (isprint(ch))
          printf ("%c\n", ch);
        else
          putchar('*');
      }
    
      return 0;
    }
    
    /* output:
    
    Press any key, q to quit
    *K
    *M
    *H
    *P
    */
    Each time I pressed an arrow key I got two bytes of input, read separately as we can determine from the output. So you'd read the first byte that tells you it's an arrow key and then read the distinguishing byte for left, right, up and down.

    That's almost beside the point though. If you notice I'm using int anyway for the return value. This is what getch returns. See for yourself.

    There isn't really a reason to avoid an easy to read comparison: ch == 'S'
    Everyone knows what that is. If you have to you can compare a number, but only if you have to, because the character isn't printable.

  10. #10
    Registered User
    Join Date
    Mar 2013
    Posts
    6
    Well ok. but i don't understand why do we argue on using (int)c==83 or c=='S'. i agree that with S is more readable but still it does the same job. Do you know how to omit the confirmation? Last time i've tried to replace getch() with kbhit() but that was pure guess and it didn't work out.

  11. #11
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    kbhit() merely acknowledges that a key was pressed. It cannot replace getch() since you want to know what key it was.

    but i don't understand why do we argue on (int)c==83 or c=='S'. i agree that with S is more readable but still it does the same job.
    We argue because:

    1. (int) is a cast. You can do this same job without a cast. And besides, the functions you are using return int, so there is no reason not to use an int variable here.

    2. Unless you have the ASCII table memorized, 83 is a magic number.

  12. #12
    Registered User
    Join Date
    Mar 2013
    Posts
    6
    you beat me
    just a moment ago i made it work. well under specific circumstances, but still.
    Code:
    char c;
    c=getch();
    if(c == 's')
    i've found out that this works just fine, but i'm facing 2 serious problems again.
    1) how to disable other keys. if i press sth different than "S" program ends
    2) i'ts caused by 1st. if i type key wich has 2 bytes, on welcome screen then first byte is sacrificed on passing to menu screen and second one acts like it was press of a button in menu screen so the program ends because it wasn't "S".

    Edit
    Ok. I've done it using do while.
    Now i have this working more or less. so another question(sorry for bothering). What should i use to loop it? and how should i do it?

    Edit
    Well. i have my menu, but how do i use enter to confirm choice?
    here's my code(don't kill me for using goto. i had absolutelly no idea how to loop it):
    i know it may lost clearance but i'm newbie to programming. Next time i'll do this beter.
    Code:
    void menu(void)
    {
            while(1){
            char c;
            newgame:
            system("cls");
            printf("================================  MENU  =======================================\n");
            printf("===========================  1.>>NEW GAME<< ===================================\n");
            printf("===========================  2.    HELP     ===================================\n");
            printf("===========================  3.    QUIT     ===================================\n");
            do{c=getch();
            if(c == 'w')goto quit;
            if(c == 's')
            {help:
            system("cls");
            printf("================================  MENU  =======================================\n");
            printf("===========================  1.  NEW GAME   ===================================\n");
            printf("===========================  2.  >>HELP<<   ===================================\n");
            printf("===========================  3.    QUIT     ===================================\n");
            do{c=getch();
            if (c == 'w')
                goto newgame;
            if (c == 's')
            {quit:
            system("cls");
            printf("================================  MENU  =======================================\n");
            printf("===========================  1.  NEW GAME   ===================================\n");
            printf("===========================  2.    HELP     ===================================\n");
            printf("===========================  3.  >>QUIT<<   ===================================\n");
            do {c=getch();
            if (c=='s') break;
            if (c=='w') goto help;}
            while(c!='s'&&c!='w');
            }}while (c!='s'&&c!='w');
            }}while(c!='s'&&c!='w');}
    }
    Ok. problems. Enter is coded by 2 bytes and i have no idea how to use it.
    I want to do sth like that:
    Code:
    if(c==ENTER) function();
    Last edited by Ercik; 03-26-2013 at 05:21 PM. Reason: new problem

  13. #13
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I will probably kill you for using goto.

    FWIW, I've been tinkering with this. I haven't done this in a while and it is interesting to me.

    Code:
    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>
    
    #define ARRAYSIZE(me) (sizeof(me) / sizeof(me[0]))
    
    /** SELECT_END is the last highlighted choice in selections. */
    #define SELECT_END 4
    
    void clear (void);
    void menu (void);
    void blit (unsigned int select);
    
    int main()
    {
      menu();
      return 0;
    }
    
    void menu()
    {
      int select = 0;
      int x;
    
      blit(select);
    
      while (x = getch())
      {
        if (x == 'w')
        {
          select -= 2;
          if (select < 0)
            select = 0;
          blit (select);
        }
        else if (x == 's')
        {
          select += 2;
          if (select > SELECT_END)
            select = SELECT_END;
          blit (select);
        }
      }
    }
    
    void clear()
    {
      system("cls"); /* better code here */
    }
    
    void blit (unsigned int select)
    {
      const char *selections[] =
      {
        " >> NEW GAME <<",
        "    NEW GAME   ",
        " >> HELP     <<",
        "    HELP       ",
        " >> QUIT     <<",
        "    QUIT       ",
      };
      unsigned int i;
    
      clear();
      
      for (i = 0; i < ARRAYSIZE(selections); i += 2)
      {
        if (i == select)
          printf ("%s\n", selections[i]);
        else
          printf ("%s\n", selections[i + 1]);
      }
    
      printf ("Enter choices. Close window to quit.\n");
    }
    Compile that and play with it. To know what selection was made, you can modify this to return a specific value to more important code. Each selection has a particular spot in the array, so it should not be hard to know which one. Instead of enter, use it with the space key first because that has a standard value. Save special keys for a later version.

    Using special keys like arrows and enter are more difficult because of the unbuffered input. The computer does not have a chance to turn enter into '\n' for you. You could make it easy by rolling your own function to do input. First, you need to figure out what the value for the first byte is that indicates a special key. You read that, and test for it. If it is a special key, then you have to grab the distinguishing part with another call, and return the distinguishing byte. No two control characters will be represented by the same sequence, so if you use the distinguishing byte the program should do the right thing. If you aren't detecting a special key, then just return what you read first.

    Code:
    int getkey() {
      int bytes[2];
      
      if ((bytes[0] = getch()) == 0x1a) { /* !! my guess for what the special character is; trust but verify */
        bytes[1] = getch();
        return bytes[1];
      } else {
        return bytes[0];
      }
    }
    Something like that. You'll have to find out what the special character is... maybe, put this aside for now and make another little test program. Try inputting some random stuff and printing out the corresponding numbers to discover it.

    Finally there is something in jim's earlier advice, conio is really old and was probably used when computers were not so widespread. You'd be lucky if all these magic values are the same accross windows versions even. It shouldn't take long for conio.h to show it's age. But in my opinion unbuffered input requires the same skills, no matter the API, so this is good practice.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help on making a menu system for my program
    By Graham93 in forum C Programming
    Replies: 7
    Last Post: 11-01-2012, 10:28 AM
  2. Program Displays menu twice after making a selection
    By jacobj86 in forum C Programming
    Replies: 4
    Last Post: 03-08-2012, 02:03 PM
  3. [C++] Need Help Making Menu Program
    By Bartvo in forum C++ Programming
    Replies: 2
    Last Post: 03-10-2010, 12:14 AM
  4. How to modify a menu into a menu Folder(contains submenus) ??
    By L.O.K. in forum Windows Programming
    Replies: 3
    Last Post: 01-09-2003, 02:26 PM
  5. Making a new window from a menu option
    By LD_Dreamer in forum Windows Programming
    Replies: 2
    Last Post: 12-28-2002, 09:08 PM