3 C 语言运算符深度解析:从基础到实战

目录

1 运算符分类

2 算术运算符与算术表达式

2.1 算术运算符的用法

2.2 左操作数和右操作数

3 关系运算符与关系表达式

3.1 关系运算符的用法

3.2 常量左置防错

3.3 三数相等判断误区

4 逻辑运算符与逻辑表达式

4.1 逻辑运算符的用法

4.2 闰年的判断

4.3 短路运算

5 赋值运算符

5.1 左值与右值

5.2 赋值操作的限制

5.3 复合赋值运算符

5.4 复合赋值运算符的运算规则与示例解析

6 sizeof 运算符

 7 运算符优先级表

8 小节判断题

9 OJ 练习

9.1 课时3作业1

9.2 课时3作业2


1 运算符分类

C 语言提供了 13 种类型的运算符,如下所示:

(1)算术运算符(+ - * / % ) 。
(2)关系运算符(> < == >= <= != ) 。
(3)逻辑运算符(! && || ) 。
(4)位运算符(<< >> ~ | ^ & ) 。
(5)赋值运算符(= 及其扩展赋值运算符) 。
(6)条件运算符(? : ) 。
(7)逗号运算符(, ) 。
(8)指针运算符(* 和 & )——讲指针时讲解
(9)求字节数运算符(sizeof ) 。
(10)强制类型转换运算符((类型)) 。

(11)分量运算符(. -> ) 。——讲结构体时讲解
(12)下标运算符([ ] ) 。——讲数组时讲解
(13)其他(如函数调用运算符()) 。——讲函数时讲解

部分运算符在高级阶段进行讲解。


2 算术运算符与算术表达式

2.1 算术运算符的用法

算术运算符包含 “+”、“-”、“”、“/” 和 “%”,当一个表达式中同时出现这 5 种运算符时,先进行乘(*)、除(/)、取余(%) ,取余也称取模,后进行加(+)、减(-),也就是乘、除、取余运算符的优先级高于加、减运算符。

除 “%” 运算符外,其余几种运算符既适用于浮点型数又适用于整型数。当操作符 “/” 的两个操作数都是整型数时,它执行整除运算,在其他情况下执行浮点型数除法。

“%” 为取模运算符,它接收两个整型操作数,将左操作数除以右操作数,但它的返回值是余数而不是商

由算术运算符组成的式子称为算术表达式,表达式一定有一个值。

#include <stdio.h>

int main() {
    int a = 10, b = 3;
    float c = 5.0, d = 2.0;

    // 单独使用各个算术运算符
    printf("加法: %d + %d = %d\n", a, b, a + b); // 13
    printf("减法: %d - %d = %d\n", a, b, a - b); // 7
    printf("乘法: %d * %d = %d\n", a, b, a * b); // 30
    printf("除法(整型): %d / %d = %d\n", a, b, a / b); // 3
    printf("除法(浮点型): %.2f / %.2f = %.2f\n", c, d, c / d); // 2.50
    printf("取余: %d %% %d = %d\n", a, b, a % b); // 1

    // 综合使用算术运算符
    int result = 4+5*2-6/3+11%4;// 4 + 10 - 2 + 3 = 15
    printf("综合表达式结果: %d\n", result);

    // 注意事项  
    // 1. 整数除法时,结果会向下取整(即舍弃小数部分)。
    // 2. 运算符的优先级:乘、除、取余 > 加、减。可以使用括号改变运算顺序。
    // 3. % 运算符只适用于整型操作数。
    // 4. 浮点数运算可能产生精度问题,注意结果可能不是完全精确。

    return 0;
}

注意事项:

整数除法当使用 / 运算符进行整数除法时,结果会向下取整到最接近的整数,这意味着任何小数部分都会被舍弃。

运算符优先级:算术运算符的优先级是固定的,乘、除、取余的优先级高于加、减。如果需要改变默认的运算顺序,可以使用括号 ()

取模运算符% 取模运算符只能用于整型操作数。如果尝试对浮点数使用 %,编译器会报错。

浮点数精度浮点数运算可能会遇到精度问题,因为计算机中的浮点数表示是基于二进制的,某些十进制小数在二进制中可能无法精确表示。因此,进行浮点数运算时,结果的精度可能不是完全精确的。

类型提升:在表达式中混合使用整型和浮点型时,整型操作数会被提升为浮点型,然后执行浮点型运算。这可能会影响结果的类型和精度。

