我正在创建一个程序,它有一个主菜单,当您选择一个选项(比如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: ";
}
您走在正确的道路上。每个菜单运行一个循环,每个菜单项对应一个执行其操作的函数。有时这意味着调用一个“子菜单”函数;其他时候,这意味着调用一个功能不止于此的函数。
如果您从一个很难的函数开始,它会为您提供一种可靠的方法来从
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