我正在尝试从主菜单创建子菜单,但我正在努力弄清楚如何正确执行此操作

问题描述 投票:0回答:1

我正在创建一个程序,它有一个主菜单,当您选择一个选项(比如1)时,将带您进入一个子菜单,该子菜单允许您选择另一个选项(比如1)。

我无法弄清楚如何连接以进入子菜单。

 int main()
 {
  
 sqlite3 *db;
 int rc;
 
 rc = sqlite3_open_v2("test.db", &db, SQLITE_OPEN_READWRITE, NULL);
 if (rc != SQLITE_OK)
     {
 cout << "Error opening database: " << sqlite3_errmsg(db) <<  endl;
 sqlite3_close(db);
 return 0;
     }
 else
     {
 cout << "Database opened successfully." <<  endl;
     }
 
 
 cout << "Welcome to Database" <<  endl;
 
 
 int choice = mainMenu();
 
 while (true)
         {
 switch (choice){
 
   
 case 1:
 addMenu();
 break;
 case 2:
 updateMenu();
 break;
 case 3:
 deleteCustomer(db);
 break;
 case -1:
 return 0;
 default:
 cout << "That is not a valid choice." <<  endl;
 cout << "\n\n";
 choice = mainMenu();
             }
         }
 sqlite3_close(db);//closes the database
 return 0;
 }
 
 void printMainMenu()
 {
 cout << "Please choose an option (enter -1 to quit):  " << endl;
 cout << "1. Add" << endl;
 cout << "2. Update" << endl;
 cout << "3. Delete" << endl;
 cout << "4. Make a transaction" << endl;
 cout << "Enter choice: ";
 }
 int mainMenu()
 {
 int choice = 0;
 
 printMainMenu();
 cin >> choice;
 while ((!cin || choice < 1 || choice > 4) && choice != -1)
     {
 if (!cin)
         {
 resetStream();
         }
 cout << "That is not a valid choice." << endl
 endl;
 printMainMenu();
 cin >> choice;
     }
 return choice;
 }
 
 void addMenu()
 {
 cout << "Please choose an option (enter -1 to quit):  " << endl;
 cout << "1. Add customer" << endl;
 cout << "2. Add product" << endl;
 cout << "Enter choice: ";
 
 }
c++ function sqlite menu submenu
1个回答
0
投票

您走在正确的道路上。每个菜单运行一个循环,每个菜单项对应一个执行其操作的函数。有时这意味着调用一个“子菜单”函数;其他时候,这意味着调用一个功能不止于此的函数。

如果您从一个很难的函数开始,它会为您提供一种可靠的方法来从

std::cin
获取整数输入,这会很有帮助。下面的函数
get_int
就是这样一种动物。它允许您指定有效值的范围,然后循环直到用户进行有效输入。当输入有效数字时,它返回
true
;当用户取消时,它返回
false
(这并不总是一个选项)。用户输入的数字作为参考参数返回
n

// tbx.console.get_int.h
#ifndef TBX_CONSOLE_GET_INT_H
#define TBX_CONSOLE_GET_INT_H
#include <limits>
#include <string>
namespace tbx::console
{
    bool get_int(
        int& n,
        int const min = std::numeric_limits<int>::min(),
        int const max = std::numeric_limits<int>::max(),
        std::string const& prompt = "Choice? ",
        bool const cancel_allowed = false);
}
#endif
// end file: tbx.console.get_int.h

其他参数可让您指定有效的

min
max
值,以及应使用的提示。当您传入
true
作为
cancel_allowed
的值时,用户可以在空行上按 Enter 键取消输入操作。

正如您在上面所看到的,除了参数

n
之外,所有这些参数都有默认值,因此通常情况下您可以省略其中一两个。以下程序中的菜单系统省略了
prompt
cancel_allowed
标志。默认值非常适合我们的菜单。

我有一个更强大的模板化版本

get_int
,称为
get_number
,它可以与任何 C++ 算术类型一起使用,但在这个答案中使用它太长了。

有了

get_int
可用,显示菜单并输入用户的选择就很简单:

        std::cout << menu;
        int choice;
        tbx::console::get_int(choice, 0, 2);

此示例来自“添加菜单”。变量

choice
保证获得 0 到 2 之间的值。选择 0 退出。其他选择是添加客户和添加产品。

这是

get_int
的代码。