2.2 左操作数和右操作数

在 C 语言(以及大多数编程语言中),操作数是指参与运算的数据项或表达式的值。当我们在C语言中执行一个算术运算(如加法、减法、乘法、除法和取模)时,我们通常会涉及到至少两个操作数:左操作数和右操作数。

  • 左操作数:在二元运算符(即需要两个操作数的运算符)的左侧的操作数
  • 右操作数:在二元运算符右侧的操作数

假设我们有以下表达式:

int a = 5;  
int b = 3;  
int sum = a + b;

在这个例子中,+ 是一个二元运算符,它有两个操作数:

  • 左操作数是 a(值为 5)。
  • 右操作数是 b(值为 3)。

3 关系运算符与关系表达式

3.1 关系运算符的用法

关系运算符 “>”、“<”、“==”、“>=”、“<=”、“!=” 依次为大于、小于、是否等于、大于等于、小于等于和不等于

由关系运算符组成的表达式称为关系表达式关系表达式的值只有,对应的值为 1 0 。由于 C 语言中没有布尔类型,所以在 C 语言中 0 值代表假,非 0 值即为真。例如,关系表达式 3 > 4 为假,因此整体值为 0 ,而关系表达式 5 > 2 为真,因此整体值为 1 。

【关系运算符的优先级】 低于 【算术运算符】,运算符的优先级的详细情况见本文最后。

#include <stdio.h>

int main() {
    int a = 5, b = 3, c = 2, d;

    // 演示关系运算符
    printf("%d > %d is %d\n", a, b, a > b); // 5 > 3 是真,输出 1
    printf("%d < %d is %d\n", a, b, a < b); // 5 < 3 是假,输出 0
    printf("%d == %d is %d\n", a, a, a == a); // 5 == 5 是真,输出 1
    printf("%d >= %d is %d\n", a, b, a >= b); // 5 >= 3 是真,输出 1
    printf("%d <= %d is %d\n", a, b, a <= b); // 5 <= 3 是假,输出 0
    printf("%d != %d is %d\n", b, c, b != c); // 3 != 2 是真,输出 1

    // 演示关系运算符与算术运算符的优先级
    d = (a + b) > (c * 2); // 先进行算术运算,再进行关系比较
    printf("(%d + %d) > (%d * 2) is %d\n", a, b, c, d); // (5 + 3) > (2 * 2) 是真,输出 1

    // 如果不加括号,算术运算符会先于关系运算符执行
    // 但这里由于表达式的自然结构,加不加括号结果一样
    // 只是为了说明优先级的概念
    d = a + b > c * 2; // 这实际上和上面加了括号的表达式效果一样,因为这里运算符的自然结合顺序也是先进行算术运算
    printf("Without parentheses, (%d + %d) > (%d * 2) is %d\n", a, b, c, d); // 输出也是 1

    return 0;
}

3.2 常量左置防错

在工作中,很多程序员容易不小心将两个等号写成一个等号,因此当判断整型变量 i 是否等于 3 时,我们可以写为 3 == i ,即把常量(如字面量或已定义的常量)写在前面而把变量写在后面。这是因为当不小心将两个等号写为一个等号时,变量在前面就会导致编译不通,从而快速发现错误(这种写法属于华为公司内部的一条编程规范)。

当你错误地将 == 写成 = 时,如果常量在左侧,那么这行代码将会尝试将常量赋值给变量,这在大多数情况下会导致编译错误(因为常量通常是不可写的),从而立即引起开发者的注意。例如:

if (3 = i) { // 错误,尝试将常量3赋值给变量i,导致编译错误  
    // ...  
}

而如果你将变量放在左侧,那么这行代码在语法上是合法的,但逻辑上是错误的,因为它实际上是在将常量赋值给变量,而不是在比较它们。这样的错误可能更难在编译时被发现,因为编译器不会报错,但程序的逻辑将不符合预期:

if (i = 3) { // 正确编译,但逻辑错误,因为i被赋值为3,然后表达式的结果(即3,非0)被视为真  
    // ...  
}

因此,将常量放在比较操作符的左侧是一种防御性编程的技巧,有助于避免此类逻辑错误。

3.3 三数相等判断误区

