gpt4 book ai didi

c++ - 使用字符串作为条件时减少 else if 语句的方法

转载 作者:行者123 更新时间:2023-12-02 17:58:37 24 4
gpt4 key购买 nike

我正在制作一个类似终端的程序(用于计算货币),并使用自定义命令作为输入,但我遇到了问题。每次实现新命令时,我都必须添加新的 else if 语句。这不是问题,但对于类似终端的程序来说可能有很多命令。

这是我的代码:

#include <iostream>
#include <string>
#include <Windows.h>
#include <math.h>

float user_balance = 0.0f;
float eur_in_czk = 24.0f; //ammount of czk in single euro
std::string currency = "czk";
bool czk_to_eur_enabled = true;
bool eur_to_czk_enabled = false;

//------------------START method definition---------------------------------------------------------
void czk_to_eur()
{
if (czk_to_eur_enabled) //to prevent using twice in a row
{
user_balance /= eur_in_czk;
user_balance = floorf(user_balance * 100) / 100; //limit to two decimal numbers
currency = "eur";
czk_to_eur_enabled = false;
eur_to_czk_enabled = true;
}
else
{
std::cout << "Your savings are already converted to " << currency << "!" << std::endl;
}
}

void eur_to_czk()
{
if (eur_to_czk_enabled) //to prevent using twice in a row
{
user_balance *= eur_in_czk;
user_balance = floorf(user_balance * 100) / 100; //limit to two decimal numbers
currency = "czk";
eur_to_czk_enabled = false;
czk_to_eur_enabled = true;
}
else
{
std::cout << "Your savings are already converted to " << currency << "!" << std::endl;
}
}

void set_balance(float new_balance)
{
user_balance = new_balance;
}

void add_balance(float new_balance)
{
user_balance += new_balance;
}
//------------------END method definition-----------------------------------------------------------


int main()
{
bool main_loop = true; //main loop enabler
float input_money;
std::string user_command = "";

std::cout << "This is currency converter v1.0 (czk to eur and back)\n\n\n" << std::endl;

while (main_loop) //main loop for currency converter
{
std::cout << "Input: ";
std::cin >> user_command;
std::cout << std::endl;

if ((user_command == "setbal") || (user_command == "SETBAL"))
{
std::cout << "Your balance is " << user_balance << " " << currency << ".\n";
std::cout << "Please enter desired value (" << currency << "): ";
std::cin >> input_money;
set_balance(input_money);
std::cout << "\n" << std::endl;
}
else if ((user_command == "addbal") || (user_command == "ADDBAL"))
{
std::cout << "Your balance is " << user_balance << " " << currency << ".\n";
std::cout << "Please enter desired value (" << currency << "): ";
std::cin >> input_money;
add_balance(input_money);
std::cout << "\n" << std::endl;
}
else if ((user_command == "balance") || (user_command == "BALANCE"))
{
std::cout << "Your balance is " << user_balance << " " << currency << "." << std::endl;
}
else if ((user_command == "curstat") || (user_command == "CURSTAT"))
{
std::cout << "Currency status is " << eur_in_czk << " czk in 1 eur." << std::endl;
}
else if ((user_command == "toeur") || (user_command == "TOEUR"))
{
czk_to_eur();
}
else if ((user_command == "toczk") || (user_command == "TOCZK"))
{
eur_to_czk();
}
else if ((user_command == "cheuv") || (user_command == "CHEUV"))
{
std::cout << "Change eur value (" << eur_in_czk << "): ";
std::cin >> eur_in_czk;
std::cout << std::endl;
}
else if ((user_command == "help") || (user_command == "HELP"))
{
std::cout << "SETBAL Sets balance.\n"
<< "ADDBAL Adds balance.\n"
<< "BALANCE Shows current balance.\n"
<< "CURSTAT Shows currency status.\n"
<< "TOEUR Converts czk to eur.\n"
<< "TOCZK Converts eur to czk.\n"
<< "CHEUV Changes eur currency value.\n"
<< "CLS Cleans terminal history.\n"
<< "EXIT Exits program.\n" << std::endl;
}
else if ((user_command == "cls") || (user_command == "CLS"))
{
system("CLS"); //funtion from Windows.h library
}
else if ((user_command == "exit") || (user_command == "EXIT"))
{
main_loop = false;
}
else
{
std::cout << "'" << user_command << "'"
<< "is not recognized as an internal or external command!\n";
std::cout << "Type 'HELP' to see available commands.\n" << std::endl;
}
}

return 0;
}