// tbx.console.get_int.cpp
#include <iostream>
#include <sstream>
#include <string>
namespace tbx::console
{
    bool get_int(
        int& n,
        int const min,
        int const max,
        std::string const& prompt,
        bool const cancel_allowed)
    {
        std::string s;
        for (;;)
        {
            if (prompt.empty())
                std::cout << "Enter an integer (press Enter to cancel): ";
            else
                std::cout << prompt;
            if (!cancel_allowed)
            {
                // This will help prevent errors when the user 
                // mixes `std::cin >> value;` with functions like 
                // this one, which use `std::getline`.
                if (!(std::cin >> std::ws))
                {
                    std::cout << "\nERROR: `std::cin >> std::ws` failed unexpectedly.\n\n";
                    return false;
                }
            }
            if (!std::getline(std::cin, s))
            {
                std::cout << "\nERROR: `std::getline` failed unexpectedly.\n\n";
                return false;
            }
            if (s.empty() && cancel_allowed)
            {
                std::cout << "Canceled...\n\n";
                return false;
            }
            std::stringstream sst(s);
            sst >> n;
            if (!sst.eof())
                sst >> std::ws;
            bool parses{ sst.eof() && !sst.fail() };
            bool is_in_range{ parses && min <= n && n <= max };
            if (!parses)
            {
                std::cout << "Invalid entry. Please reenter.\n\n";
            }
            else if (!is_in_range)
            {
                std::cout << n << " is out of range. Please reenter.\n"
                    << "Entries must be between " << min << " and " << max << ".\n\n";
            }
            else
            {
                return true;
            }
        }
    }
}
// end file: tbx.console.get_int.cpp

菜单使用 switch 语句来处理用户的选择。以下是添加菜单的完整功能:

bool add_menu()
{
    std::string menu
    {
        "Add Menu"
        "\n0. Quit"
        "\n1. Add customer"
        "\n2. Add product"
        "\n\n"
    };
    enum : int { Quit, Add_Customer, Add_Product };
    bool done{ false };
    do
    {
        std::cout << menu;
        int choice;
        tbx::console::get_int(choice, 0, 2);
        std::cout << "\n\n";
        switch (choice)
        {
        case Quit:
            done = true;
            break;
        case Add_Customer:
            done = add_customer();
            break;
        case Add_Product:
            done = add_product();
            break;
        default:
            std::cout << "Internal Error: choice is "
                << choice << "\n\n";
            break;
        }
    } while (!done);

    // Return false if you want to redisplay the parent menu.
    // Return true if you want to automatically quit the parent menu.
    // Returning true allows you to skip a menu, and jump to the 
    // menu two levels above this one.
    return false;
}

唯一棘手的部分是返回值。一个函数的返回值成为调用者中的

done
标志。当您返回
true
时,会在调用者中设置
done
标志。

在完整的程序中,有一些功能“正在建设中”,但其中四个菜单已经完成:1.主菜单,2.添加菜单,3.更新菜单和删除菜单。您应该能够运行这个程序来尝试它们。

// main.cpp
#include <iostream>
#include "tbx.console.get_int.h"

bool add_customer()
{
    std::cout << "Add Customer\n\n";
    std::cout << "Under construction - Press Enter to continue...";
    std::string press_enter;
    std::getline(std::cin, press_enter);
    std::cout << "\n\n";

    // Return false if you want to redisplay the parent menu.
    // Return true if you want to automatically quit the parent menu.
    // Returning true allows you to skip a menu, and jump to the 
    // menu two levels above this one.
    return false;
}

bool update_customer()
{
    std::cout << "Update Customer\n\n";
    std::cout << "Under construction - Press Enter to continue...";
    std::string press_enter;
    std::getline(std::cin, press_enter);
    std::cout << "\n\n";

    // Return false if you want to redisplay the parent menu.
    // Return true if you want to automatically quit the parent menu.
    // Returning true allows you to skip a menu, and jump to the 
    // menu two levels above this one.
    return false;
}

bool delete_customer()
{
    std::cout << "Delete Customer\n\n";
    std::cout << "Under construction - Press Enter to continue...";
    std::string press_enter;
    std::getline(std::cin, press_enter);
    std::cout << "\n\n";

    // Return false if you want to redisplay the parent menu.
    // Return true if you want to automatically quit the parent menu.
    // Returning true allows you to skip a menu, and jump to the 
    // menu two levels above this one.
    return false;
}

bool add_product()
{
    std::cout << "Add Product\n\n";
    std::cout << "Under construction - Press Enter to continue...";
    std::string press_enter;
    std::getline(std::cin, press_enter);
    std::cout << "\n\n";

    // Return false if you want to redisplay the parent menu.
    // Return true if you want to automatically quit the parent menu.
    // Returning true allows you to skip a menu, and jump to the 
    // menu two levels above this one.
    return false;
}

bool update_product()
{
    std::cout << "Update Product\n\n";
    std::cout << "Under construction - Press Enter to continue...";
    std::string press_enter;
    std::getline(std::cin, press_enter);
    std::cout << "\n\n";

    // Return false if you want to redisplay the parent menu.
    // Return true if you want to automatically quit the parent menu.
    // Returning true allows you to skip a menu, and jump to the 
    // menu two levels above this one.
    return false;
}