在编写程序时,如果我们需要判断三个数是否相等,那么绝对不可以写为 if(5==5==5) ,这种写法的值无论何时都为假,为什么?因为首先 5==5 得到的结果为 1 ,然后 1==5 得到的结果为 0 。如果要判断三个变量 a、b、c 是否相等,那么不能写为 a==b==c ,而应写为 a==b && b==c 。下面来看一个例子:

#include <stdio.h>

// 不能用数学上的连续判断大小来判断某个数
int main()
{
    int a;

    while(scanf("%d",&a))  // 只要 scanf 函数成功读取到一个整数,就会一直执行循环
    {
        // 正确的判断方式应该是使用逻辑运算符 if(a > 3 && a < 10)
        if(3 < a < 10)  // 错误的判断方式,在 C 语言中这种连续比较是不正确的
        {
            printf("a 在 3 和 10 之间\n");
            fflush(stdout);// Clion中需要加上这句代码才会上面的输出语句
        }
        else
        {
            printf("a 不在 3 和 10 之间\n");
        }
    }
}

输出结果:

如果要判断变量 a 是否大于 3 且同时小于 10 ,那么不能写为 3 < a < 10 , 这种写法在数学上的确是正确的,但是在程序中是错误的。首先,无论 a 是大于 3 还是小于 3 , 对于 3<a 这个表达式只有 1 或 0 两种结果。由于 1 和 0 都是小于 10 的,所以无论 a 的值为多少, 这个表达式的值始终为真,因此在判断变量 a 是否大于 3 且同时小于 10 时,要写成 a>3 && a<10 ,这才是正确的写法。


4 逻辑运算符与逻辑表达式

逻辑运算符 “!”、“&&”、“||” 依次为逻辑非、逻辑与、逻辑或,这和数学上的与、或、非是一致的。

运算符用于取反,即将真变为假,假变为真。

!! 是一个常见的技巧,用于将任何非零值转换为1(真),将0转换为0(假)。这是因为!运算符会将非零值视为真并返回0(假),然后再取反就得到了1(真)。

&& 运算符用于逻辑与操作,只有当两边的表达式都为真时,结果才为真。一假即假!

|| 运算符用于逻辑或操作,只要两边的表达式中有一个为真,结果就为真。一真即真!

逻辑非的优先级高于算术运算符,逻辑与和逻辑或的优先级低于关系运算符。

简单记就是: ! > 算术运算符 > 关系运算符 > && > || > 赋值运算符

由逻辑运算符组成的表达式称为逻辑表达式,逻辑表达式的值只有,对应的值为 10

4.1 逻辑运算符的用法

下面是一个包含逻辑运算符以及多重否定(如!!)的程序。这个程序将演示如何使用这些逻辑运算符,并解释它们的行为:

#include <stdio.h>

int main() {
    int a = 1; // 真(在C中,非零值被视为真)
    int b = 0; // 假(在C中,0被视为假)

    // 逻辑非(!)
    printf("!a = %d\n", !a); // 预期输出:!a = 0,因为a是真,非真为假
    printf("!b = %d\n", !b); // 预期输出:!b = 1,因为b是假,非假为真

    // 双重否定(!!)
    printf("!!a = %d\n", !!a); // 预期输出:!!a = 1,因为!a是0(假),再取非就是真
    printf("!!b = %d\n", !!b); // 预期输出:!!b = 0,因为!b是1(真),再取非就是假

    // 逻辑与(&&)
    printf("a && b = %d\n", a && b); // 预期输出:a && b = 0,因为a是真,但b是假,真与假为假
    printf("a && a = %d\n", a && a); // 预期输出:a && a = 1,因为a是真,真与真为真

    // 逻辑或(||)
    printf("a || b = %d\n", a || b); // 预期输出:a || b = 1,因为a是真,真或任何值都为真
    printf("b || b = %d\n", b || b); // 预期输出:b || b = 0,因为b是假,假或假还是假

    // 混合使用
    printf("!!(a && b) = %d\n", !!(a && b)); // 预期输出:!!(a && b) = 0,因为a && b是0(假),再取双重非还是假
    printf("!!(a || b) = %d\n", !!(a || b)); // 预期输出:!!(a || b) = 1,因为a || b是1(真),再取双重非还是真

    return 0;
}

4.2 闰年的判断

判断一个年份是否为闰年通常有以下两种常见的规则:

  1. 能被 4 整除但不能被 100 整除的年份为闰年。例如,2008 年是闰年,因为 2008 能被 4 整除但不能被 100 整除;1900 年不是闰年,因为它能被 100 整除但不能被 400 整除。

  2. 能被 400 整除的年份也是闰年。例如,2000 年是闰年,因为它能被 400 整除。

下例中的代码是计算一年是否为闰年的例子,因为需要重复测试,所以我们用了一个 while 循环:

#include <stdio.h>

int main() {
    int year;  // 定义一个整型变量 `year` 用于存储输入的年份

    while (scanf("%d", &year) && year!= 0) {  // 只要能成功读取一个整数到 `year` 并且 `year` 不等于 0,就会一直执行循环
        if (year % 4 == 0 && year % 100!= 0 || year % 400 == 0)  // 判断年份是否为闰年的条件
        {  
            printf("%d is leap year\n", year);  // 如果是闰年,输出相应信息
            fflush(stdout);  // 立即刷新标准输出缓冲区,确保输出内容立即显示
        }
        else
        {
            printf("%d is not leap year\n", year);  // 如果不是闰年,输出相应信息
            fflush(stdout);  // 立即刷新标准输出缓冲区,确保输出内容立即显示
        }
    }
    printf("Program exited.\n");  // 当循环结束(即输入为 0 时),输出程序已退出的信息
    return 0;
}

输出结果:

if (year % 4 == 0 && year % 100!= 0 || year % 400 == 0)

if ((year % 4 == 0 && year % 100!= 0) || year % 400 == 0)
这两个表达式的逻辑是一样的,括号在这里主要是为了增强代码的可读性和明确运算的先后顺序,即使不加括号,其运算结果也是相同的。

但是,在初始时,由于是人工阅卷,如果括号写得较多,不便于阅卷老师阅卷,避免可分,能不加括号就不加括号,如这句代码:if (((year % 4 == 0) && (year % 100!= 0)) || (year % 400 == 0)),括号很多,完全没必要!

所以,常见运算符的优先级还是得记住!

4.3 短路运算

在 C 语言中,逻辑运算符 &&(逻辑与)和 ||(逻辑或)确实实现了短路运算(short-circuit evaluation)。这意味着,如果逻辑表达式的第一部分已经足够确定整个表达式的值,那么第二部分将不会被评估。这常用于条件判断中,以避免潜在的错误或不必要的计算。

下面是一个使用 && 运算符实现短路运算的例子,其中在短路运算符后面跟了 printf 打印语句,但由于短路的原因,这些打印语句可能不会被执行。

printf 函数返回一个整数值,该值表示实际输出的字符数(不包括结尾的空字符'\0')。如果输出成功,这个返回值将大于或等于0;如果发生错误,返回值将是负值。

#include <stdio.h>

int main() {
    int a = 0;
    int b = 1;

    // 使用 && 运算符的短路特性
    // if 括号里面的printf不会被打印
    if (a && (printf("This && will not print.\n") > 0)) {
        // 这个代码块不会执行,因为 a 是 0(假),所以 && 表达式的第一部分已经决定了整个表达式的值
        printf("我不会被打印");
    }

    //让 && 表达式的第一部分为假
    // if 括号里面的printf会被打印
    if (!a && (printf("This && will print.\n") > 0)) {
        // 这个代码块会执行,因为 !a 是 1(真),所以需要评估第二部分来确定整个表达式的值
        printf("我会被打印1\n");
    }

    // 使用 || 运算符的短路特性
    // if 括号里面的printf不会被打印
    if (b || (printf("This will not print either, because b is already true.\n") > 0)) {
        // 这个代码块不会执行,因为 b 是 1(真),所以 || 表达式的第一部分已经足够确定整个表达式的值
        printf("我会被打印2\n");
    }

    // 让 || 表达式的第一部分为假
    // if 括号里面的printf会被打印
    if (0 || (printf("This || will print, because the first part of || is false.\n") > 0)) {
        // 这个代码块会执行,且 printf 语句也会执行,因为 || 表达式的第一部分是 0(假),所以需要评估第二部分来确定整个表达式的值
        printf("我会被打印3\n");
    }

    return 0;
}

输出结果:


5 赋值运算符

赋值运算符 = 在编程中用于将一个表达式的值赋给另一个变量。然而,这个操作受到左值和右值概念的限制。

5.1 左值与右值

