简体   繁体   English

如何在ANSI / ISO C中编写控制台菜单?

[英]How to write a console menu in ANSI/ISO C?

I'm trying to create a simple program in c, where the user has to choose between several options: 我正在尝试在c中创建一个简单的程序,其中用户必须在几个选项之间进行选择:

char command = '1';
while(command!='0') {
    printf("Menu:\n");
    printf("1. First option\n");
    printf("2. Second option\n");
    printf("0. Exit\n");
    printf("Choose: 0,1,2?: ");
    command = getchar();
    while(getchar()!='\n');     
    switch(command) {
        case '0': break;
        case '1': functionCall1(); break; 
        case '2': functionCall2(); break;
    }
}

The problem with my code is, that every second time I enter 1,2 or 0, nothing happens, only the menu prints itself again. 我的代码的问题是,每第二次我输入1,2或0,就什么也没发生,只有菜单再次打印出来。 With the debugger I can see, that the value of command , after command = getchar() equals '', every second time. 与调试器可以想见,该命令的值,之后命令=的getchar()等于“”,每一秒的时间。 I thought that eating the newline character is enough? 我以为吃换行符就足够了吗?

Try my customized menu, I implemented it to make my life easier when I work with programs which contains multiple choices operations. 尝试我的自定义菜单,当使用包含多种选择操作的程序时,我实现了它来使我的生活更轻松。 Menu is navigable (arrows:up, down, left, right), and for making a selection you only need to press enter key, menu orientation can be set vertically or horizontally, padding can be set to a group of items(childrens), child starting position, and update with delay. 菜单是可导航的(箭头:上,下,左,右),您只需按Enter键即可进行选择,菜单方向可以垂直或水平设置,填充可以设置为一组项目(儿童),子开始位置,并延迟更新。

Menu call example (vertically): 菜单调用示例(垂直):

int response = menu("OPTIONS","[*]","->",
                    1,3,3,0,5,
                    "PROFILES","ACTIVITY","VIDEO","SOUND","GAMEPLAY");

The most important thing is because function implementation takes only 60 lines of code. 最重要的是,因为函数实现只需要60行代码。

Menu implementation: 菜单实现:

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

// LXSoft
// mod: cui/menu_021
// stdarg.h  -> used for variable list of arguments (va_list, va_start ...)
// windows.h -> used for Sleep function, for *nix use unistd.h

typedef unsigned short int usint_t;
// Menu function prototype
int menu(char* name, char* prefix, char* cursor, usint_t orientation,
         usint_t padding, usint_t start_pos, usint_t delay,
         usint_t num_childs, ...);

int main()
{
    int response = menu("OPTIONS","[*]","->",1,3,3,0,5,
                        "PROFILES","ACTIVITY","VIDEO","SOUND","GAMEPLAY");
    switch(response)
    {
        case 1:
            // doSomethingFoo1();
        break;
        case 2:
            //doSomethingFoo2();
        break;
        /*
         * .
         * .
         * .
         * case n:
         * break;
         */
    }
    printf("\nYour choice is: %d", response);
    return 0;
}

// Menu implementation
int menu
(
    char *name,        // Menu name (eg.: OPTIONS)
    char *prefix,      // Menu prefix (eg.: [*])
    char *cursor,      // Menu cursor (eg.: ->)
    usint_t orient,    /*
                        * Menu orientation vertical or horzontal.
                        * 0 or false for horizontal
                        * 1 or true for vertical
                        */
    usint_t padding,   // Menu childrens padding (eg.: 3)
    usint_t start_pos, // Menu set active child (eg.: 1)
    usint_t delay,     // Menu children switch delay
    usint_t childs,    // Number of childrens
    ...                /*
                        * Variable list of arguments char* type.
                        * Name of the childrens.
                        */
)
{
    va_list args;
    int tmp=0,pos;
    char chr;
    usint_t opt=start_pos;
    char* format=malloc
    (
        (
            strlen(name)+strlen(prefix)+strlen(cursor)+
            3+ /* menu suffix (1 byte) and backspace (2 bytes) */
            (2*childs)+ /* newline (2 bytes) times childs */
            (padding*childs)+ /* number of spaces times childs */
            childs*15 /* children name maxlen (15 bytes) times childs*/
        )*sizeof(char)
    );
    do
    {
        if(tmp!=0)chr=getch();
        if(chr==0x48||chr==0x4B)
            (opt>1&&opt!=1)?opt--:(opt=childs);
        else if(chr==0x50||chr==0x4D)
            (opt>=1&&opt!=childs)?opt++:(opt=1);
        else {/* do nothing at this time*/}
        strcpy(format,"");
        strcat(format,prefix);
        strcat(format,name);
        strcat(format,":");
        va_start(args,childs);
        for (tmp=1;tmp<=childs;tmp++)
        {
            (orient)?strcat(format,"\n"):0;
            pos=padding;
            while((pos--)>0) strcat(format," ");
            if(tmp==opt)
            {
                strcat(format,"\b");
                strcat(format,cursor);
            }
            strcat(format,va_arg(args,char*));
        }
        /*if(tmp!=childs)
        {
            fprintf(stderr,"%s: recieved NULL pointer argument,"
                           " child not named", __func__);
            return -1;
        }*/
        Sleep(delay);
        system("cls");
        printf(format);
        va_end(args);
    }while((chr=getch())!=0x0D);
    return opt;
}

May be you should try to use int x as a key to use a desirable command, may be like that: 可能是您应该尝试使用int x作为使用所需命令的键,可能像这样:

 while(x != 0) { scanf("%d", &x); switch (x) { printf("input '2' to...\\n"); printf("input '3' to...\\n"); printf("input '4' to...\\n"); printf("input '5' to...\\n"); printf("input '6' to...\\n"); case 1: head = Enqueue(head); break; case 2: head1 = spisokMagazinovScenoiMensheiZadannoi(head, head1); break; case 3: head1 = udalenieElementa(head1); break; case 4: head1 = addNewMagazin(head1); break; case 5: head1 = addNewMagazin(head1); break; case 6: printToTheFile(head); break; } } 

I used it in my previous homework. 我在以前的作业中使用过它。 Hope it will be usefull for you 希望对您有用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM