首页 > 其他分享 >C语言-“关系”,“条件”,“逻辑”操作符详解

C语言-“关系”,“条件”,“逻辑”操作符详解

时间:2024-07-20 17:57:31浏览次数:19  
标签:操作数 ++ C语言 运算符 详解 操作符 && 表达式

目录

关系操作符

 “==”与“=”的区别 

多个关系运算符不宜连用

多个关系运算符判断值是否在中间的写法

条件操作符

逻辑操作符

逻辑取反操作符:!

逻辑与运算符:&&

 

逻辑或运算符:||

练习:闰年的判断

短路

 


关系操作符

c语言用于比较的表达式,称为“关系表达式”(relational expression),里面使用的运算符就称为“关系运算符”(relational operator),主要有下面6个。

  • > 大于运算符
  • < 小于运算符
  • >= 大于等于运算符
  • <= 小于等于运算符
  • == 相等运算符
  • != 不相等运算符

关系表达式的一些例子:

  1. a == b;
  2. a != b;
  3. a < b;
  4. a > b;
  5. a <= b;
  6. a >= b;

关系表达式通常返回 0 或 1,表示真假。

eg:例一中a等于b的话,表达式会返回1,为真。若 a 不等于 b 的话,表达式会返回0,为假。

用代码来验证,2不等于3,为假,程序返回(打印)的是0

当将表达式换成2等于2时,为真,程序返回(打印)的是1

也比如:20>12返回1;12>20返回0。


 “==”与“=”的区别 

注意:相等运算符 “==” 与赋值运算符 “=” 是两个不一样的运算符,不要混淆。

当我们键盘输入3时,if 表达式中 a(3)判断等于3,if 表达式为真,打印了“hehe”

当我们键盘输入5时,if 表达式中a(5)判断不等于3,if 表达式为假,打印else中的“haha”

所以,两个等于号“==”是判断相等。

有时候,可能会不小心误写出下面的代码,它可以运行,但很容易出现意料之外的结果。

if (a=3)...

上面示例中,原意是a==3,但是不小心写成a=3a=3这个式子表示对变量a赋值3,所以不论a之前为几,就算是键盘输入的数是5放在了a中,到 if 表达式那里会将3赋值给a,所以if表达式的结果(返回值)为3,if表达式判断为真,打印“hehe”。

此时无论键盘输入a为几,到if那里会将3赋值给a,所以这个 if 表达式就恒为真了,就永远打印 if 中的语句,else则永远不打印。

为了防止出现这种错误,写判断相等的表达式时,将常量写在左边,将变量写在等号右边。

if (3==a)...

这样的话,如果把 “==” 误写成 =,编译器就会报错。

因为不可能把a这个变量赋值给3这个常量,所以编译器会报错。


多个关系运算符不宜连用

 另一个需要避免的错误是: 多个关系运算符不宜连用。

i < j < k 

上面示例中,连续使用两个小于运算符。这是合法表达式,不会报错,但是通常达不到想要的结果。

即:不保证变量j在i和k之间。

其实实际执行的是下面的表达式:

( i < j )< k 

因为关系运算符是从左到右计算,所以上面式子中,(i<j)先计算返回 0 或 1,最终0或1与右边<k进行比较 

例子:

if表达式中明明规定18<=age<=40才是青年,但是age为10也打印出了青年,为什么10也能打印“青年”呢? 

因为因为这段代码是错的,在语法上是对的,但在逻辑上是错的。if表达式中先算的是:18<=age,而18不可能小于等于10,所以18<=10为假,为假就是0。紧接着0<=40为真,就打印了“青年”。并不是拿age与18和40一起比的。


多个关系运算符判断值是否在中间的写法

上面式子中,i<j返回0或1,所以最终是0或1与变量k进行比较。如果想要判断变量j的值是否在i和k之间,应该使用下面的写法:

i < j && j <k

比如: 我们输入一个年龄,如果年龄在18岁~36岁之间,我们输出青年。

此时代码正确,青年就不打印了


条件操作符

条件操作符也叫三目操作符(c语言中唯一的一个三目操作符),需要接受三个操作数,形式如下:

exp1 ? exp2 : exp3

注:exp1(表达式1) ?(操作符)exp2(表达式2):(操作符)exp3(表达式3) 

条件操作符的计算逻辑是:如果exp1为真,exp2计算,计算的结果是整个表达式的结果;如果exp1为假,exp3计算,计算的结果是整个表达式的结果。 