while循环中代码的底部部分就是问题所在。

一切正常,但我想知道是否还有其他方法。据我所知,switch 不支持字符串值作为条件/依赖项。 (而且我目前没有使用任何自定义类和/或自定义头文件,因为这只是实验。)

还有其他办法吗?

最佳答案

通常,我建议使用 std::map ,其中字符串作为键,函数作为值,以便您可以在映射中搜索命令,然后调用与其关联的函数。然而,由于评论中已经提到了这一点,我想我会变得很奇特并提供一个你可能不应该使用的完全古怪的解决方案

这个奇怪的解决方案允许您在 switch/case 语句中使用字符串文字。这是可以通过利用现代 C++ 的一个称为“用户定义文字”的功能来实现的,该功能允许您通过定义用户定义后缀来生成用户定义类型的对象与将 U 附加到整数文字以指定无符号值的方式相同。

我们要做的第一件事是定义一个用户定义的文字,它生成一个在编译时计算的哈希值。由于这会从字符串生成哈希值,因此可能会遇到冲突,但这取决于所使用的哈希算法的质量。对于我们的示例,我们将使用一些简单的东西。下面的代码片段定义了一个带有后缀 _C 的字符串文字,用于生成我们的哈希值。

constexpr uint32_t djb2Hash(const char* str, int index = 0)
{
return !str[index]
? 0x1505
: (djb2Hash(str, index + 1) * 0x21) ^ str[index];
}

// Create a literal type for short-hand case strings
constexpr uint32_t operator"" _C(const char str[], size_t /*size*/)
{
return djb2Hash(str);
}

现在,每当编译器看到 "Hello World"_C 格式的字符串文字时,它都会生成一个哈希值并使用它来代替字符串。

现在我们会将其应用到您现有的代码中。首先,我们将采用用户命令的代码与 cin 分开,并将给定的命令全部小写。

std::string get_command()
{
std::cout << "Input: ";

std::string user_command;
std::cin >> user_command;
std::cout << std::endl;

std::transform(
user_command.begin(),
user_command.end(),
user_command.begin(),
[](char ch) { return static_cast<char>(std::tolower(ch)); });

return user_command;
}

现在,我们可以从用户那里获取一个全小写的命令,我们需要处理该命令,因此我们将采用您原始的一组 if/else 语句并转将它们改为简单的 switch/case 语句。现在,由于我们实际上无法在 switch/case 语句中使用字符串文字,因此我们必须稍微修改一下并生成 users 命令的哈希值switch 部分代码。我们还将获取您的所有命令并向其添加 _C 后缀,以便编译器自动为我们生成哈希值。

int main()
{
bool main_loop = true; //main loop enabler

std::cout << "This is currency converter v1.0 (czk to eur and back)\n\n\n" << std::endl;

while (main_loop) //main loop for currency converter
{
const auto user_command(get_command());
switch(djb2Hash(user_command.c_str()))
{
case "setbal"_C:
std::cout << "Set balance command\n";
break;

case "addbal"_C:
std::cout << "Add balance command\n";
break;

case "balance"_C:
std::cout << "Get balance command\n";
break;

case "curstat"_C:
std::cout << "Get current status command\n";
break;

case "help"_C:
std::cout << "Get help command\n";
break;

case "exit"_C:
main_loop = false;
break;

default:
std::cout
<< "'" << user_command << "'"
<< "is not recognized as an internal or external command!\n"
<< "Type 'HELP' to see available commands.\n" << std::endl;
}
}
}

这就是你想要的。一个完全奇怪的解决方案!现在请记住,我们并没有真正在 switch/case 语句中使用字符串,我们只是隐藏了生成随后使用的哈希值的大部分细节.

关于c++ - 使用字符串作为条件时减少 else if 语句的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74999955/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com