在计算机编程中,特别是 C 和 C++ 等语言中,左值(L-value)和右值(R-value)是两个重要的概念,它们源于赋值操作的上下文,但具有更广泛的含义。

左值(L-value)左值是指可以出现在赋值表达式左侧的表达式。简单来说,左值代表了一个明确的内存位置,即它可以被赋予一个新值。在赋值操作中,左值用于存储右侧表达式计算出的结果。例如,在表达式 a = b + 25; 中,a 是一个左值,因为它代表了一个可以被赋新值的变量。

右值(R-value)右值则是指可以出现在赋值表达式右侧的表达式右值通常表示一个具体的值或者一个临时对象它不能表示一个可以存储新值的内存位置。在上面的例子中,b + 25 是一个右值,因为它是一个表达式的结果,这个结果可以赋值给左值。但是,b + 25 不能作为左值,因为它并未标识一个特定的位置(并不对应特定的内存空间)。因此,b + 25 = a 这条赋值语句是非法的。

5.2 赋值操作的限制

左值必须可修改赋值操作要求左侧必须是一个左值,即一个可以存储新值的内存位置。如果尝试将一个右值(如表达式的结果)放在赋值语句的左侧,编译器会报错,因为右值没有内存位置来存储新值。

右值提供值:赋值操作的右侧可以是一个右值,它提供了要赋给左值的具体值。右值可以是字面量、表达式的结果、函数调用返回的值等。

示例与错误用法

  • 正确用法:a = b + 25;(a是左值,b + 25 是右值)
  • 错误用法:b + 25 = a;(尝试将右值 b + 25 用作左值,这是不允许的)
  • 编译错误结果,如下图所示:

5.3 复合赋值运算符

在C语言中,复合赋值运算符是一种简化的赋值方式,它将算术运算符或位运算符与赋值运算符(=)结合使用,以便在单个操作中完成值的计算和赋值。这些运算符包括 +=、-=、*=、/=、%= 等。下面是一张简明的表格,列出了这些复合赋值运算符及其功能:

运算符含义示例(假设 a = 5, b = 2)
+=加法赋值a += b; 等同于 a = a + b; 结果:a = 7
-=减法赋值a -= b; 等同于 a = a - b; 结果:a = 3
*=乘法赋值a *= b; 等同于 a = a * b; 结果:a = 10
/=除法赋值(整数除法时向下取整)a /= b; 等同于 a = a / b; 结果:a = 2
%=求余赋值(模运算)a %= b; 等同于 a = a % b; 结果:a = 1

下面是一个简单的C语言程序示例,展示了如何使用这些复合赋值运算符:

#include <stdio.h>

int main() {
    int a = 5;
    int b = 2;

    // 使用复合赋值运算符
    a += b;  // a = a + b
    printf("a += b: a = %d\n", a);  // 7

    a -= b;  // a = a - b
    printf("a -= b: a = %d\n", a);  // 5

    a *= b;  // a = a * b
    printf("a *= b: a = %d\n", a);  // 10

    a /= b;  // a = a / b
    printf("a /= b: a = %d\n", a);  // 5

    a = 10;  // 重置a的值
    a %= b;  // a = a % b
    printf("a %= b: a = %d\n", a);  // 0

    return 0;
}

5.4 复合赋值运算符的运算规则与示例解析

在复合赋值运算符(如 +=、-=、*=、/=、%= 等)中,等号(=)后面的表达式首先被计算为一个整体的值,然后将这个值与等号左边的变量进行相应的算术或位运算,并将结果赋值回该变量。

以 a += b + 2; 为例,这里的计算过程可以分为两步:

首先计算等号右边的表达式 b + 2。假设 b 的值是已知的(比如 b = 3),则 b + 2 的结果是 5。然后,将这个结果 5 与 a 的当前值进行加法运算,即 a 的当前值(假设为 10)加上 5,得到 15。最后,将计算结果 15 赋值回 a,更新 a 的值为 15。

这种运算方式简化了代码,使得在需要更新变量值时不必显式地写出变量名两次,但是不好看。例如,a = a + b + 2; 可以更简洁地写为 a += b + 2;


6 sizeof 运算符

很多同学会认为 sizeof 是一个函数,这种理解是错误的,实际sizeof是一个运算符。

