【问题标题】:How would I clean up these If Statements?我将如何清理这些 If 语句?
【发布时间】:2020-05-27 03:28:18
【问题描述】:
if (calculation == "help") {
    cout << "add, subtract, multiplication, divide\nsquare root, sin, cos, power\n";
}
else if (calculation == "add") {
    cout << num1 << " + " << num2 << " = " << num1 + num2 << endl;
}
else if (calculation == "subtract") {
    cout << num1 << " - " << num2 << " = " << num1 - num2 << endl;
}
else if (calculation == "multiplication") {
    cout << num1 << " x " << num2 << " = " << num1 * num2 << endl;
}
else if (calculation == "divide") {
    cout << num1 << " / " << num2 << " = " << num1/ num2 << endl;
}
else if (calculation == "square root") {
    cout << "The square root of the first number is " << sqrt(num1) << ". The square root of the second number is " << sqrt(num2) << "." << endl;
}
else if (calculation == "sin") {
    cout << "The sine of the first number is " << sin(num1) << ". The sine of the second number is " << sin(num2) << "." << endl;
}
else if (calculation == "cos") {
    cout << "The cosine of the first number is " << cos(num1) << ". The cosine of the second number is " << cos(num2) << "." << endl;
}
else if (calculation == "power") {
    cout << num1 << " to the power of " << num2 << " = " << pow(num1, num2) << endl;
}

我有一个解决这些 if 语句的想法,例如创建地图或字典。我不相信您也可以在 C++ 中将字符串与 switch 语句一起使用。非常感谢任何帮助!

编辑:我可以使用地图。

map<string, int> Choices = {
        { "help", 0 },
        { "add", 1 },
        { "subtract", 2 },
        { "multiply", 3 },
        { "divide", 4 },
        { "square root", 5 },
        { "sine", 6 },
        { "cosine", 7 },
        { "power", 8 }
        };

    it = Choices.find(choice);
    i = it->second;

如果有更快的方法,请告诉我。感谢大家的回复!

【问题讨论】:

  • 把它们放在 enum 中并有一个 switch 代替。看this回答
  • 让我们假设您(和问题的)原因是您被来自外部来源的字符串(例如消息)所困扰。由于您使用的是 C++,因此您可以使用 std::strings(啊,我看到您说过——是的,这是个好主意)作为键和您选择的类似函数的对象作为值来创建映射。您也可以尽早将它们转换为枚举(也可以使用地图),然后使用开关。
  • 密钥会在其他地方使用吗?在stp::map&lt;std::string, std::function&lt;void(int, int)&gt;&gt; 中移动它只会在地图初始化中移动冗长的东西。不确定您是否真的提高了可读性。
  • 您是否测试过性能并将解决方案与 map 和 if 语句进行比较。我可能是地图解决方案比 ifs 慢。在为性能编码时,您总是需要考虑处理器缓存以及预取器的工作方式。如果列表的类型只存储几个项目,数组通常比地图快。

标签: c++ if-statement


【解决方案1】:

如果您匹配前两个字符并将它们转换为一个数字,则可以创建一个开关。它不会很漂亮,但它会很快

编辑:如果字符串的第一部分是唯一的,我做了一个关于如何使用“字符串”创建开关的示例。如果需要,您可以使用两个以上的字符来执行此操作,如果有重复,您可以在案例部分中使用开关。

只有在性能非常重要的情况下才这样做,它会在速度上碾压其他解决方案

#include <iostream>
#include <string>

