C语言梦开始的地方4

文章目录

C语言梦开始的地方4

在上一章节我们了解了C语言各种操作符,通过算术操作符我们知道C语言中是怎么处理算术计算,通过位运算我们知道C语言是怎么处理2进制运算,通过赋值操作符我们知道C语言中初始化和赋值的区别等等一些知识点。

本章节我们继续了解C语言的其他操作符和选择与循环语句

选择语句

选择语句C语言提供了两个:一个是if 一个是switch

if

if语句的语法形式如下:

复制代码
if(表达式)
	语句;

表达式为真时执行语句,表达式为假时语句不执行,在C语言中我们把0为假,非0为真;

也就是说if中的表达式写非0那么它就必定执行如果写0那么它必定不执行。

C语言通常将1认为真,0认为假。

c 复制代码
int main()
{
    int num = 0;
    scanf("%d",&num);

    if(num % 2 == 0)
    {
        printf("%d是偶数\n",num);
    }
    if(num % 2 != 0)
    {
        printf("%d是奇数\n",num);
    }
    
    return 0;
}

上述代码是一个简单判断num是否是奇偶数的代码

在我们的逻辑里面这个代码只会进一个if里面去实则不然它其实会将上述代码中的2个if都执行一遍,如果只输入一个num那么我们只需要判断2次,那么输入10次num就要判断20次以此类推那么n次就要判断n * 2次

那么C语言对这种需要多次判断是不是也提供了对应的解决方法呢?

是的,C语言提供了:else

else

else语句的语法格式为:

复制代码
if(表达式)  		
	语句;				
else 语句;	

此时我们再去修改刚才的代码

c 复制代码
int main()
{
    int num = 0;
    scanf("%d",&num);

    if(num % 2 == 0)
    {
        printf("%d是偶数\n",num);
    }
    else {
        printf("%d是奇数\n",num);
    }
    return 0;
}

那么不管num是奇数还是偶数该程序只会判断1次

注意

  1. ifelse 在没有像上述代码的花括号时那么ifelse 默认只会控制一条语句
  2. 浮点数在内存中是近似存储的,0.1 实际可能存成 0.100000001...,所以 if(0.1 * 3 == 0.3) 这种比较结果往往出乎意料。判断两个小数是否相等,应比较它们差的绝对值是否足够小:
    if (fabs(a - b) < 0.000001
c 复制代码
int main()
{
    int num = 0;
    scanf("%d",&num);
    if(num % 2 == 0)
        printf("%d是偶数\n",num);
        printf("%d是奇数\n",num);
    return 0;
}

此时num为偶数时都会打印,num为奇数时只会打印num是奇数

所以在编写这种程序时加上花括号会更好一点,减少歧义或不更改原本的含义

嵌套if

if else 语句中,else可以与另一个if语句连用

比如:我们要先判断一个数是否是正数,然后再判断这个数是偶数还是奇数

c 复制代码
int main()
{
    int num = 0;
    scanf("%d", &num);
    if (num == 0)
        printf("输入的数字是0\n");
    else
    {
        if (num > 0)
                printf("输入的数字是正数\n");
        else
            printf("输入的数字是负数\n");
    }
    return 0;
}

注意

  1. 我们需要注意的是C语言的语法中没有else if这种语法 ,也就是下面这个代码是等价于上述代码的,else if只是如今行业里面的编写习惯
  2. 层级越深,代码越难读。能合并的条件就用逻辑操作符合并(if(age >= 18 && age <= 36)),能用 switch 就用 switch,保持结构扁平。

但是我们不建议像下面这样写代码,因为悬空else的问题

c 复制代码
int main()
{
	int num = 0;
	scanf("%d", &num);
	if(num == 0)
		printf("输入的数字是0\n");
	else if(num > 0) //这里的if 相当于嵌套在else语句中,形成了嵌套结构
			printf("输入的数字是正数\n");
	else
		printf("输入的数字是负数\n");
	return 0;
}

悬空else

在C语言中,else 总是与距离它最近的、且尚未配对的 if 相结合(即就近配对原则)。当 if 与 else 嵌套书写时,如果缩进不当或省略花括号,就容易产生歧义,这种现象被称为"悬空else"

c 复制代码
int main()
{
    int a = 0;
    int b = 2;
    if (a == 1)
        if (b == 2)
            printf("hehe\n");
    else
        printf("haha\n");
    return 0;
}

比如上述代码最下面的 else 是和第二个 if 匹配的,所以我们在写这些代码时能用花括号就用花括号。

switch语句

switch语句,选择语句的第二种语法。上述都是if语法的衍生写法

我们来看看switch语句的语法格式

复制代码
switch(表达式)
{
 case value1:
   语句;
case value2: 
  语句;
default:
 语句;
}

switch规则如下:

  1. 表达式类型 必须是整型(int、char、enum 等),不能是浮点数或字符串
  2. case 值类型 必须是编译期常量(字面量、宏、枚举常量),不能是变量或表达式(如 score >= 80 绝对不行)
  3. case 唯一性 同一个 switch 中,case 的值不能重复
  4. break 和贯穿匹配后会顺序执行,遇到 break 才跳出;可故意利用贯穿来合并分支
  5. default 位置可选,通常放最后,用来处理所有未匹配的情况
  6. 变量定义在 case 中定义变量需要加 {} 限定作用域

我们看下面的switch代码:

c 复制代码
int main()
{
    int score = 0;
    scanf("%d",&score);
    switch(score / 10)
    {
        case 10:
        case 9:
        case 8:
            printf("优秀\n");
            break;
        case 7:
        case 6:
            printf("及格\n");
            break;
        default:
            printf("不及格\n");
    }

    return 0;
}

关系操作符

经过刚才选择语句的了解我们就能很快的了解并上手关系操作符了

关系操作符:> < >= <= == != 结果通常为1或0

注意:===极易混淆。因为if(score = 60) 是把 60 赋值给 score,表达式值为 60(非0为真),永远成立,编译器还不一定报错。建议把常量放左边写 if(60 == score),一旦漏写一个 =,编译器会立刻报错提醒你。

c 复制代码
a == b;
a != b;
a < b;
a > b;
a <= b;
a >= b;

当我们要判断一个区间时在生活中是这样写的

当我们要判断当前年龄在哪个阶段,此时我们要判断当前年龄是青年这个阶段吗,那么在外面生活中就是这样写 18 <= age <= 36 这个区间内是青年

但是如果我们在C语言这样写会发生什么

c 复制代码
int main()
{
    int age = 0;
    scanf("%d", &age);
    if (18 <= age <= 36)
    {
        printf("青年\n");
    }
    return 0;
}

最终打印结果是青年。为什么?因为age = 10, 10 >= 18吗?很明显不>=,那么此时结果为0,0 <= 36吗?36 >= 0结果为1,那么为真if执行下面语句。

所以要这样写:

c 复制代码
int main()
{
    int age = 0;
    scanf("%d", &age);
    if (age >= 18 && age <= 36) // &&是逻辑操作符
    {
        printf("青年\n");
    }
    return 0;
}

条件操作符

严格来说C语言中只有一个条件操作符又叫三元运算符? :

该操作符等价于if else

比如我们要求a,b最大值时可以这样写:

c 复制代码
int main()
{
    int a = 10,b = 20;

    int max = (a > b) ? a : b;

    printf("%d\n",max);
}

有时如果想代码简洁一点就可以用条件操作符来代替if else

但是我想说的是代码首先是给人看的,其次才是给编译器来看。

逻辑操作符

逻辑操作符:! && ||

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

注意:&&||是短路求值,&& 左边为假不看右边,||左边为真不看右边

我们写一个判断闰年的代码:什么是闰年?闰年是指能被4整除同时不能被100整除或能被400整除的是闰年

c 复制代码
int main()
{
     // 判断闰年
    int year = 0;
    scanf("%d", &year);
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
        printf("%d是闰年\n", year);
    else
        printf("%d不是闰年\n", year);
    return 0;

}

循环语句

循环语句C语言提供了三个:whiledo......whilefor

while语句

首先上来就是执行判断表达式,表达式的值为0,循环直接结束;表达式的值不为0,则执行循环语句,语句执行完后再继续判断,是否进行下一次判断

while循环的语法结构:

复制代码
while(表达式)
	语句;

我们来写两个代码看看

使用while循环实现打印1到10的值

c 复制代码
int main()
{
    int n = 1;
    while(n <= 10)
    {
        printf("%d ",n);
        n++;
    }
    return 0;
}

逆序输出num,比如num为1234就输出 4 3 2 1

c 复制代码
int main()
{
    int num = 0;
    scanf("%d",&num);

    while(num > 0)
    {
        printf("%d ",num % 10);
        num /= 10;
    }
    printf("\n");
    return 0;
}

for语句

三种循环中for循环用的最多也是最好掌握的循环

for循环的语法格式是

复制代码
for(表达式1;表达式2;表达式3)
	语句;

使用for循环实现打印1到10的值

c 复制代码
int main()
{
    for(int i = 1;i <= 10;++i)
    {
        printf("%d ",i);
    }
    return 0;
}

再来写一个:计算1~100之间3的倍数的数字之和

c 复制代码
int main()
{
    int sum = 0;
    for(int i = 0;i < 100;++i)
    {
        if(i % 3 == 0)
        {
            sum += i;
        }
    }
    printf("%d\n",sum);
    return 0;
}

for循环和while循环对比

for 和while 在实现循环的过程中都有初始化、判断、调整这三个部分,但是for 循环的三个部

分非常集中,便于代码的维护,而如果代码较多的时候while 循环的三个部分就比较分散,所以从形

式上for 循环要更优一些。

do......while语句

do while是三个循环中用的最少的,也是最不好用的

do while的语法格式:

复制代码
do{
	语句;
}while(表达式);

while 和for 这两种循环都是先判断,条件如果满足就进入循环,执行循环语句,如果不满足就跳出循环;

而 do while 循环则是先直接进入循环体,执行循环语句,然后再执行 while 后的判断表达式,表达式为真,就会进行下一次,表达式为假,则不再继续循环。
使用do while循环打印1到10

c 复制代码
int main()
{
    int i = 1;
    do
    {
        printf("%d ", i);
        i++;
    } while (i <= 10);
    return 0;
}

输入一个正整数,计算这个整数是几位数?

比如: 输入:1234,输出:4

c 复制代码
int main()
{
    int n = 1234;
    int cnt = 0;
    do{
        cnt++;
        n /= 10;
    }while(n > 0);

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

    return 0;
}

break 和 continue语句

在循环中,break 和 continue 用来控制循环的走向:

  • break:立即终止整个循环,跳出循环体,执行循环后面的代码
  • continue:跳过本次循环的剩余语句,直接进入下一次循环的判断

在switch时我们就遇到过break,那么我们知道break时终止循环跳出循环体用的。那么为什么switch也可以用,因为switch的运行方式是类似循环的不过的是switch是从头到尾的运行且只运行一次

break和continue在三个循环中的代码如下:

while循环

c 复制代码
int main()
{
    //i等于5时退出循环
    int i = 0;
    while(i < 10)
    {
        i++;
        if(i == 5)
        {
            break;
        }
        printf("%d ",i);
    }
    printf("\n");
    //输出1到10以内的奇数
    i = 0;
    while(i < 10)
    {
        i++;
        if(i == 5)
        {
            continue;
        }
        printf("%d ",i);
    }
    printf("\n");
    return 0;
}

for循环

c 复制代码
int main()
{
    // i等于5时退出循环
    int i;
    for(i = 1; i <= 10; i++)
    {
        if(i == 5)
        {
            break;
        }
    }
    printf("%d\n",i);
    // 输出1到10以内除5以外的数
    for(i = 1; i <= 10; i++)
    {
        if(i == 5)
        {
            continue;
        }
        printf("%d ",i);
    }
    printf("\n");
    return 0;
}

do while循环

c 复制代码
int main()
{
    // i等于5时退出循环
    int i = 0;
    do
    {
        i++;
        if(i == 5)
        {
            break;
        }
    } while(i < 10);
    printf("%d\n",i);
    // 输出1到10以内除5以外的数
    i = 0;
    do
    {
        i++;
        if(i == 5)
        {
            continue;
        }
        printf("%d ",i);
    } while(i < 10);
    printf("\n");
    return 0;
}

循环嵌套

循环嵌套:指一个循环的循环体内部再包含另一个完整的循环结构。外面的循环叫外层循环,里面的叫内层循环。

执行规则:

  • 每执行一次外层循环,内层循环都要从头到尾完整执行一遍;
  • 若外层循环执行 m 次、内层循环执行 n 次,则内层循环体总共执行 m × n 次;
  • 常见写法中,外层循环通常控制"行",内层循环控制"列"(下面乘法表就是例子)。

while循环

c 复制代码
int main()
{
    int i = 1;
    while(i <= 9)
    {
        int j = 1;
        while(j <= i)
        {
            printf("%d×%d=%-2d ", j, i, i * j);
            j++;
        }
        printf("\n");
        i++;
    }
    return 0;
}

for循环嵌套

c 复制代码
int main()
{
    for(int i = 1; i <= 9; i++)
    {
        for(int j = 1; j <= i; j++)
        {
            printf("%d×%d=%-2d ", j, i, i * j);
        }
        printf("\n");
    }
    return 0;
}

do while循环嵌套

c 复制代码
int main()
{
    int i = 1;
    do
    {
        int j = 1;
        do
        {
            printf("%d×%d=%-2d ", j, i, i * j);
            j++;
        } while(j <= i);
        printf("\n");
        i++;
    } while(i <= 9);
    return 0;
}

goto语句

C语言提供了一种非常特别的语法,就是goto 语句和跳转标号, goto 语句可以实现在同一个函数内跳转到设置好的标号处。

goto 语句如果使用的不当,就会导致在函数内部随意乱跳转,打乱程序的执行流程,所以我们建议是能不用尽量不去使用;但是goto 语句也不是一无是处,在多层循环的代码中,如果想快速跳出使用 goto 就非常的方便了。

它的语法格式

复制代码
标签名:
  语句;
goto 标签名;
c 复制代码
#include <stdio.h>

int main() {
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            if (i == 5 && j == 5) {
                printf("找到目标坐标: (%d, %d)\n", i, j);
                goto end_loop; // 直接跳出两层循环
            }
        }
    }

end_loop: // 跳转目标
    printf("循环已彻底结束。\n");
    return 0;
}
相关推荐
老师我太想进步了20261 小时前
C语言版讲解函数递归
c语言·开发语言
猿长大人2 小时前
C# | 函数式编程入门
开发语言·c#·.net
W_326002 小时前
Python 组合数据类型——序列(列表 & 元组)
开发语言·python
Billy121382 小时前
Day10-C++20 Ranges(上):惰性求值与组合式数据处理
开发语言·c++进阶学习
有点。2 小时前
C++深度优先搜索(二)
开发语言·c++·深度优先
二进制杯莫停2 小时前
A和B环境的python版本相同,B环境无法安装pip依赖,离线安装
开发语言·python·pip
l1t2 小时前
kryonix提交的DuckDB 统一并优化标量执行器基础设施 - #24564 PR
开发语言·数据库·数据仓库·sql
unityのkiven3 小时前
C# 中的奇异递归模板模式:MonoSingleton<T> 的实现
java·开发语言·c#
wuminyu3 小时前
JUC包的AQS与JVM的ObjectMonitor机制对比分析
java·linux·c语言·jvm·c++
就不掉头发4 小时前
C++函数模板
java·开发语言·c++