有没有一种方法可以缩短这种情况?

时间:2019-07-23 05:43:09

标签: c++ if-statement while-loop simplify

while (temp->left->oper == '+' || 
       temp->left->oper == '-' || 
       temp->left->oper == '*' || 
       temp->left->oper == '/' || 
       temp->right->oper == '+' || 
       temp->right->oper == '-' || 
       temp->right->oper == '*' || 
       temp->right->oper == '/') {
    // do something
}

为清楚起见:temp是指向此结构的指针:

struct node
{
    int num;
    char oper;
    node* left;
    node* right;
};

11 个答案:

答案 0 :(得分:20)

创建一个子函数,

bool is_arithmetic_char(char)
{
// Your implementation or one proposed in another answers.
}

然后:

while (is_arithmetic_char(temp->left->oper)
    || is_arithmetic_char(temp->right->oper))
{
    // do something
}

答案 1 :(得分:7)

当然,您可以使用一串有效的运算符进行搜索。

Migrate()

如果您担心性能,那么可以进行表查找:

#include <cstring>

// : :

const char* ops = "+-*/";
while(strchr(ops, temp->left->oper) || strchr(ops, temp->right->oper))
{
     // do something
}

答案 2 :(得分:7)

C风格:

int cont = 1;
while(cont)
    switch(temp->left->oper) {
    case '+':
    case '-':
    ...
    case '/':
        // Do something
        break;
    default:
        cont = 0;
    }

如果要声明变量,可能需要用大括号括住// Do something

答案 3 :(得分:6)

是的。您可以将字符存储到std::array甚至是简单数组中,然后将标准算法std::any_of应用于其中以检查条件。

const std::array<char, 4> options{ '+', '-', '*', '/' };
if (std::any_of(options.cbegin(), options.cend(),
    [=](char opt) {return temp->left->oper == opt || temp->right->oper == opt; }))
{
    // do something
}

答案 4 :(得分:2)

将运算符放入unordered_set将非常有效率,并将为运算符提供O(1)访问权限。

unordered_set<char> u_set;                                                                                                                                                   
u_set.insert('+');                                                                                                                                                           
u_set.insert('*');                                                                                                                                                           
u_set.insert('/');                                                                                                                                                           
u_set.insert('-');                                                                                                                                                           


if((u_set.find(temp->left->oper) != u_set.end()) || (u_set.find(temp->right->oper) != u_set.end())) {     
                 //do something                                                                                                                
}

答案 5 :(得分:1)

您可以构造一个包含选项的字符串并搜索字符:

#include <string>

// ...

for (auto ops = "+-*/"s; ops.find(temp-> left->oper) != std::string::npos ||
                         ops.find(temp->right->oper) != std::string::npos;)
    /* ... */;

"+-*/"s是C ++ 14的功能。在C ++ 14之前使用std::string ops = "+-*/";

答案 6 :(得分:1)

Lambda和std::string_view

string_view提供了std::string的许多功能,并且可以对文字进行运算,并且它不拥有string

对于高度本地化的代码,请使用Lambda而不是函数,该代码对于文件的其余部分不使用。此外,当lambda可以捕获变量时,无需传递变量。无需指定将要创建的功能,也可以获得inline的好处。

制作char const

auto is_arithm = [](const char c) {
  return std::string_view("+-/*").find_first_of(c) != std::string::npos;
};

while (is_arithm(temp->left->oper) || is_arithm(temp->right->oper)) {
}

您可以将const char c更改为const node *t,以访问其在lambda中的oper成员。但这不是一个好主意,因为left的{​​{1}} / right的成员可以修改。

temp

答案 7 :(得分:0)

正则表达式可以解救!

#include <regex>

while (
    std::regex_match(temp->left->oper, std::regex("[\+\-\*/]")) ||
    std::regex_match(temp->right->oper, std::regex("[\+\-\*/]"))
) { 
// do something
}

说明:正则表达式括号[]表示正则表达式“字符类”。这意味着“匹配括号内列出的任何字符”。例如,g[eiou]t将匹配“ get”,“ git”,“ got”和“ gut”,但不匹配“ gat”。需要反斜杠,因为加号(+)减号(-)和星号(*)在字符类中具有含义。

免责声明:我没有时间运行这段代码;您可能需要对其进行调整,但是您明白了。您可能需要将operchar声明为std::string

参考资料
1. http://www.cplusplus.com/reference/regex/regex_match/
2. https://www.rexegg.com/regex-quickstart.html
3. https://www.amazon.com/Mastering-Regular-Expressions-Jeffrey-Friedl/dp/0596528124/ref=sr_1_1?keywords=regex&qid=1563904113&s=gateway&sr=8-1

答案 8 :(得分:0)

交易空间与时间的关系,您可以构建两个分别由temp->left->opertemp->left->oper索引的“布尔”数组。 满足条件时,相应的数组包含 true ,否则为 false 。 所以:

while (array1[temp->left->oper] || array1[temp->right->oper]) {
// do something
}

由于左侧和右侧的集合似乎相同,因此一个数组实际上可以。

初始化如下:

static char array1[256]; // initialized to "all false"

...

array1['+'] = array1['-'] = array1['*'] = array1['/'] = '\001';

array2类似。 由于跳转对现代流水线CPU不利,因此您甚至可以使用更大的表,如下所示:

while (array1[temp->left->oper << 8 | temp->right->oper]) {
    // do something
}

但是初始化更加棘手:

static char array1[256 * 256]; // initialized to "all false"

...

void init(char c) {
    for (unsigned char i = 0; i <= 255; ++i) {
        array1[(c << 8) | i] = array1[(i << 8) | c] = '\001';
    }
}

init('+');
init('-');
init('*');
init('/');

答案 9 :(得分:0)

编程是寻找冗余并消除冗余的过程。

struct node {
    int num;
    char oper;
    node* left;
    node* right;
};

while (temp->left->oper == '+' || 
       temp->left->oper == '-' || 
       temp->left->oper == '*' || 
       temp->left->oper == '/' || 
       temp->right->oper == '+' || 
       temp->right->oper == '-' || 
       temp->right->oper == '*' || 
       temp->right->oper == '/') {
    // do something
}

这里的“重复单元”是什么?好吧,我看到了两个实例

   (something)->oper == '+' || 
   (something)->oper == '-' || 
   (something)->oper == '*' || 
   (something)->oper == '/'

因此,让我们将重复的部分分解为一个函数,这样我们只需要编写一次即可。

struct node {
    int num;
    char oper;
    node* left;
    node* right;

    bool oper_is_arithmetic() const {
        return this->oper == '+' || 
               this->oper == '-' || 
               this->oper == '*' || 
               this->oper == '/';
    }
};

while (temp->left->oper_is_arithmetic() ||
       temp->right->oper_is_arithmetic()) {
    // do something
}

Ta-da!缩短!
(原始代码:17行,其中8个是循环条件。修改后的代码:18行,其中2个是循环条件。)

答案 10 :(得分:-1)

“ +”“-”“ *”和“ /”是ASCII十进制值42、43、45和47 因此

#define IS_OPER(x) (x > 41 && x < 48 && x != 44 && x != 46)

while(IS_OPER(temp->left->oper || IS_OPER(temp->right->oper){ /* do something */ }