int main()
{
    // first some code to show how to calculate constant from string if the first part in string is unique
    unsigned int uNumber = (unsigned int)'A';
    std::cout << uNumber << std::endl;
    uNumber <<= 8;
    std::cout << uNumber << std::endl;
    uNumber += (unsigned int)'A';
    std::cout << uNumber << std::endl;

    unsigned int uNumberAA = (unsigned int)*(uint16_t*)"AA";
    std::cout << uNumberAA << std::endl;
    uNumberAA = (unsigned int)*(uint16_t*)"AAAA";
    std::cout << uNumberAA << std::endl;


    // How to create a switch with strings

    static constexpr unsigned int he_help = ((unsigned int)'h' << 8) + (unsigned int)'e';           // "help"
    static constexpr unsigned int ad_add = ((unsigned int)'a' << 8) + (unsigned int)'d';            // "add"
    static constexpr unsigned int su_subtract = ((unsigned int)'s' << 8) + (unsigned int)'u';       // "subtract"
    static constexpr unsigned int mu_multiplication = ((unsigned int)'m' << 8) + (unsigned int)'u'; // "multiplication"

    std::string calculation = "subtract";

    uNumber = ((unsigned int)calculation[0] << 8) + (unsigned int)calculation[1];
    switch(uNumber)
    {
    case he_help :
        std::cout << "help" << std::endl;
        break;
    case ad_add :
        std::cout << "add" << std::endl;
        break;
    case su_subtract :
        std::cout << "subtract" << std::endl;
        break;
    case mu_multiplication :
        std::cout << "multiplication" << std::endl;
        break;
    }
}

【讨论】:

    【解决方案2】:

    你可以很容易地清理它们。考虑这个例子:

    #include <stdio.h>
    
    int main(void) {
        int a, b, result;
        char calculation;
        .
        .
        switch (calculation) { // must be a character or integral type
            case 'a': result = a + b; break; // add
            case 's': result = a - b; break; // subtract
            .
            .
            default:
                printf("No such operation.\n"); // when invalid operation
                return -1;
        }
        // valid operation? continue...
    
        printf("The result is: %d\n", result);
    
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      阅读更多关于C++ programmingC++ programming languageHow to debug small programs 以及后来的C++11 标准n3337 的信息。考虑使用一些functional programming 风格进行编码。 SICP 这本书很好地介绍了它。

      请记住,C++ 有closures,是用lambda expressions 创建的。它还有几个关联的containers,包括std::mapstd::unordered_map

      一种可能是建立一个闭包的关联映射:

      static std::map<std::string,
                      std::function<int(const std::vector<int>&)>> 
             mapclosures= {
        { "add", [](const std::vector<int>& v) { return v[0]+v[1]; }},
        { "mult", [](const std::vector<int>& v) { return v[0]*v[1]; }},
        //// etc...
      }
      

      以后使用mapclosures[str](v)mapclosures[str](std::vector({3,5}))

      当然,真正的代码会检查v 是否有两个add 的参数,如果没有throw some exception。对于除法,请注意除以零。

      关于性能,它是可以接受的(当然,比普通的switch 慢)。如果性能很重要并且您愿意花费编码时间,请了解有关 parsing 技术的更多信息(例如,使用 Dragon book 或您的 recursive descent parser 构建一些 abstract syntax tree)将字符串 "add" 转换为一些 @ 987654352@ 值。

      阅读有关interpretation 技术的更多信息,并研究以 C++ 编码的现有open source 解释器的源代码(可能是 Linux fish shell,或gitlabgithub 上的其他解释器)。

      【讨论】:

        【解决方案4】:

        在这种情况下使用 switch 可以帮助您将代码修改为更整洁的代码。但是,switch 与条件没有太大区别。只有当你有这么多条件只基于一件可能改变的事情时,它才会看起来更全面。这是一个适合您的开关示例: 想象一下,我输入了一个 1 到 4 范围内的 int,然后想要打印用户给出的数字。以下是在这种情况下使用 switch 的方法:

        int n;
        cin>>n;
        switch(n){
           case 1:{cout<<"one";break;}
           case 2:{cout<<"two";break;}
           case 3:{cout<<"three";break;}
           case 4:{cout<<"four";break;}
        }
        

        【讨论】:

        • 切换速度非常快,编译器擅长优化,C++ 只能在切换语句中使用数字是有原因的。其他可以在 switch 中使用字符串的语言更像是“if”。只是另一种编写方式。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-23
        • 2019-05-10
        • 2017-06-06
        • 1970-01-01
        • 2021-09-19
        相关资源
        最近更新 更多