sizeof 在 C 和 C++ 中是一个编译时运算符,用于计算对象或类型在内存中所占用的字节数。由于它是编译时求值的,因此其参数可以是任何数据类型、数组、结构体、联合体或者指针,但不可以是函数类型或者未定义的类型(如未声明的变量类型)。

#include <stdio.h>

int main() {
    int a = 10;
    double b = 3.14;
    char c = 'A';
    char str[] = "Hello, World!";

    // 使用 sizeof 运算符获取变量和数组的内存大小
    printf("Size of int: %zu bytes\n", sizeof(a));  // 4bytes
    printf("Size of double: %zu bytes\n", sizeof(b));  // 8bytes
    printf("Size of char: %zu bytes\n", sizeof(c));  // 1bytes
    printf("Size of string (including null terminator): %zu bytes\n", sizeof(str));  // 14bytes

    // 也可以用于类型
    printf("Size of int type: %zu bytes\n", sizeof(int));  // 4bytes
    printf("Size of double type: %zu bytes\n", sizeof(double));  // 8bytes
    printf("Size of char type: %zu bytes\n", sizeof(char));  // 1bytes

    // 注意:sizeof 对于指针总是返回指针自身的大小,与指针指向的类型无关
    // 在大多数现代系统上,指针的大小是固定的(例如,在 32 位系统上通常是 4 字节,在 64 位系统上通常是 8 字节)
    int *ptr = &a;
    printf("Size of pointer to int: %zu bytes\n", sizeof(ptr));  // 8bytes

    return 0;
}

sizeof 对于指针总是返回指针自身的大小,与指针指向的类型无关。
 在大多数现代系统上,指针的大小是固定的(例如,在 32 位系统上通常是 4 字节,在 64 位系统上通常是 8 字节)


 7 运算符优先级表

同一优先级的运算符,运算次序由结合方向所决定。
简单记就是: ! > 算术运算符 > 关系运算符 > && > || > 赋值运算符


8 小节判断题

1、算术运算符包含 “+”、“-”、“*”、“/” 和 “%”,乘、除、取余运算符的优先级高于加、减运算符?

A. 正确         B. 错误

答案:A

解释:正确的,这个需要记住。


2、“%” 取余(也称为取模运算)可以用于浮点数?

A. 正确         B. 错误

答案:B

解释:取模运算只能用于整型数,不能用于浮点数。


3、关系运算符的优先级高于算术运算符?

A. 正确         B. 错误

答案:B

解释:关系运算符优先级是低于算术运算符的,记住这个对于初试大题编写是必须的。


4、代码编写 “int a = 5; if (3 < a < 10)” 这种编写方式是否正确?

A. 正确         B. 错误

答案:B

解释:在程序中是错误的。首先,无论 a 是大于 3 还是小于 3 ,对于 “3 < a” 这个表达式只有 1 或 0 两种结果。由于 1 和 0 都是小于 10 的,所以无论 a 的值为多少,这个表达式的值始终为真,因此在判断变量 a 是否大于 3 且同时小于 10 时,要写成 “a > 3 && a < 10”,这才是正确的写法。


5、C 语言中逻辑表达式的值是真或假,真的值是 1,假是 0 ?

A. 正确         B. 错误

答案:A

解释:正确的,这个需要记住。


6、逻辑非的优先级高于算术运算符,逻辑与和逻辑或的优先级低于关系运算符?

A. 正确         B. 错误

答案:A

解释:逻辑非是单目运算符,优先级高于算术运算符,逻辑与和逻辑或的优先级低于关系运算符。


7、int a = 1, b = 0; b + 2 = a; 这个运算可以正常编译通过 ?

A. 正确         B. 错误

答案:B

解释:b + 2 = a 无法编译通过,因为 b + 2 是表达式,不是变量,没有对应的内存空间,无法作为左值。


8、sizeof(char) 的值是 1?

A. 正确         B. 错误

答案:A

解释:sizeof 用来计算不同类型空间大小,char 类型占用一个字节空间大小。


9、int j = 1; j || printf("hello world\n"); 代码运行后,我们会看到“hello world”的打印输出?

A. 正确         B. 错误

答案:B

解释:由于 j 等于 1,为真。逻辑或的短路运算,当前一个表达式为真时,后面的表达式不会得到运行,因此 printf("hello world\n"); 不会得到运行,所以看不到其打印输出。


9 OJ 练习

9.1 课时3作业1

