C 语言流程控制核心:分支与循环语句详解

一.关系、条件和逻辑操作符

在学本章主要内容之前,我们先来了解一下以下几个重要的操作符。

1.关系操作符

关系操作符用于比较两个值的关系,返回布尔值(TrueFalse),常用于编程和数学逻辑中,不同编程语言符号可能略有差异。
常见关系操作符:

操作符描述示例结果
==等于5 == 5
!=不等于3 != 2
>大于10 > 5
<小于4 < 7
>=大于等于5 >= 5
<=小于等于2 <= 3

这些操作符常用于条件语句中,例如 if 语句,来控制程序的执行路径。

示例:
#include<stdio.h>
int main()
{
	int a = 0;
	scanf("%d", &a);//输入一个值
	if (a == 4)//判断两个值是否相等
	{
		printf("a is %d\n", a);
	}
	else
	{
		printf("a isn't 4");
	}
	return 0;
}

值得注意的是在C语言中“==”是检查两个值是否相等,而“=”是将右边的值赋值给左边,两者不要混淆

2.条件操作符

条件操作符,又称三元运算符,是一种根据条件判断结果选择执行不同操作的运算符,语法结构紧凑,常用于简化简单的条件判断逻辑。

语法:条件表达式 ? 表达式1 : 表达式2

执行逻辑
若条件表达式为真(True),则返回 “ 表达式1 ” 的值;
若为假(False),则返回 “ 表达式2 ” 的值。

示例:
#include<stdio.h>
int main()
{
	int a, b;
	scanf("%d %d", &a, &b);//输入a和b
	int m = (a > b ? a : b);//判断结果,并将结果赋值给m
	printf("m is %d\n", m);//输出m
	return 0;
}

注意:
优先级:低于关系操作符和算术操作符,建议用括号明确优先级(操作符的优先原则

如示例中的代码:
int m = (a > b ? a : b);//先算括号里的条件操作符,再将判断结果赋值给m

数据类型:“ 表达式1 ” 和“ 表达式2 ” 的类型需兼容,或可隐式转换为同一类型(即表达式1,2类型相同
可读性避免过度嵌套,复杂逻辑建议用 if-else 语句提升可读性

if-else 语句的区别

特性条件操作符if-else 语句
结构一行表达式多行语句块
返回值可直接赋值或返回值需通过变量接收结果
适用场景简单条件判断复杂逻辑或多条语句

3.逻辑操作符

逻辑操作符是用于对布尔值进行操作的运算符

常见的逻辑操作符:

操作符名称描述示例结果
&&逻辑与两个表达式都为 true 时,结果为 true,否则为 false(5 > 3) && (2 < 4)true
||逻辑或至少一个表达式为 true 时,结果为 true,否则为 false(5>3) || (2>4)true
!逻辑非对布尔值取反:truefalsefalsetrue!(5 == 3)true

逻辑操作符代码示意
逻辑与( &&

错误示范
#include<stdio.h>
int main()
{
	int a;
	scanf("%d", &a);//假如输入90
	if (18 <= a <= 36)//由于操作符的优先级,在if语句里从左到右开始,先算18<=90,为真,等于1,接着1<=36为真,最后打印‘成年人’
	{
		printf("成年人\n");
	}
	return 0;
}
正确示范
#include<stdio.h>
int main()
{
	int a;
	scanf("%d", &a);
	if (a >= 18 && a <= 36)
	{
		printf("成年人\n");
	}
	else
	{
		printf("不是成年人\n");
	}
	return 0;
}

逻辑或( ||

示例
#include<stdio.h>
int main()
{
	int a = 0;
	scanf("%d", &a);
	if (a == 1 || a == 2 || a == 3)
	{
		printf("hahaha\n");//输入1或2或3都会打印“hahaha”
	}
	return 0;
}

逻辑非( !

示例
#include <stdio.h>

int main() 
{
    int num = 0;
    int flag = 1;

    //使用逻辑非操作符 !
    if (!num) 
    {
        printf("num的值是0\n");//会运行,因为!0 等价于 !false → true
    }

    if (!flag) 
    {
        printf("flag的值是0\n");//不会运行,因为!1 等价于 !true → false
    } 
    else 
    {
        printf("flag的值非0\n");//会运行
    }

    //布尔值取反
    int log_in = 0;//0表示未登录
    if (!log_in) 
    {
        printf("用户未登录,请先登录\n");//会运行
    }

    //结合关系表达式
    int x = 10;
    if (!(x > 5)) 
    {
        printf("x小于等于5\n");//不会运行,因为!(x > 5) 等价于 !(true) → false
    } 
    else 
    {
        printf("x大于5\n");//会运行
    }

    return 0;
}

在使用时,需要注意逻辑操作符的 “优先级” 以及 “结合性” 必要时可以使用括号来明确运算顺序

二.if、switch和goto语句

1.if 语句

if 语句的执行流程图
在这里插入图片描述

(1)简单 if 语句

if(condition)
{
//当condition为真时执行
}

(2)if-else 语句

if(condition)
{
//当condition为真时执行
}
else
{
//当condition为假时执行
}

(3)嵌套 if-else 语句

if(condition1)
{
//当condition1为真时执行
}
else if(condition2)
{
//当condition1为假时执行,condition2为真时执行
}
......
else
{
//当以上的conditions为假时执行
}

我们可以结合上述操作符与if语句来判断闰年

#include <stdio.h>

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

    return 0;
}

也能简写下图代码,效果一样

#include <stdio.h>

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;
}

注意:
(1)条件表达式必须是整数类型(如 intchar
(2)ifelse后面默认只跟一条语句
(3)逻辑操作符(&&||!)的优先级低于关系操作符

如代码中的:
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))

(4)C语言中 else 总是与最近的未匹配if 配对(避免else悬空)

if (x > 5)
    if (y > 10)
        printf("x 和 y 都大\n");
else//这个 else 与内层 if 配对
    printf("x 小于等于 5\n");

2.switch语句

(1)switch 基本语法

switch (expression) {
    case constant1:
        // 当 expression 等于 constant1 时执行的代码
        break;
    case constant2:
        // 当 expression 等于 constant2 时执行的代码
        break;
    ...
    default:
        // 当 expression 不等于任何 case 时执行的代码
}

switch语句关键
(1)expression(条件):必须是整数类型(如 intchar)。
(2)constant(常量):必须是整数常量或常量表达式,且不能重复。
(3)break:可选,用于终止 switch 语句的执行。
(4)default:可选,当所有 case 都不匹配时执行。

执行流程
(1)计算表达式:首先计算 expression 的值。
(2)接着匹配 case
expression 等于某个 case 的常量,则执行该 case 后的代码。
若没有匹配的 case,且存在 default,则执行 default 后的代码。

(2)switch语句的穿透特性

穿透特性:若没有 break,程序会继续执行下一个 case 的代码(称为 “穿透” )。

多个case合并(穿透特性)
#include <stdio.h>

int main() {
    char grade = 'B';

    switch (grade) {
        case 'A':
        case 'B':  //'B'、'C'与 'A' 共用代码
        case 'C':
            printf("成绩合格\n");
            break;
        case 'D':
        case 'F':
            printf("成绩不合格\n");
            break;
        default:
            printf("无效等级\n");
    }

    return 0;
}

没有 break 的穿透示例

#include <stdio.h>

int main() {
    int num = 2;

    switch (num) {
        case 1:
            printf("执行 case 1\n");
            //无break,继续执行下一个case
        case 2:
            printf("执行 case 2\n");
            //无break,继续执行下一个case
        case 3:
            printf("执行 case 3\n");
            break;  //有break,最终跳出switch
        default:
            printf("执行 default\n");
    }

    // 输出结果:
    // 执行 case 2
    // 执行 case 3

    return 0;
}

注意:
(1)expression 的类型限制必须是整数类型(如 intchar),不能是浮点数或字符串。
(2)case 常量的唯一性:每个 case 常量必须唯一,否则会导致编译错误。
(3)break 的使用
需要终止时:大多数情况下需要使用 break 终止执行。
需要穿透时:故意不使用 break,让代码继续执行后续 case
(4)default 的位置default 可以放在任意位置,但通常放在末尾以提高可读性

(3)if 与 switch 的对比

特性switch 语句if-else 语句
适用条件整数常量表达式(如 intchar任何表达式
语法复杂度简单条件更简洁复杂条件更灵活
执行效率通过跳转表直接定位分支,效率高依次判断每个条件,效率较低
适用场景等值判断范围判断、复杂逻辑

3.goto语句

goto语句是一种编程语言中的控制流语句,其作用是无条件跳转到程序中指定的标签位置执行后续代码。它通过 “标签”(Label)标记目标位置,标签通常是一个标识符,后跟冒号( : ),位于目标语句之前。

(1)goto 基本语法

goto label;
...
label: // 标签声明
    语句;

关键点:
label:自定义的标识符,用于标记代码位置,遵循变量命名规则(如error_handler、loop_start)。
goto label;:将程序执行跳转到指定的label处继续执行。
标签声明label必须放在某个语句之前,用于标记跳转目标

示例
#include <stdio.h>

int main() 
{
    int i, j;
    for (i = 1; i <= 3; i++) 
    {
        for (j = 1; j <= 3; j++) 
        {
            if (i == 2 && j == 2)
            {
                goto exit;//当i=2且j=2时,使用goto跳出所有循环
            }
        }
    }
    
exit: //标签位置
    printf("hahahaha\n");
    return 0;
}

(2)goto 总结

goto语句是早期编程语言的重要控制工具,但其弊端在大型项目中尤为明显。现代软件开发更强调代码的可读性和可维护性,因此goto通常被视为 “过时” 的特性,仅在极少数场景下谨慎使用。理解其原理有助于阅读历史代码,但在新项目中应尽量避免依赖。

三.for、while和do while循环

1.for循环

for 循环的执行流程图
在这里插入图片描述

C 语言中的 for 循环是一种非常常用的迭代控制结构,用于重复执行特定代码块。

(1)基本语法

for (初始化表达式; 条件表达式; 更新表达式) 
{
    //循环体(重复执行的代码)
}

(2)嵌套 for 循环

尝试打印打印九九乘法表

例如
#include <stdio.h>

int main() 
{
    int i, j;
    for (i = 1; i <= 9; i++) //外层循环控制行数(被乘数
    {
        for (j = 1; j <= i; j++)//内层循环控制列数(乘数
        {
            printf("%d×%d=%-2d  ", j, i, i*j);//格式化输出:左对齐,宽度为7字符
        }
        printf("\n");//每行结束后换行
    }
    
    return 0;
}

运行结果
在这里插入图片描述

(3)循环控制语句

break:提前终止整个循环

for (int i = 1; i <= 10; i++) 
{
    if (i == 5) 
    break;//当i=5时跳出循环
    printf("%d ", i);//输出:1 2 3 4
}

continue:跳过当前迭代

for (int i = 1; i <= 5; i++) 
{
    if (i == 3) 
    continue;//跳过i=3的情况
    printf("%d ", i);//输出:1 2 4 5
}

breakcontinue 详细解析也会在第四点提及到

2.while循环

whlie 语句的执行流程图
在这里插入图片描述

(1)基本语法

while (条件表达式) 
{
    //循环体(重复执行的代码)
}

(2)嵌套 while 循环

可以用于处理多维数据等等(如矩阵):

例如:
#include <stdio.h>

int main() 
{
    int i = 1;
    while (i <= 3)//外层循环控制行数
    {  
        int j = 1;
        while (j <= 3)//内层循环控制列数
        {  
            printf("%d×%d=%d\t", i, j, i*j);
            j++;
        }
        printf("\n");
        i++;
    }
    return 0;
}

运行结果:
在这里插入图片描述

(3)循环控制语句

break:提前终止整个循环

例如:
int i = 1;
while (i <= 10) 
{
    if (i == 5) 
    break;//当i=5时跳出循环
    printf("%d ", i);//输出:1 2 3 4
    i++;
}

continue:跳过当前迭代

例如
int i = 0;
while (i < 5) 
{
    i++;//注意:更新语句需放在continue前
    if (i == 3) 
    continue;//跳过i=3的情况
    printf("%d ", i);//输出:1 2 4 5
}

(4)while 循环的特点

先判断后执行:与 do-while 不同,while 可能一次都不执行。

例如:
int i = 10;
while (i < 5) 
{
    printf("循环体");//不会执行
}

灵活的条件:条件表达式可以是任意类型(会被隐式转换为布尔值)。

例如:
int flag = 1;
while (flag) 
{  //等价于 while(flag != 0)
   //循环体
    flag = 0;//终止条件
}

无限循环:条件恒为真时,需通过break终止。

例如:
while (1) 
{   //无限循环
    printf("hahaha");
    if (condition) 
    break;//手动终止
}

3.do while循环

do while 循环的执行流程图
在这里插入图片描述

C 语言中的do-while循环是一种后测试循环结构,与while和for循环不同的是,它会先执行一次循环体,再判断条件是否继续执行。

(1)基本语法

do {
    //循环体(至少执行一次)
} while (条件表达式);//注意分号不能省略

例如我们来打印1到5的数字

#include <stdio.h>

int main() 
{
    int i = 1;
    do {
        printf("%d ", i);
        i++;
    } while (i <= 5);//最后的“ ;”别漏了
    return 0;
}

运行结果:
在这里插入图片描述

(2)嵌套 do while 循环

用于处理多维数据:

例如:
#include <stdio.h>

int main() 
{
    int i = 1;
    do {//外部循环
        int j = 1;
        do {//内部循环
            printf("%d×%d=%d\t", i, j, i*j);
            j++;
        } while (j <= 3);
        printf("\n");
        i++;
    } while (i <= 3);
    return 0;
}

运行结果:
在这里插入图片描述

(3)循环控制语句

break:提前终止整个循环

例如:
int i = 1;
do {
    if (i == 5) 
    break;//当i=5时跳出循环
    printf("%d ", i);//输出:1 2 3 4
    i++;
} while (i <= 10);

continue:跳过当前迭代

例如:
int i = 0;
do {
    i++;
    if (i == 3) 
    continue;//跳过i=3的情况
    printf("%d ", i);//输出:1 2 4 5
} while (i < 5);

(4)do while 循环的特点

至少执行一次:即使条件一开始就不满足,循环体也会执行一次。
条件后置:适合需要先执行操作再判断条件的场景(如交互式输入)。
无限循环:条件恒为真时,需通过break终止。

值得注意的是
分号不可省略:在while (条件) ; 末尾的分号是语法必需的。
避免死循环:确保条件最终会变为假,或在循环体中使用break。
变量作用域循环变量需在 do-while 之前定义

错误示范:

do {
    int i = 0;//每次循环重新初始化,无意义
    i++;
} while (i < 5);//错误:i在此处不可见

正确示范:

int i = 0;
do {
    i++;
} while (i < 5);

4.for、while和do while循环之间的对比

特性for 循环while 循环do-while 循环
基本语法for (初始化; 条件; 更新) { … }while (条件) { … }do { … } while (条件);
执行顺序先判断条件,再执行循环体先判断条件,再执行循环体先执行一次循环体,再判断条件
最少执行次数0 次(条件不满足时跳过)0 次(条件不满足时跳过)1 次(无论条件如何都先执行)
循环变量初始化位置for语句内部或外部必须在while之前初始化必须在do-while之前初始化
循环变量更新位置for语句的更新表达式中在循环体内部手动更新在循环体内部手动更新
适用场景已知循环次数(如遍历数组)未知循环次数,依赖条件判断需要至少执行一次(如输入验证)

四.break和continue语句解析以及用法

1.基本概念

break和continue 是编程语言中用于控制循环流程的关键字,
它们的核心区别在于:
break:立即终止当前所在的整个循环( for / while / do-while),跳出循环体执行后续代码。
continue:跳过当前循环体中剩余的代码,直接进入下一次循环迭代。

2.语法与执行逻辑

(1)对于break语句

while (条件1) 
{
    //代码块1
    if (条件2) 
    {
        break; //满足条件时终止循环
    }
    //代码块2(break后不会执行)
}
//循环结束后执行此处

使用 break 语句效果
提前终止循环:当满足某个条件时无需继续执行循环。

例如:
//查找数组中第一个偶数
int arr[] = {1, 3, 5, 8, 7};
int i, found = 0;
for (i = 0; i < 5; i++) {
    if (arr[i] % 2 == 0) {
        found = 1;
        break;//找到后立即跳出循环
    }
}

(2)对于continue语句

while (条件) 
{
    //代码块1
    if (条件2) 
    {
        continue; //满足条件时跳过后续代码,进入下一次循环
    }
    //代码块2(continue可能跳过)
}
//循环结束后执行此处

使用 continue 语句效果
过滤无效数据:忽略某些不符合条件的迭代。

例如:
//计算数组中所有正数的和
int arr[] = {1, -2, 3, -4, 5};
int sum = 0;
for (int i = 0; i < 5; i++) 
{
    if (arr[i] <= 0) 
    {
        continue;//跳过非正数
    }
    sum += arr[i];//仅累加正数
}

简化复杂条件判断:将不满足条件的情况提前处理。

例如:
//打印1-10之间的奇数
for (int i = 1; i <= 10; i++) 
{
    if (i % 2 == 0) 
    {
        continue;//偶数直接跳过
    }
    printf("%d ", i);//只打印奇数
}

3.break与continue对比

特性breakcontinue
终止循环完全终止当前循环仅跳过当前迭代
执行后续代码立即执行循环后的代码继续下一次循环迭代
常见场景查找结果后提前退出过滤无效数据
多层循环影响仅作用于当前层仅作用于当前层

4.作用范围限制

(1)breakcontinue 仅作用于最近的一层循环,无法直接跳出多层循环,除非结合标签(如 goto 语句)或异常处理。
(2)在嵌套循环中使用时,需明确目标循环层级。

五.循环的嵌套

1.基本概念

C 语言中,循环嵌套是指在一个循环体内包含另一个完整的循环结构。这种技术常用于处理多维数据(如矩阵、表格)或需要多次迭代的复杂任务。

for、while和do while循环已经涉及过各个循环控制语句,而在这里我们将进行深入了解循环语句的相互嵌套。

2.嵌套循环的基本形式

C 语言支持三种循环( forwhiledo-while )的任意组合嵌套。
常见形式有:

// 1. for嵌套for
for (初始化1; 条件1; 更新1) 
{
    for (初始化2; 条件2; 更新2) 
    {
        //内层循环体
    }
}

// 2. while嵌套while
while (条件1) 
{
    while (条件2) 
    {
        //内层循环体
    }
}

// 3. for嵌套while
for (初始化; 条件1; 更新) 
{
    while (条件2) 
    {
        //内层循环体
    }
}

// 4. 多层嵌套(如三层)
for (...) {
    for (...) {
        for (...) {
            //最内层循环体
        }
    }
}

嵌套循环的执行流程
外层循环每执行一次,内层循环会完整执行所有迭代。
总执行次数 = 外层循环次数 × 内层循环次数。

例如
for (int i = 1; i <= 2; i++)//外层循环2次
{      
    for (int j = 1; j <= 3; j++)//内层循环3次
    {  
        printf("i=%d, j=%d\n", i, j);
    }
}

我们直接来一个典型的例子:
for 嵌套 while(打印矩形)

示例:
#include <stdio.h>

int main() 
{
    int rows = 3, cols = 4;

    for (int i = 1; i <= rows; i++)//控制行数
    {  
        int j = 1;
        while (j <= cols)//控制列数
        {             
            printf("* ");
            j++;
        }
        printf("\n");
    }
    return 0;
}

运行结果:
在这里插入图片描述

3.嵌套循环中的控制语句

在这里 breakcontinue 中起的作用与 “ forwhiledo while ” 循环 有所不同,可以亲自去编译器里试试。

break:仅跳出当前层循环

例如:
for (int i = 1; i <= 3; i++) 
{
    for (int j = 1; j <= 3; j++) 
    {
        if (j == 2) 
        break;//仅跳出内层循环
        printf("i=%d, j=%d\n", i, j);
    }
}

continue:跳过当前层的剩余代码

例如:
for (int i = 1; i <= 2; i++) 
{
    for (int j = 1; j <= 3; j++) 
    {
        if (j == 2) 
        continue;//跳过j=2的情况
        printf("i=%d, j=%d\n", i, j);
    }
}

4.注意事项

(1)性能问题:多层嵌套会显著增加时间复杂度,需谨慎使用。
(2)代码可读性:嵌套层数建议不超过 3 层,否则需重构逻辑(如封装为函数)。
(3)变量作用域:内层循环可访问外层变量,但避免同名变量导致混淆。
(4)初始化位置:内层循环的变量需在内层循环内或之前初始化。

最后作者想说的是,不经一番寒彻骨,怎得梅花扑鼻香
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值