【问题标题】:Adding boolean expressions switch statements in C++?在 C++ 中添加布尔表达式 switch 语句?
【发布时间】:2014-11-06 23:12:33
【问题描述】:

我正在用 C++ 练习 switch 语句,我想知道是否可以添加一个布尔表达式以及如何添加,就像它是一个 if/else 对应物。可以合并吗?

这是我的骨架代码:

#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
#include <Windows.h>
#include <stdlib.h>
#include <time.h>
#include <random>

using namespace std;


int main()
{
    int HouseValue;
    cout << "Enter your total house value estimate:";
    cin >> HouseValue;

    switch (HouseValue)
    {
        case 1:
            (HouseValue < 100000 && HouseValue > 50000);
            cout << "";
            break;
        case 2:
            (HouseValue < 250000 && HouseValue > 100000);
            cout << "";
            break;
        case 3:
            (HouseValue < 500000 && HouseValue > 250000);
            cout << "";
            break;
        case 4:
            (HouseValue < 1000000 && HouseValue > 500000);
            cout << "";
            break;
        case 5:
            (HouseValue < 3000000 && HouseValue > 1000000);
            cout << "";
            break;
    }
    return 0;
}

【问题讨论】:

  • case 表达式必须在编译时知道。
  • 我添加了 if's before 但我姐姐说这不可能,所以我删除了它们,它们的行为有问题。
  • @Chantola 即使他们在那里,他们在这段代码中也没用。例如,case 1: 的开关已经确定HouseValue 是......好吧..1。测试它是否在 50000 和 100000 之间有点毫无意义,因为它显然不是(它的 1)。
  • 好的,我只是想知道这样的事情是否可以在 switch 语句中,答案是否定的。谢谢你们的超快速回复
  • 我看不出switch 中的条件如何比if() 构造更有效,而if() 构造更具表现力。所以我看不到任何好处。 switch 的真正强大之处在于编译器可以利用分支的静态特性(例如构建跳转表)。

标签: c++ boolean case break boolean-expression


【解决方案1】:

您不能直接在 switch 中使用条件,因为它们需要编译时常量表达式。在任何情况下,您的方法都缺少精确值的任何分支(例如HouseValue == 100000),而且它是多余的。

最简单的解决方案是使用if/else 链:

if (HouseValue < 50000)
  ...
else if (HouseValue < 100000)
  ...
else if (HouseValue < 250000)
  ...
else if (HouseValue < 500000)
  ...