这道题主要是练习关系运算符与逻辑与逻辑运算符,闰年的判断规则是可以被 4 整除同时不能被 100 整除,或者可以被 400 整除,在考研初试时,我们要记住运算符的优先级,不要加太多的括号,避免阅卷老师扣分。
#include <stdio.h>

int main() {
    int year;
    scanf("%d",&year);
    if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0){
        printf("yes\n");
    }else{
        printf("no\n");
    }
    return 0;
}

9.2 课时3作业2

这个题目主要考察的是 scanf 读取不同数据类型,同时不同的数据类型可以做算术运算,注意控制输出的数据格式。
#include <stdio.h>

int main() {
    int i;
    char j;
    float k;
    scanf("%d %c%f",&i,&j,&k); // 注意%c前面的空格
    printf("%.2f\n",i+j+k);  //保留两位小数
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/798626.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI大模型探索之旅:深潜大语言模型的训练秘境

在人工智能的浩瀚星空中&#xff0c;大语言模型无疑是最耀眼的星辰之一&#xff0c;它们以无与伦比的语言理解与生成能力&#xff0c;引领着智能交互的新纪元。本文将带您踏上一场探索之旅&#xff0c;深入大语言模型的训练秘境&#xff0c;揭开其背后复杂而精妙的全景画卷。 …

51单片机9(使用左移实现流水灯编程)

一、序言&#xff1a;下面我们来给大家介绍一下这个流水灯&#xff0c;流水灯如何来实现&#xff1f;我们依然使用这个工程来完成它。 1、那要使用实现这个流水灯&#xff0c;那我们只需要让D1到D8逐个的点亮&#xff0c;那同样要实现它足够的点亮&#xff0c;也会涉及到延时&…

PNC103/103B-PORPSVOC/波洛斯数据手册高性能32位音频处理器

PNC 103/103B是针对降噪市场推出的一颗音频处理芯片&#xff0c;搭载POROSVOC业内领先的DNN神经网络降噪算法或搭载POROSVOC AECAES回声消除算法&#xff0c;可广泛且快速应用于音视频&#xff0c;对讲&#xff0c;话务等领域。 该芯片采用32bit RSIC架构内核&#xff0c;并加入…

【学习笔记】无人机(UAV)在3GPP系统中的增强支持(一)-3GPP TR 22.829 V17.1.0技术报告

本文是3GPP TR 22.829 V17.1.0技术报告&#xff0c;专注于无人机&#xff08;UAV&#xff09;在3GPP系统中的增强支持。文章提出了多个无人机应用场景&#xff0c;分析了相应的能力要求&#xff0c;并建议了新的服务级别要求和关键性能指标&#xff08;KPIs&#xff09;。 下载…

MyBatis where标签替换WHERE 1 = 1会提升性能吗

MyBatis <where>标签替换WHERE 1 1会提升性能吗 查看项目早期数据库查询语句时&#xff0c;发现很多地方写了WHERE 1 1&#xff0c;怀疑这里有性能损失&#xff0c;想替换成<where>标签。 验证 已知索引 CREATE INDEX BP_LOG_BP_DATE_IDX ON QXX.BP_LOG (BP_…

pxe高效网络批量装机

文章目录 一&#xff0c; PXE远程安装服务&#xff08;一&#xff09;三种系统装机的方式&#xff08;二&#xff09;linux装机1. 加载 Boot Loader2. 加载启动安装菜单3. 加载内核和 initrd4. 加载根文件系统5. 运行 Anaconda 安装向导 &#xff08;三&#xff09;实现过程&am…

games103作业2(未完)

PBD方法 首先是每个质点的力的分析&#xff0c;不考虑碰撞和弹簧弹力的情况下&#xff0c;每个质点受重力的影响&#xff0c;所以需要对每个质点进行速度和位置的重力影响更新。 float t 0.0333f; float damping 0.99f; int[] E; float[] L; Vector3[] V; Vector3 gra…

Ubuntu系统安装mysql之后进行远程连接

1.首先要配置数据库允许进行远程连接 1.1 打开MySQL配置文件 /etc/mysql/mysql.conf.d/mysqld.cnf sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf1.2 修改 bind-address 行 #按i进入插入模式 bind-address 0.0.0.0 #按 Esc 键退出插入模式。 #输入:wq 然后按 Enter 保存并退…

【机器翻译】基于术语词典干预的机器翻译挑战赛

文章目录 一、赛题链接二、安装库1.spacy2.torch_text 三、数据预处理赛题数据类定义 TranslationDataset批量处理函数 collate_fn 四、编码器和解码器Encoder 类Decoder 类Seq2Seq 类注意事项 五、主函数1. load_terminology_dictionary(dict_file)2. train(model, iterator, …

windows USB 设备驱动开发- USB Type-C支持(二)

Microsoft 提供 USB Type-C 连接器系统软件接口 (UCSI) 符合规范的 ACPI 传输驱动程序。 如果你的设计包含带有 ACPI 传输的嵌入式控制器&#xff0c;请在系统的 BIOS/EC 中实现 UCSI&#xff0c;并加载随机 UCSI 驱动程序&#xff08;UcmUcsiCx.sys 和 UcmUcsiAcpiClient.sys&…

【Linux】:重定向和缓冲区

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家带来关于重定向和缓冲区的相关知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精…

海事无人机解决方案

海事巡察 海事巡察现状 巡查效率低下&#xff0c;存在视野盲区&#xff0c;耗时长&#xff0c;人力成本高。 海事的职能 统一管理水上交通安全和防治船舶污染。 管理通航秩序、通航环境。负责水域的划定和监督管理&#xff0c;维护水 上交通秩序&#xff1b;核定船舶靠泊安…

Spring Boot集成groovy快速入门Demo

1.什么是groovy&#xff1f; Groovy 是构建在 JVM 上的一个轻量级却强大的动态语言&#xff0c;它结合了 Python、Ruby 和 Smalltalk 的许多强大的特性。 Groovy 就是用 Java 写的&#xff0c;Groovy 语法与 Java 语法类似&#xff0c;Groovy 代码能够与 Java 代码很好地结合&…

QQ频道导航退出

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/140413538 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

C#中的MD5摘要算法与哈希算法

文章目录 一、哈希算法基础二、MD5 算法原理三、MD5摘要算法四、哈希算法五、C#实现示例MD5算法示例哈希算法示例字符串MD5值对比 六、总结 一、哈希算法基础 哈希算法是一种单向密码体制&#xff0c;它将任意长度的数据转换成固定长度的字符串。这种转换是不可逆的&#xff0…

Java二十三种设计模式-工厂方法模式(2/23)

工厂方法模式&#xff1a;设计模式中的瑞士军刀 引言 在软件开发中&#xff0c;工厂方法模式是一种常用的创建型设计模式&#xff0c;它用于处理对象的创建&#xff0c;将对象的实例化推迟到子类中进行。这种模式不仅简化了对象的创建过程&#xff0c;还提高了代码的可维护性…

WordPress:无法创建新文章?创建新帖子时候页面空白

wordPress中我们新建文章的时候&#xff0c;会遇到页面空白&#xff0c;这个问题是怎么导致呢&#xff1f;我们可以打开F12开发者模式看下报错信息&#xff0c;这是一个警告信息 Warning: Creating default object from empty value in /pub 到数据库 wp_posts中查看生成了很…

SpringBoot新手快速入门系列教程十一:自动生成API文档,Springboot3.x集成SpringDoc

本次项目我们用Maven来做&#xff0c;最近发现gradle其实很多项目的支持比较差&#xff0c;所以项目还是用Maven来新建项目。对比了市面上的几种API生成第三方库&#xff0c;只有springdoc 是能够按照文档就能部署出来的。 官网&#xff1a; OpenAPI 3 Library for spring-bo…

Mac电脑下运行java命令行出现:错误: 找不到或无法加载主类

mac 电脑 问题复现 随手写了一个main方法&#xff0c;想用命令行操作 进入 BlockDemo.java 所在目录&#xff1a; wnwangnandeMBP wn % cd /Users/wn/IdeaProjects/test/JianZhiOffer/src/main/java/com/io/wn wnwangnandeMBP wn % ls -l total 16 -rw-r--r-- 1 wangnan …

Qt文件下载工具

在Qt中实现文件下载功能&#xff0c;通常可以通过多种方式来完成&#xff0c;包括使用 QNetworkAccessManager 和 QNetworkReply 类&#xff0c;或者使用更高级别的 QHttpMultiPart 类。以下是两种常见的实现方法&#xff1a; 方法1&#xff1a;使用 QNetworkAccessManager 和…