我们常用的逻辑运算主要有三种:与(&&)、或(||)、非(!)。还有一些组合的逻辑运算:异或、同或、与非、或非。

在计算机中常用的就只有与(&&)、或(||)、非(!)、异或(^),当然还有一些位运算中的逻辑运算符,这里不多涉及。

对于以上提及的逻辑运算符,只有一元逻辑运算符(即只有一个操作数) ,其余逻辑运算符都是二元逻辑运算符(即需要两个操作数)。

注意:逻辑运算的结果为布尔类型,只有如下两种:

  • 0:表示假(false)
  • 1:表示真(true),在运算中只要是非0都表示真

运算符简介

首先单独介绍一下上面提及到的逻辑运算符。

1. 与(&&)逻辑

运算逻辑:有零为零,全一为一

解释:与运算符是二元逻辑运算符,需要两个操作数。当两个操作数中有一个是假的时候,与逻辑运算结果为假;当两个操作数都是真时,运算结果为真。

操作数1

操作数2

运算结果

1

1

1

1

0

0

0

1

0

0

0

0

2. 或(||)逻辑

运算逻辑:有一为一,全零为零

解释:或运算符也是二元逻辑运算符,也需要两个操作数。当两个操作数中有一个是真的时候,或逻辑运算结果为真;当两个操作数都是假时,运算结果为假。

操作数1

操作数2

运算结果

1

1

1

1

0

1

0

1

1

0

0

0

3. 非(!)逻辑

运算逻辑:遇假为真,遇真为假

解释:非运算符属于一元逻辑运算符,只需要一个操作数。当操作数为真的时候,逻辑运算结果为假;当操作数为假的时候,逻辑运算结果为真。

操作数

运算结果

1

0

0

1

4. 异或(^)逻辑

运算逻辑:相同为假,相异为真

解释:异或运算符属于二元逻辑运算符,需要两个操作数。当两个操作数相同(布尔值相同)的时候,运算结果为假;当两个操作数不同(布尔值不同)的时候,运算结果为真。

操作数1

操作数2

结果值

1

1

0

1

0

1

0

1

1

0

0

0

上面的内容属于复习,本文的重点来了。

运算符运行过程

最近在写代码的时候,用到与(&&)运算符和或(||)运算符,遇到一些问题(也是一些简单的问题):与(&&)运算符和或(||)运算符的运算过程。

问题

if语句中的判断条件出错

stack<char> st;
    for (int i = 0; i < s.size(); i++)
    {
        if (st.top() != s[i] || st.empty())
        {
            st.push(s[i]);
        }
        else
        {
            st.pop();
        }
    }

描述

该if语句要实现的是当栈为空的时候或者当栈顶元素与当前字符元素不等时,进行入栈操作,否则运行出栈操作。但是当栈为空的时候,在if语句判断的时候就会报错,而不会进入if语句进行入栈操作。

原因

或逻辑运算规则是:有一为一,全零为零。在或逻辑运算过程中会先检查第一个元素的布尔值,如上代码,第一个布尔值是栈顶元素与当前字符是否匹配,但是当栈为空的时候,获取栈顶元素的top()函数就会运行失败,从而导致整个或逻辑运行出错。

解决方案

交换或逻辑的两个操作数的顺序,如下:

stack<char> st;
    for (int i = 0; i < s.size(); i++)
    {
        if (st.empty() || st.top() != s[i])
        {
            st.push(s[i]);
        }
        else
        {
            st.pop();
        }
    }

此时或逻辑的运算过程如下:当栈为空的时候,或运算符首先获取第一个操作数的布尔值,第一个操作数是判断栈是否为空,此时第一个操作数的布尔值为真,再回想一下或运算符的运算逻辑:有一为一,全零为零,此时第一个操作数为真,那么无论第二个操作数是真是假,整个或运算符的运算结果都是真,此时就不会去获取第二个操作数的布尔值,从而避开对空栈获取栈顶元素的错误操作。

与(&&)逻辑也有相同的操作:

与逻辑的运算逻辑是:有零为零,全一为一

当获取到第一个操作数为假的时候,无论第二个操作数是真是假,都不会影响与运算符的运算结果,所以就不会获取第二个操作数的布尔值,如果第二个操作数是表达式的话,就不会运行该表达式。