练习1: 使用条件操作符改造下面代码的逻辑。

#include <stdio.h>

int main()

{

     int a =0;

     int b =0;

     scanf("%d",&a);

     if(a>5)

        b=3;

     else

        b=-3

     printf("%d\n",b);

     return 0;

 需要用条件操作符改造的就是选中的if...else...语句:

改造后:

int main()

{

    int a =0;

    int b =0;

    scanf("%d",%a);

    b=(a>5 ? 3 : -3);

    printf("%d\n",b);

    return 0;

}

练习2: 使用条件表达式实现找两个数中较大值。


逻辑操作符

逻辑运算符提供逻辑判断功能,用于构建更复杂的表达式,主要有下面三个运算符。

  • !:逻辑取反运算符(改变单个表达式的真假)。
  • &&:与运算符,就是并且的意思(两侧的表达式都为真,则为真,否则为假)。
  • ||:或运算符,就是或者的意思(两侧至少有一个表达式为真,则为真,否则为假)。

注:C语言中,非0表示真,0表示假。 


逻辑取反操作符:!

!:只有一个操作数,所以是单目操作符。

a!a
非0(真)0(假)
0(假)1(真)

注:!不能放在操作数的后面,只能放在操作数的前面。


逻辑与运算符:&&

aba&&b
非0(真)非0(真)1(真)
非0(真)0(假)0(假)
0(假)非0(真)0(假)
0(假)0(假)0(假)

注:全真则真,一假全假。

 

&& 就是与运算符,也是并且的意思,&&是一个双目操作符,使用的方式是a&&b,&&两边的表达式都是真时,整个表达式才为真,只要有一个是假,则整个表达式为假。

例如:如果我们说月份是3月到5月是春天,那使用代码怎么体现呢?


逻辑或运算符:||

aba||b
非0(真)非0(真)1(真)
非0(真)0(假)1(真)
0(假)非0(真)1(真)
0(假)0(假)0(假)

注:一真则真

||就是或运算符,也就是或者的意思,||也是一个双目操作符,使用的方式是:a||b,||两边的表达式只要有一个是真,整个表达式就是真,两边的表达式都为假的时候,才为假

例如:我们说一年中月份是12月或者1月或者2月是冬天,那么我们怎么使用代码体现呢?


练习:闰年的判断

输入一个月份year,判断year是否是闰年

闰年的判断规则:

  1. 能被4整除并且不能被100整除的是闰年
  2. 能被400整除的是闰年

可以发现:

规则1有“并且”两字,所以规则一是并且的关系:()&&();规则1与规则2都能判断是不是闰年,它们是或者的关系。:(这其中包含规则1的并且关系:()&&())||()

合并起来则为:(()&&())||()

第一种写法:

第二种写法:

int main()
{
    int year = 0;
    scanf("%d",&year);
    if ((year % 4 == 0) && (year % 100 != 0))
    {
        printf("是闰年");
    }
    else
    {
        if (year % 400 == 0)
        {
            printf("是闰年");
        }
        else
        {
            printf("不是闰年");
        }
    }
    return 0;
}


短路

C语言逻辑运算符还有一个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是保证的。如果左边的表达式满足逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为“短路”。

如前面的代码:

If(month >= 3 && month <= 5)

表达式中&&的左操作数是month>=3,右操作数是month<=5,当左操作数month>=3的结果是0的时候,即使不判断month<=5,整个表达式的结果也是0(不是春季)。因为逻辑与一假全假,从左边表达式就知道结果,不再对后面表达式进行计算了。

所以,对于&&操作符来说,左边操作数的结果是0的时候,右边操作数就不再执行。

对于||操作符是怎么样呢?我们结合前面的代码:

if(month == 12 || month==1 || month==2)

 如果month==12,则不用再判断month是否等于1或者2,整个表达式的结果也是1(是冬季)。

所以,||操作符的左操作数的结果不为0时,就无需执行右操作数。

像这样仅仅根据左操作数的结果就能知道整个表达式的结果,不再对右操作数进行计算的运算称为短路求值。

练习阅读代码,计算代码输出的结果。

因为:

a++是后置++:先用后加。在i=a++ && ++b && d++中,a为0,后面又是&&(逻辑与),所以 a++ (0)&& ++b为0(假),紧接着后面又是&&(逻辑与),即a++ && ++b (0)&&d++,为0。

所以b,c,d不做变化,只有a在使用过后自加了1,即a=1;b=2;c=3;d=4。

将a改为2后的值呢?

因为:

a++是后置++:先用后加。在i=a++ && ++b && d++中,a++整个表达式为2,是真,所以得算后面的++b。同时用完后a自加了1==3。

++b是前置++:先加后用。所以++b这个表达式在i=a++ && ++b && d++中为3,是真,接着算d++。

d++是后置++:先用后加。在i=a++ && ++b && d++中,d++整个表达式为4,同时用完后自加了1==5。

所以最后的值:a=3,b=3,c=3,d=5.

注:i的值为1。因为i=a++ && ++b && d++都为真,为真就返回了1

将&&改为||,读下面代码:

a++在i = a++ || ++b || d++中为2,是真,所以后面短路求值,都不用算了,即b,d的值都不变。只有a在用后自加了1为3

同样的,将a变为0,代码的结果分别为:

 

 

 

标签:操作数,++,C语言,运算符,详解,操作符,&&,表达式
From: https://blog.csdn.net/2302_80244431/article/details/140569410

相关文章

  • Java中的枚举详解
    文章目录概述使用枚举枚举的实现枚举的性能枚举与常量枚举集合类枚举与泛型枚举与反射概述枚举在Java中是一种特殊的类,用来定义一组固定的常量。它在Java5中引入,提供了一种类型安全的方式来定义和使用常量集合。尽管enum看起来像是新的数据类型,但它实际上是一个受限......
  • 【Python】使用库 -- 详解
    库就是别人已经写好了的代码,可以让我们直接拿来用。一个编程语言能不能流行起来,一方面取决于语法是否简单方便容易学习,一方面取决于生态是否完备。所谓的“生态” 指的就是语言是否有足够丰富的库,来应对各种各样的场景。在实际开发中,也并非所有的代码都自己手写,而是要充分利......
  • 【数据结构初阶】顺序表三道经典算法题(详解+图例)
    Hello!很高兴又见到你了~~~看看今天要学点什么来充实大脑吧——目录1、移除元素【思路+图解】 【总结】2、删除有序数组中的重复项【思路+图解】【总结】3、合并两个有序数组【思路+图解】【总结】 至此结束,ShowTime!1、移除元素【思路+图解】 ......
  • 【数据结构】详解堆
    一、堆的概念堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。堆是非线性数据结构,相当于一维数组,有两个直接后继。如果有一个关键码的集合K={k₀,k₁,k₂,k₃,…,kₙ₋₁ },把它的所有元素按完全二叉树的顺序存储方......
  • 【数据结构】超详解二叉树
    1、树的概念及结构堆与树的结构类似堆的概念及代码实现-CSDN博客树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。有一个特殊的结点,称为根结点,根结点没有前驱结点除......
  • C语言数组笔记
    该笔记整理自阮一峰老师的《C语言教程》和部分网上资料声明和初始化数组//声明一个数组并初始化intnums[]={1,2,3,4,5};//完整写法:intnums[5]={1,2,3,4,5};//数组长度可以省略,因为长度系统可以判断出来//声明一个长度为5的数组intnums[5];//相当......
  • C语言指针详解(进阶)
    二、指针的进阶    本章重点:            1.字符指针        2.数组指针        3.指针数组        4.数组传参和指针传参        5.函数指针        6.函数指针数组    ......
  • C语言之typedef,位运算
    typedef用typedef声明新的类型名来代替已有的类型名声明INTEGER为整型TypedefintINTEGER定义整形变量定义结构体定义数组定义字符型声明POINT为指向函数的指针类型,该函数返回整型值typedefint(*POINT)();用typedef可以声明各种类型名,但不能用来定义变量......
  • Linux系统安装的详细步骤详解
    在VM虚拟机上安装Linux系统全过程,闭眼跟着走就行!!!1、准备好VMwareWorestation虚拟机软件和Linux系统的映像文件2、点击创建新的虚拟机3、在新建虚拟机向导中,选择典型安装模式。典型安装模式可以通过几个简单的步骤快速安装虚拟机,更方便操作。点击下一步。4、在安装来源......
  • Java NIO 快速入门:Java 非阻塞 IO 编程详解
    一、NIO简介1.概述介绍:JavaNIO(NewInput/Output)是从Java1.4开始引入的一组新的IO库,旨在替代传统的阻塞式IO。NIO提供了更高效的IO操作,支持非阻塞模式和多路复用,适用于高并发场景。概述:NIO中通过Buffer作为缓存区,Channel作为数据通道来传输数据进行数据通讯,通过S......