bool delete_product()
{
    std::cout << "Delete Product\n\n";
    std::cout << "Under construction - Press Enter to continue...";
    std::string press_enter;
    std::getline(std::cin, press_enter);
    std::cout << "\n\n";

    // Return false if you want to redisplay the parent menu.
    // Return true if you want to automatically quit the parent menu.
    // Returning true allows you to skip a menu, and jump to the 
    // menu two levels above this one.
    return false;
}

bool add_menu()
{
    std::string menu
    {
        "Add Menu"
        "\n0. Quit"
        "\n1. Add customer"
        "\n2. Add product"
        "\n\n"
    };
    enum : int { Quit, Add_Customer, Add_Product };
    bool done{ false };
    do
    {
        std::cout << menu;
        int choice;
        tbx::console::get_int(choice, 0, 2);
        std::cout << "\n\n";
        switch (choice)
        {
        case Quit:
            done = true;
            break;
        case Add_Customer:
            done = add_customer();
            break;
        case Add_Product:
            done = add_product();
            break;
        default:
            std::cout << "Internal Error: choice is "
                << choice << "\n\n";
            break;
        }
    } while (!done);

    // Return false if you want to redisplay the parent menu.
    // Return true if you want to automatically quit the parent menu.
    // Returning true allows you to skip a menu, and jump to the 
    // menu two levels above this one.
    return false;
}
bool update_menu()
{
    std::string menu
    {
        "Update Menu"
        "\n0. Quit"
        "\n1. Update customer"
        "\n2. Update product"
        "\n\n"
    };
    enum : int { Quit, Update_Customer, Update_Product };
    bool done{ false };
    do
    {
        std::cout << menu;
        int choice;
        tbx::console::get_int(choice, 0, 2);
        std::cout << "\n\n";
        switch (choice)
        {
        case Quit:
            done = true;
            break;
        case Update_Customer:
            done = update_customer();
            break;
        case Update_Product:
            done = update_product();
            break;
        default:
            std::cout << "Internal Error: choice is "
                << choice << "\n\n";
            break;
        }
    } while (!done);

    // Return false if you want to redisplay the parent menu.
    // Return true if you want to automatically quit the parent menu.
    // Returning true allows you to skip a menu, and jump to the 
    // menu two levels above this one.
    return false;
}
bool delete_menu()
{
    std::string menu
    {
        "Delete Menu"
        "\n0. Quit"
        "\n1. Delete customer"
        "\n2. Delete product"
        "\n\n"
    };
    enum : int { Quit, Delete_Customer, Delete_Product };
    bool done{ false };
    do
    {
        std::cout << menu;
        int choice;
        tbx::console::get_int(choice, 0, 2);
        std::cout << "\n\n";
        switch (choice)
        {
        case Quit:
            done = true;
            break;
        case Delete_Customer:
            done = delete_customer();
            break;
        case Delete_Product:
            done = delete_product();
            break;
        default:
            std::cout << "Internal Error: choice is "
                << choice << "\n\n";
            break;
        }
    } while (!done);

    // Return false if you want to redisplay the parent menu.
    // Return true if you want to automatically quit the parent menu.
    // Returning true allows you to skip a menu, and jump to the 
    // menu two levels above this one.
    return false;
}
bool transaction_menu()
{
    std::cout << "Make a Transaction\n\n";
    std::cout << "Under construction - Press Enter to continue...";
    std::string press_enter;
    std::getline(std::cin, press_enter);
    std::cout << "\n\n";

    // Return false if you want to redisplay the parent menu.
    // Return true if you want to automatically quit the parent menu.
    // Returning true allows you to skip a menu, and jump to the 
    // menu two levels above this one.
    return false;
}
bool main_menu()
{
    std::string menu
    {
        "Main Menu"
        "\n0. Quit"
        "\n1. Add"
        "\n2. Update"
        "\n3. Delete"
        "\n4. Make a transaction"
        "\n\n"
    };
    enum : int { Quit, Add, Update, Delete, Transaction };
    bool done{ false };
    do
    {
        std::cout << menu;
        int choice;
        tbx::console::get_int(choice, 0, 4);
        std::cout << "\n\n";
        switch (choice)
        {
        case Quit:
            done = true;
            break;
        case Add:
            done = add_menu();
            break;
        case Update:
            done = update_menu();
            break;
        case Delete:
            done = delete_menu();
            break;
        case Transaction:
            done = transaction_menu();
            break;
        default:
            std::cout << "Internal Error: choice is "
                << choice << "\n\n";
            break;
        }
    } while (!done);

    // Return false if you want to redisplay the parent menu.
    // Return true if you want to automatically quit the parent menu.
    // Returning true allows you to skip a menu, and jump to the 
    // menu two levels above this one.
    return false;
}
int main()
{
    main_menu();
    return 0;
}
// end file: main.cpp
© www.soinside.com 2019 - 2024. All rights reserved.