首页 > 解决方案 > 返回主菜单保持循环菜单

问题描述

当程序第一次启动时,我可以成功地从主菜单中选择任何选项。但是,当我从任何子菜单中选择返回主菜单选项时,它会返回主菜单,但无论我之后再次按下哪个选项,它都会继续循环该菜单。只允许我选择返回主菜单选项。如何将选择重置为不会继续循环的位置?我已经尽可能地缩短了代码,以便它仍然可以编译但也可以显示错误。先感谢您。

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

int main()
{
    //declare all working variables: mOption, FManOption, COption...etc...
    int MOption = 0;
    int FManOption = 0;
    int FOption = 0;
    int COption = 0;
    int userChoice = 0;

    //declarations for all arrays of struct
    //declare a pointer to an array of struct using malloc() for fisherman, fish, catch

    //process:
    printf("Please select 1 to start the program or 0 to quit: ");
    scanf("%d", &userChoice);
    while(userChoice != 1 && userChoice != 0)
    {
        printf("Invalid selection! Please type a 1 or a 0: ");
        scanf("%d", &userChoice);
    }//end (userChoice != 1 && userChoice != 0)
    if(userChoice != 1)
        printf("Thank you for wasting my time! Have a great day!");
    else
    {

      MOption = mainMenu();


        switch(MOption)
        {
            case 1: FManOption = FishermanMenu();
                    while(FManOption != 3)
                    {
                        switch(FManOption)
                        {
                            case 1: getFisherman();//get a fisherman
                                    //count fisherman
                                    break;
                            case 2: //prompt for a ssn, validate, search
                                    //if found display everything about this fisherman
                                    break;
                            case 3: FManOption = mainMenu();

                                    //reset FManOption
                                    break;
                            default: printf("\nInvalid selection! Please select from one of the menu options\n");
                        }//end switch(FManOption)
                    }//end while(FManOption != 3)
                    break;
        }
    }
}

int mainMenu()
{
    int Option;

    printf("\n-------Welcome to the Fishing Tournament Main Menu!-------\n");
    printf("1 - Fisherman menu\n");
    printf("2 - Fish menu\n");
    printf("3 - Tournament(Catch) menu\n");
    printf("4 - Close Tournament (determine winner)\n");
    printf("5 - Quit Program\n\n");
    printf("Please select a menu option: ");
    scanf("%d", &Option);
    if(Option > 5 || Option < 1)
        do /* check scanf() return value for input errors */
        {
            printf("\nInvalid selection! Please select from one of the menu options\n");
            printf("1 - Fisherman menu\n");
            printf("2 - Fish menu\n");
            printf("3 - Tournament(Catch) menu\n");
            printf("4 - Close Tournament (determine winner)\n");
            printf("5 - Quit Program\n\n");
            printf("Please select a menu option: ");
            scanf("%d", &Option);
        }
        while(Option > 5 || Option < 1);

    return Option; /* finally return the final correct option */
}//end main menu

int FishermanMenu()
{
    int ManOption;
    printf("\n-------Fisherman Menu-------\n");
    printf("1 - Register fisherman\n");
    printf("2 - Search fisherman\n");
    printf("3 - Go back to main menu\n");
    printf("Please select a menu option: ");
    scanf("%d", &ManOption);
    if(ManOption > 5 || ManOption < 1)
        do /* check scanf() return value for input errors */
        {
            printf("\nInvalid selection! Please select from one of the menu options\n");/* handle input error */
            printf("1 - Register fisherman\n");
            printf("2 - Search fisherman\n");
            printf("3 - Go back to main menu\n");
            printf("Please select a menu option: ");
            scanf("%d", &ManOption);
        }
        while(ManOption > 5 || ManOption < 1);
    return ManOption; /* finally return the final correct option */
}//end Fisherman Menu

标签: cfunctionmenuswitch-statementsubmenu

解决方案


这依赖于一种称为隐式函数声明的特性;这被认为是有害的,已在 中删除C99。可以将菜单重新排列在顶部,或者在调用函数之前对其进行原型设计,

int mainMenu(void);
int FishermanMenu(void);

并将隐式int参数更改为返回的局部变量,

int mainMenu(void) {
    int MOption;
...
}
int FishermanMenu(void) {
    int FManOption;
...
}

编辑

与其弄清楚那些只会让调试变得更糟的开关,不如让我建议改变应用程序结构。这段代码可以是一个没有太多变化的状态机,只需从函数返回下一个状态。

enum states {
    START, MAIN, FISHPERSON, REGISTER, SEARCH, FISH, CATCH, CLOSE, END
};

enum states StartMenu(void);
enum states MainMenu(void);
enum states FishermanMenu(void);
/* ... */

typedef enum states (*state_function)(void);
static const state_function states[] = { StartMenu, MainMenu,
    FishermanMenu, /*...*/0, 0, 0, 0, 0, /* END is actually 0 == NULL */0 };

int main(void)
{
    enum states state = START;
    while(states[state]) state = states[state]();
    return 0;
}

然后从菜单返回状态,

enum states StartMenu(void) {
    int userChoice = 0;
    //process:
    printf("Please select 1 to start the program or 0 to quit: ");
    scanf("%d", &userChoice);
    while(userChoice != 1 && userChoice != 0)
    {
        printf("Invalid selection! Please type a 1 or a 0: ");
        scanf("%d", &userChoice);
    }//end (userChoice != 1 && userChoice != 0)
    if(userChoice != 1) {
        printf("Thank you for wasting my time! Have a great day!");
        return END;
    } else {
        return MAIN;
    }
}

为了减少重复,而不是while() {}考虑do {} while()在前面显示信息的菜单上。


推荐阅读