【讨论】:

    【解决方案2】:

    没有。 C++ 没有这种开关结构:switch 仅用于常量。

    该控制结构的 C++ 实现是

    if (HouseValue >= 50000 && HouseValue < 100000) {
       ...
    } else if (HouseValue >= 100000 && HouseValue < 150000) {
       ...
    } else if (HouseValue >= 150000 && HouseValue < 200000) {
       ...
    } else {
       ...
    }
    

    或者,稍微简化一下

    if (HouseValue >= 50000 && HouseValue < 100000) {
       ...
    } else if (HouseValue < 150000) {
       ...
    } else if (HouseValue < 200000) {
       ...
    } else {
       ...
    }
    

    【讨论】:

      【解决方案3】:

      可以在推断您的案例值时利用switch() eval 的值获得创意。例如:

      switch((HouseValue + 50000)/50000)
      

      由于integer division,将导致下表的潜在结果:

      HouseValue (N)           (HouseValue + 50000)/50000
      ===================================================
      0      <= N < 50000                  1
      50000  <= N < 100000                 2
      100000 <= N < 150000                 3
      etc...
      

      我不会破坏计算公式中使用哪些值来获得您正在寻找的特定范围的乐趣(或者如果它甚至可能的话)。我会告诉你这个。如果您不提供 break ,还记得提到的关于“通过”特定案例标签到下一个的事情吗?是的,这可能会派上用场。

      总之,没有人说你必须在输入值上直接switch。您始终可以使用基于输入值的表达式,只要 case 标签是常量,您就有很大的回旋余地。

      祝你好运。

      【讨论】:

        【解决方案4】:

        不,不能那样做。

        switch 语句并未作为链式if 的“语法糖”引入语言。专门引入了switch 语句,以便为“参数化 goto”功能提供结构更好的替代,即具有运行时跳转目标的goto,可以立即从参数值派生。 switch 必须始终立即知道要跳到哪里。这就是switch 声明背后的全部想法。你的条件不符合这个想法。 (再想一想,他们有点像,但按照原来的switch 标准,他们仍然“太复杂了”。)

        您正在尝试做的是通过链式if 实现的。如果你不喜欢它,你可以发明其他东西,比如某种范围集合,它可以从给定的HouseValue 有效地生成整数范围索引(1、2、3 等)。您将能够在该索引上执行switch。 (见@WhozCraig 的回答。)

        当然,由于您的HouseValue 是一个整数,您可以使用覆盖所有可能的HouseValue 值的大小写标签来创建switch,但这除了纯粹的幽默之外几乎没有任何价值。

        还应注意,某些编译器(例如 GCC)支持 swicth 语句中的“范围”大小写标签,例如

        switch (HouseValue)
        {
            case 50000 ... 100000:
                ...
                break;
            case 100000 ... 250000:
                ...
                break;
            ...
        }
        

        但这是一个非标准的语言扩展。

        【讨论】:

          【解决方案5】:

          另一种解决方案:使用函数指针查找表。

          typedef void (*Ptr_Processing_Function)(void);
          
          void Process_Range_1(void);
          void Process_Range_2(void);
          void Process_Range_3(void)
          
          struct Range_Entry
          {
            unsigned int lower_price;
            unsigned int high_price;
            Ptr_Processing_function process_function;
          };
          
          const Range_Entry table[] =
          {
            {50000, 10000, Process_Range_1},
            {10000, 15000, Process_Range_2},
            //...
          };
          const unsigned int entries_in_table =
              sizeof(table) / sizeof(table[0]);
          
          //...
          cin >> price;
          for (unsigned int i = 0; i < entries_in_table; ++i)
          {
            if ((price >= table[i].lower_price) && (price < table[i].high_price))
            {
              table[i].processing_function();
              break;
            }
          }
          

          【讨论】:

            【解决方案6】:

            这是另一种解决方案,只需将ValueBracket(HouseValue) 插入开关即可

            static const std::array<int, 6> Values = { 50000, 100000, 250000, 500000, 1000000, 3000001 };
            size_t ValueBracket(int value) {
                return std::lower_bound(Values.begin(), Values.end(), value) - Values.begin();
            }
            

            并添加以下2个案例

            case 0:
                cout << "you live in a shed peasant, go away";
                break;
            default:
                cout << "sorry my Lord, we can't sell your castle here";
                break;
            

            一个精神病案例

            constexpr int Return1() {
                return 1;
            }
            
            
            switch(index) {
            case Return1():
                    break;
            }
            

            这可能只是快乐的 GCC ...

            但是 case 只能是编译时常量,比如 constexpr ...

            【讨论】:

              【解决方案7】:

              我知道我来晚了,但你可以把它变成这样的开关:

              int mycase = HouseValue / 50000;
              
              switch (mycase) {
                case 0: /* HouseValue < 50000) */
                  ...
                case 1: /* HouseValue >= 50000 && HouseValue < 100000 */
                  ...
                case 2: /* HouseValue >= 100000 && HouseValue < 250000 */
                case 3:
                case 4:
                case 5:
                  ...
                /* etc */
              }
              

              通过这种方式,您可以将 5 个 if 语句的(可能)评估与单个 int 除法和跳转进行交换。衡量哪种方式更适合您的用例。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2020-05-10
                • 2015-09-21
                • 2011-03-28
                • 1970-01-01
                相关资源
                最近更新 更多