C++:单向跳转到函数.任何替代方案

C++ : One way jump to functions... any alternative?

本文关键字:函数 任何替 方案 C++      更新时间:2023-10-16

我是一名学生,正在学习 c++。去年我为我的 skul 做了一个简单的项目,现在我意识到为了使其用户友好,我从一个函数到另一个函数进行了多次调用,而不考虑堆栈和它会导致的内存泄漏。基本上,它是一个学生数据库管理系统,我已经制作了一个对应于一个屏幕的功能,即一个用于菜单的功能,一个用于添加数据,修改数据等的功能。代码很大,所以我粘贴了一小部分.只需观察我如何首先从menu((调用add1((,然后再次从add1((调用menu((...

 `//***************************STUDENT DATABASE***********************************
void add1(){
     system("CLS");
     char ch;
     int i=no; 
     do{   
     i++;  
     cout<<"nName : ";
     cin.ignore ( std::numeric_limits<std::streamsize>::max(), 'n' );
     getline (cin,s[i].name);      
     cout<<"nClass : ";
     cin>>s[i].cl;
     cout<<"nRollno : ";
     cin>>s[i].rollno;
     cout<<"nMarks in";
     s[i].m.avg=0;
     for(int j=0;j<maxsb;j++)
     {
                            cout<<"n"<<subject[j]<<": ";
                            cin>>s[i].m.s[j];
                            s[i].m.avg+=(s[i].m.s[j]/maxsb);
                            }
     no=i;
     cout<<"nPress 'n' for next and 'b' to exit : "; 
     cin>>ch;
     cout<<"n***********************************************************************";
     }while(ch=='n'); 
     menu(); //calling menu() again from this function...
}
                             //*************        
void menu(){
     system("CLS");
     int n,flag=0;
     do
     {
     cout<<"1.ADD DATAn2.VIEW REPORTn3.MODIFY DATAn4.DELETE DATAn5.SORT DATAn6.GO BACK TO PREVIOUS MENUn";
     cout<<"PLEASE ENTER YOUR CHOICE(enter corresponding integer): "; 
     cin>>n;
     switch(n)
     { case 2: report();break;
       case 1: add1();break;
       case 3: modify();break;
       case 4: del();break;
       case 5: sort();break;
       case 6: first(); 
       default:cout<<"PLEASE ENTER A VALID CHOICE";system("CLS");flag=1;
       }
       }
       while(flag==1);                              
     }
                              //**************
void first()
{
     system("CLS");
     int n,flag=0;
     cout<<"tttSoftware for Teachers";
     cout<<"nn1.Student Databasenn2.Play Gamenn3.Calculator";
     cout<<"nnEnter your choice: ";
     do{
     flag=0;
     cin>>n;
     switch(n)
     {
              case 1:{  if(flag2==0) 
                        {           setting();
                                    flag2=1;
                                    }
                        menu(); }
                   break;
              case 2: game();
                   break;
            //  case 3: calculator();
               //    break;
              default: cout<<"nPlz enter a valid choice nn Enter your choice again:  ";flag=1;
              }
     }
     while(flag);
}
//******************************************************************************
int main()
{
    int temp;
    first();
    cin>>temp;
}
`

这种从一个函数跳到另一个函数然后再也不返回在我的代码中已经做过几次了,我现在意识到,杀死了堆栈。我已经用谷歌搜索了很多,我知道首先不可能单向从一个函数随机跳到另一个函数,并且将所有内容组合在一个函数中并使用 goto 从一个块跳到另一个块不是一个好主意(它实际上更糟!!所以,我的问题是,有没有更好的方法可以完成这项任务?(这里的意思是我在上面的代码中试图做的事情,即该程序的用户友好性(

谢谢

不要

调用 menu()first() 返回上一个菜单,而是使用 return 。例如,在menu()函数中:

   case 6: return; 

这意味着控件将在函数调用后立即返回到调用函数。例如,当您从add1返回到menu时,执行将继续在请求选择的循环中。

只需将 menu(((在函数内部或外部(括在一个循环中,然后从 add1 函数正常返回。

void add1(){
    …..
    }while(ch=='n'); 
    return; <--------------
}
void menu(){
    while(true) <------------------
    {
    system("CLS");
    int n,flag=0;
    do
    {
    cout<<"1.ADD DATAn2.VIEW REPORTn3.MODIFY DATAn4.DELETE DATAn5.SORT DATAn6.GO BACK TO PREVIOUS MENUn";
    cout<<"PLEASE ENTER YOUR CHOICE(enter corresponding     integer): "; 
     cin>>n;
    switch(n)
   { case 2: report();break;
     case 1: add1();break;
     case 3: modify();break;
     case 4: del();break;
     case 5: sort();break;
     case 6: return; <-------------------
     default:cout<<"PLEASE ENTER A VALID CHOICE";system("CLS");flag=1;
      }
     }
     while(flag==1);                              
   }
}

你应该让处理程序函数(即add1()(返回到主函数,这将在循环中再次调用menu(),直到你要求退出。

您是否曾经在马里奥等游戏机上玩过街机游戏?在这样的游戏中,我们有多级菜单(带有子菜单的菜单;每个屏幕一个菜单(。希望,这是你想要实现的。

在电脑游戏中,通常,我们使用堆栈数据结构(LIFO(实现这样的菜单(状态(。

  • 将菜单屏幕(状态(包装到对象中。所有资源都在构造函数中初始化,所有清理都在析构函数中进行,因此没有泄漏。

    class IState
    {
    public:
        virtual ~IState() {}
        virtual void Apply() = 0;
    };
    class MainMenuState : public IState
    {
    public:
        MainMenuState() { /*Here goes resources allocation*/ }
        virtual ~MainMenuState() {  /*Here goes resources freeing*/ }
        virtual void Apply() override { /*Here goes menu rendering*/ }
    };
    class SettingsMenuState : public IState
    {
    public:
        SettingsMenuState() { /*Here goes resources allocation*/ }
        virtual ~SettingsMenuState() {  /*Here goes resources freeing*/ }
        virtual void Apply() override { /*Here goes menu rendering*/ }
    };
    
  • 将状态存储在堆栈中

    std::stack<IState> states;
    
  • 当用户必须看到新菜单时,您推送状态:

        states.push(MainMenuState()); // initial menu
        if (userWantsToSettings)
        {
            states.push(SettingsMenuState()); // second level
        }
    
  • 当用户想要返回时,您弹出状态

        if (userWantsGoBack)
        {
            states.pop();
        }
    
  • 有时(对于游戏,每帧一次,对于控制台应用程序,它可以是用户按下按钮一次(您调用Update() 来呈现最顶层的菜单:

        void Update()
        {
            states.top().Apply();
        }
    

裁判:

制作主菜单系统的最佳方法是什么?

我应该如何构建我的菜单/游戏循环?

希望对您有所帮助。祝您编码愉快!=)

相关文章: