第三章:分支与循环



C 语言中有三种结构:

  • 顺序结构
  • 选择结构
  • 循环结构

1.顺序结构

依照线性顺序从上到下依次执行

例如:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	printf("1");
	printf("2");
	printf("3");
	
	return 0;
}

2. 选择结构

通过给定的条件进行判断,当条件为真或假时分别执行不同的程序语句。

2.1 if 语句

if (表达式)
{
	语句1
}
else if (表达式)
{
	语句2
}
else
{
    语句3
}

执行流程:

当表达式成立(为真),语句执行,否则(为假)不执行。在 C 语言中,非零即为真

嵌套 if 练习:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int num = 0;
	printf("请输入一个整数:");
	int count = scanf("%d", &num);//定义变量接受 scanf 的返回值

	if (count == 1) //如果 count 为 1,scanf 接收到数据执行,否则就是格式不对没有接收到
	{
		if (num == 0)
		{
			printf("输入的数字为0");
		}
		else if (num > 0) //判断是否为正数
		{
			if (num % 2 == 0)
			{
				printf("为偶数");
			}
			else if (num % 2 == 1)
			{
				printf("为奇数");
			}
		}
		else
		{
			printf("您输入的数字为负数");
		}
	}
	else
	{
		printf("您输入的不是整数");
	}
	
	return 0;
}

悬空 else 问题:

如果有多个 ifelseelse 且没有带大括号,则 else 总是跟最接近的 if 匹配,就会导致程序运行不是我们理想的结果。

测试:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int a = 0;
	int b = 2;
	if (a == 1) //此处不加大括号,编译器会识别成 else 和第二个 if 为一对代码块,就近原则
		if (b == 2)
			printf("hehe\n");
	else
			printf("haha\n");


	return 0;
}

2.2 switch 语句

switch 是一种特殊形式的 if ... else 结构,用于判断条件有多个结果的情况。当表达式的值无法匹配 case 语句时,将匹配 default 语句。

switch (expression) 
{ 
	 case value1: 
		 语句1;
		 break;
	 case value2:
		 语句2;
		 break;
	 ... 
	 default:
		语句3;
		break;
 }
  • switch 后的 expression 必须是整形表达式
  • case 后的值,必须是整形常量表达式
  • case 和后边的数字之间必须有空格
  • case语句中的代码执行完后,需要加上 break,才能跳出这个 switch,否则会继续向下执行

输入1~5 输出工作日,6~7 输出休息日:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

//周一到周五为工作日,周六到周日为休息日,思路:不使用 break 实现 switch 的范围选择
int main()
{
	int num = 0;
	printf("请您输入1~7的数字:");
	scanf("%d", &num);

	switch (num)
	{
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
		printf("工作日");//前面介绍过,switch 不加 break 程序会一直向下执行,直到遇到 break 或者 switch 语句结束
		break;//所以可以通过此写法实现周一到周五都为休息日,不用在每个程序块都输出一句工作日
	case 6:
	case 7:
		printf("休息日");
		break;
	default: //当所有 case 选项不匹配执行
		printf("请输入合法的字符");
		break;//default 放在最后,此时的 break 可加可不加,不加走到最后依然会跳出
	}
	return 0;
}

3. 操作符

3.1 关系操作符

关系表达式:用于比较的表达式

关系操作符(关系表达式中使用的运算符):

  • >
  • <
  • >=
  • <=
  • ==
  • !=

关系表达式通常返回 01 ,表示真假。

输入年龄,在18~36 之间,输出青年:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int age = 0;
	printf("请输入你的年龄:");
	scanf("%d", &age);

	if (age >=18 && age <= 36)
	{
		printf("青年");
	}
	return 0;
}

注意:

== 是判断是否相等,= 是进行赋值

3.2 条件操作符

条件操作符需要接受三个操作数,也被称为三目操作符。

exp1 ? exp2 : exp3

当 exp1 为真,则执行 exp2,否则执行 exp3。计算后的结果是整个表达式的结果。

使用条件表达式找出两个输入数字最大值:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a,&b);

	int m = (a > b ? a : b);//第一个表达式为真,则执行第二个表达式,否则执行第三个表达式。(相当于 if else)
	//a > b ? printf("&d",a) : printf("%d",b);//第二种写法
	printf("%d", m);
	return 0;
}

3.3 逻辑操作符

  • ! :逻辑取反
  • && :逻辑与(两侧的表达式都为真,则为真,否则为假)
  • ||:逻辑或(两侧至少有一个表达式为真,则为真,否则为假)

测试:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

// !取反 ,&& 两者为真即为真 ,|| 最少一个为真即为真
int main()
{
	int flag = 0;
	scanf("%d", &flag);

	//if () 括号内内容为真时才执行后续语句
	// if (flag) 表示 (flag == true) 也就是非零
	// if (!flag) 表示 if (flag != true) 即 flag == false 也就是等于 0 时
	if (!flag)
	{
		printf("假");
	}
	return 0;
}

闰年的判断:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	int year = 0;
	printf("请输入一个年份:");
	scanf("%d", &year);

	if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
	{
		printf("闰年");
	}
	else
	{
		printf("平年");
	}
	return 0;
}

C 语言逻辑运算符有一个特点,就是先对左侧的表达式求值,再对右边的表达式求值。如果坐标的表达式满足逻辑运算符的条件,就不会再对右边的表达式求值,这种情况被称为 短路。

测试:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

// 当使用 && 运算符时,左侧表达式为 0,便没有执行后面表达式的必要
// 当使用 || 运算符时,左侧表达式为 1,便没有执行后面表达式的必要
// 当左边表达式能够确定整个表达式的结果时,便不需要再执行右边表达式。这种情况称为“短路”

int main()
{
	//试验一
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	//  0
	i = a++ && ++b && d++;//赋值运算符的优先级最低,右边整个表达式计算完再进行赋值

	printf("i = %d\na = %d\nb = %d\nc = %d\nd = %d\n",i, a, b, c, d);// 0 1 2 3 4
	printf("-------------------------------------------------------\n");

	//解析:因为赋值运算符的优先级最低,此时执行 a++ 的时候,a 需要先使用再自增
	//所以 a++ 整体代表 0,而且表达式还是 && 逻辑操作符,所以后面的表达式都没有被执行
	//直到 printf 语句 再次输出 a,此时 a 已经完成自增,所以输出的是 1

	//试验二
	int i2 = 0, a2 = 1, b2 = 2, c2 = 3, d2 = 4;

	//8 =  1    +   3    +  4
	i2 = (a2++) + (++b2) + (d2++);

	printf("i2 = %d\na2 = %d\nb2 = %d\nc2 = %d\nd2 = %d\n", i2, a2, b2, c2, d2);// 8 2 3 3 5
	printf("-------------------------------------------------------\n");

	//试验三
	int i3 = 0, a3 = 1, b3 = 2, c3 = 3, d3 = 4;
	//  1
	i3 = a3++ || ++b3 || d3++;

	printf("i3 = %d\na3 = %d\nb3 = %d\nc3 = %d\nd3 = %d\n", i3,a3, b3, c3, d3);// 1 2 2 3 4
	printf("-------------------------------------------------------\n");

	//执行 a++ 的时候,a 需要先使用再自增
	//所以 a++ 整体代表 1,而且表达式是 || 逻辑操作符,所以后面的表达式不需要被执行
	//直到 printf 语句 再次输出 a,此时 a 已经完成自增,所以输出的是 2


	//试验四
	int i4 = 0, a4 = 0, b4 = 2, c4 = 3, d4 = 4;
	//   0          3
	i4 = a4++ || ++b4 || d4++;

	printf("i4 = %d\na4 = %d\nb4 = %d\nc4 = %d\nd4 = %d\n", i4, a4, b4, c4, d4);// 1 1 3 3 4
	printf("-------------------------------------------------------\n");

	//执行 a++ 的时候,a 需要先使用再自增
	//所以 a++ 整体代表 0,表达式是 || 逻辑操作符,接着向后执行 ++b4,先自增再使用,此时 ++b4 为 3
	//已经满足一个为真的情况,此时便不需要再执行后面的表达式
	//直到 printf 语句再次输出 a,此时 a 已经完成自增,所以输出的是 1

	return 0;
}

4. 循环结构

满足指定的条件,将会一直循环执行

4.1 while 循环

while (表达式)
{
	循环语句;
}

执行流程:

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

输入一个正整数,逆序打印整数的每一位:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

// while 循环:循环次数不知道,只知道循环结束条件

int main()
{
	//输入一个正的整数,逆序打印这个整数的每一位
	int num = 0;
	printf("请输入一个整数");
	scanf("%d", &num);

	while (num)//当 num =0 时说明数字已经遍历完成,此时就不会进入循环体
	{
		printf("%d ", num % 10);// num % 10 获取数字的最后一位,例如 123 % 10 = 3
		num /= 10;//此时已经获取到最后一位,接着让数字往前进一位
	}

	return 0;
}

4.2 for 循环

for(表达式1:循环变量初始化;表达式2:循环结束条件;表达式3:循环变量调整)
{
	循环语句;
}

执行流程:

首先执行表达式 1 初始化循环变量,接着执行表达式 2 的判断部分,如果 表达式 2 的结果为假,则循环结束。否则执行循环语句,循环语句执行完后,再去执行表达式 3,调整循环变量,然后再去表达式 2 的地方进行判断,表达式的结果是否为假,决定循环是否继续。

注意:整个循环过程中,表达式 1 只被执行一次。

计算 1~100 之间3的倍数的数字之和

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

// for 循环(知道循环次数)
//for (变量初始化;判断;调整)

int main()
{
	int sum = 0;//定义一个变量记录和

	//计算1~100之间3的倍数的数字之和
	//写法一(循环一百次,判断一百次)
	//for (int i = 1; i < 101; i++)
	//{
	//	if (i % 3 == 0)//判断是否是3的倍数
	//	{
	//		sum += i;//当是3的倍数的时候相加
	//	}
	//}

	//写法二 (循环33次)
	for (int i = 3; i < 101; i+=3)//直接从3开始,循环一次调整变量+3,即每次循环就是3的倍数
	{
		sum += i;
	}

	printf("数字之和为:%d", sum);

	return 0;
}

for 循环相比 while 循环,在实现循环的过程中,初始化、判断和调整这三个部分,比 while 循环更集中,方便代码维护。

4.3 do while 循环

do
	循环语句;
while(表达式);

执行流程:

whilefor 循环都是先判断,条件满足才进入循环。而 do while 则是先进入循环体执行循环语句,然后再执行 while 的判断表达式,表达式为真,才会进行下一次,为假则结束循环,所以在 do while 中,语句至少被执行一次。

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

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	//输入一个正整数,计算这个整数是几位数,正整数不管输入几都是一位数,所以用 do while
	int num = 0;
	int count = 0;//定义变量计数
	printf("请输入一个正整数:");
	scanf("%d", &num);

	do
	{
		count++;
		num /= 10;
	} while (num);// 当num == 0 时,程序便结束

	printf("这个整数是%d位数", count);
	return 0;
}

4.4 break 和 continue

  • break:终止当前循环体
  • continue:跳过本次循环并忽略之后的代码重新循环

找出 100~200 之间的素数:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

/*
break(终止整个循环程序) continue(跳过本次循环)
break: while和for执行都一样
continue:调整变量如果在 continue 后,do while 和 while 循环中可能会出现死循环,因为 continue 会跳过之后的代码,此时变量就不会发生调整。而 for 循环的调整变量是在循环体外,所以不会受影响
*/

#include <math.h> //sqrt 开平方需要的头文件
//循环的嵌套
int main()
{
	//找出 100~200 之间的素数(只能被1和本身整除)

	for (int i = 101; i < 201; i += 2)//外层循环代表 101~201 之间的偶数,偶数不可能是质数,所以只判断奇数
	{
		int count = 0;//定义一个变量来记录当前循环的数字可以被整除的次数,每次循环即每更换一个数字重置

		//内层循环代表遍历外层所包含的数字,从2开始,到 i 开平方
		//因为如果 i = a * b,a和b是i的因子,那么a和b中至少有一个数字 <= i 开平方
		//不论是a还是b,只要在 i开平方之前的范围找到,便能找到与之对应的值
		for (int j = 2; j <= sqrt(i); j++)
		{
			if ( i % j == 0)
			{
				count++;
				break;//如果找到被整除的数字了,直接结束内层的整个循环体
			}
		}
		if (count == 0)//如果次数为0,则代表只能被1和本身整除
		{
			printf("%d ", i);
		}
	}
	return 0;
}

5. goto 语句

goto 语句可以实现在同一个函数内跳转到设置的标记处

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

// goto 语句,同一个函数跳转

int main()
{
	printf("hehe\n");
	goto next;//忽略之后代码,跳入到next开始执行

	printf("haha\n");

next:
	printf("hhhhhhh\n");
	return 0;
}

goto 语句如果使用不当,就会导致在函数内部随意乱跳转,打乱程序的执行流程,但是 goto 语句在多层循环的代码中,如果想快速跳 goto 就非常方便。

关机程序:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h> //system 函数头文件
#include <string.h>//字符串头文件

//写一个关机程序
//功能:程序运行起来后,电脑倒计时一分钟关机,如果一分钟内输入取消关机,则取消。
int main()
{
	char str[20];//定义字符数组接受用户输入的字符串

again:
	printf("请注意,您的电脑一分钟之后将关机,输入取消将会取消关机:");
	//system 函数用于执行系统命令
	system("shutdown -s -t 60");//shutdown -s 指定关机 -t 指定倒计时,单位为秒
	scanf("%s", str);

	//两个字符串在比较内容的时候,不能使用 ==,而是用 strcmp 函数
	//如果两个字符串相等,strcmp 函数会返回 0
	if (strcmp(str, "取消") == 0)
	{
		system("shutdown -a");//取消关机 
	}
	else
	{
		goto again;//如果用户没有输入取消关机,则跳转到 again 地方,继续提醒用户实现循环的效果
	}

	return 0;
}

第四章:随机数生成

声明

本文是在鹏哥 C 语言集训营学习过程中所记录的学习笔记,梳理了核心知识点,同时也记录了本人实操验证的代码案例,供后续学习复盘使用。

更多推荐