紧凑的多条件if语句

Compact multi-conditional if statement

本文关键字:if 语句 条件      更新时间:2023-10-16
我有一个最简单的问题。我正在练习if语句,想知道我是否可以在不同的条件下打印出不同的信息,但我想保持简单。如果第一个条件为真,则将打印cout的第一行;如果第二个条件为真,则输出cout的第二行;等等......代码;
int x; cin >> x;
int y; cin >> y;
if(x<y||x>y||x==y)
{
    cout << x << " is smaller than " << y << endl;
    cout << x << " is bigger than " << y << endl;
    cout << x << " is equal to " << y << endl;
}

显然在cout s之间缺少了某种|| s。是否有可能保持代码的紧凑性并使其正常运行?

要完成您的要求,您的代码应该是:

int x; cin >> x;
int y; cin >> y;
if(x<y)
{
    cout << x << " is smaller than " << y << endl;
}
else if (x>y)
{
    cout << x << " is bigger than " << y << endl;
}
else
{
    cout << x << " is equal to " << y << endl;
}

换句话说,您的三个条件必须位于if-else if-else控制结构的不同部分。这样,其中一个将根据您的输入执行,并打印出相应的消息。

你说的简单是什么意思?如果紧凑,那么这是正确的(但不是最可读的)。

x==y?cout<<"x=y":(x<y?cout<<"x<y":cout<<"x>y");

。或者让==作为保存字符

的默认大小写
x>y?cout<<"x>y":(x<y?cout<<"x<y":cout<<"x=y");

用数学方法来思考这些情况是有帮助的。如果有三种可能的情况(<,>和=),那么您需要测试两次。在下面的代码中,执行两个测试以确定关系是小于还是大于;如果是,则发出正确的输出。假设以上两种情况都不成立,那么唯一的另一种可能性是相等的。这是由else处理的。链接如果……其他的如果……Else语句加在一起就是通解。switch关键字用于更有限的方法。

#include <iostream>
using namespace std;
int main() {
    int x;
    cout << "Enter x: ";
    cin >> x;
    cout << "Enter y: ";
    int y; cin >> y;
    if (x < y)
        cout << x << " is smaller than " << y << endl;
    else if (x > y)
        cout << x << " is bigger than " << y << endl;
    else
        cout << x << " is equal to " << y << endl;
}

你可以这样写:

int x; cin >> x;
int y; cin >> y;
if(x<y) {
    cout << x << " is smaller than " << y << endl;
} else if (x>y) {
    cout << x << " is bigger than " << y << endl;
} else if (x==y)  {
    cout << x << " is equal to " << y << endl;
}

或者如果你想冒险,就:

 } else {
    cout << x << " is equal to " << y << endl;
 }

使用神奇的三元运算符:

#include <iostream>
int main()
{
    int x, y;
    std::cin >> x >> y;
    (x == y) ? (std::cout << x << " is equal to " << y << std::endl) : 
    ((x <  y) ? (std::cout << x << " is smaller than " << y << std::endl) :
    (std::cout << x << " is bigger than " << y << std::endl));
    return 0;
}

如果你想要完全过度,你可以稍微滥用模板系统。

auto if_ = make_if(
    std::greater<>{}, [](auto x, auto y){ cout << x << " is greater than " << y << endl; },
    std::less<>{}, [](auto x, auto y){ cout << x << " is smaller than " << y << endl; },
    std::equal_to<>{}, [](auto x, auto y){ cout << x << " is equal to " << y << endl; }
);
if_(0,0);
if_(0,1);
if_(1,0);

将产生

0 is equal to 0
0 is smaller than 1
1 is greater than 0

现场演示

下面是它的完整实现:

template<typename Pred, typename Result, typename... Others>
struct If;
namespace detail
{
template<typename... Ts>
struct IfSelector
{
    using type = If<Ts...>;
};
template<>
struct IfSelector<>
{
    struct EmptyIf
    {
        template<typename... Ts>
        void operator()(Ts&&...){}
    };
    using type = EmptyIf;
};
template<typename... Ts>
using ParentIf = typename IfSelector<Ts...>::type;
}
template<typename Pred, typename Result>
struct IfEntry
{
    Pred pred;
    Result result;
};
template<typename Pred, typename Result, typename... Others>
struct If : detail::ParentIf<Others...>
{
    using pred = Pred;
    using result = Result;
    using parent = detail::ParentIf<Others...>;
    template<typename P, typename R, typename... Os>
    If(P&& p, R&& r, Os&&... os):
        parent{std::forward<Os>(os)...},
        entry{std::forward<P>(p), std::forward<R>(r)}
    {}
    template<typename... Ts>
    void operator()(Ts&&... ts) {
        if(entry.pred(ts...)) {
            entry.result(std::forward<Ts>(ts)...);
        } else {
            this->parent::operator()(std::forward<Ts>(ts)...);
        }
    }
    IfEntry<Pred, Result> entry;
};

template<typename... Ts>
auto make_if(Ts&&... ts){
    return If<Ts...>(std::forward<Ts>(ts)...);
}

基本上,您将谓词结果对的列表传递给模板,并以相反的顺序检查它们。如果谓词的结果为true,则执行配对操作。

如果你真的想让它简短,并且不太关心可读性,可以从标签数组开始:

static char const *names[] = {" is smaller than ", " is equal to ", " is bigger than "};

然后使用难看的布尔逻辑来索引

std::cout << x << names[1 + (y<x)-(x<y)] << y << 'n';

要弄清楚这个逻辑,请记住a<b产生false(将转换为0)或true(将转换为1)。

:

  • if x < y => y<x = 0, x<y = 1, 0-1 = -1
  • if y == x => y<x = 0, x<y = 0, 0-0 = 0
  • if y < x => y<x = 1, x<y = 0, 1-0 = 1

然后加1得到-1…1等于0…2,并使用它来索引数组。

严肃地说:如果你要做这样的事情,至少把比较放在cmp(x,y)或其他顺序中:

int cmp(int x, int y) { return y<x - x<y; }

然后在其他代码中使用:

std::cout << names[1+cmp(x, y)] << 'n';

这并没有消除不可读的代码位,但至少它将其限制在一个小地方(并且当您厌倦了它的过度可爱时,您可以用更正常的逻辑替换它,而不必编辑其余的代码)。

对于它的价值(不是很多),这个cmp函数被定义为产生与qsortbsearch期望的相同类型的结果。