[C]基础3.分支和循环

  • 博客主页:算法歌者
  • 本篇专栏:[C]
  • 您的支持,是我的创作动力。


0、总结

在这里插入图片描述

C语言是结构化的程序语言,这里的结构指的是顺序结构、选择结构、循环结构

  • ifswitch可实现分支结构。

  • whilefordo while可实现循环结构。

1、分支

1、if语句

if语句的语法形式如下:

if (表达式)
	语句;

表达式成立(为真),则语句执行,表达式不成立(为假),则语句不执行。

注:在C语言中,0为假,非0为真。

例1:输入一个整数,判断是否为奇数?

#include <stdio.h>
int main()
{
	int num = 0;
	printf("请输入整数:");
	scanf("%d", &num);
	if (num % 2 == 1)
		printf("%d是奇数\n", num);
	return 0;
}
输入:
3
输出:
请输入整数:3
3是奇数

如果想要表达一个数是偶数,那么需要if...else...语句,语法形式如下:

if(表达式)
	语句1;
else
	语句2;

例2:输入一个整数,判断是否为奇数,如果是奇数打印是奇数,否则打印数偶数。

#include <stdio.h>
int main()
{
	int num = 0;
	printf("请输入一个整数:");
	scanf("%d", &num);
	if (num % 2 == 1)
		printf("%d是奇数\n", num);
	else
		printf("%d是偶数\n", num);
	return 0;
}
输入:
2
输出:
请输入一个整数:2
2是偶数

ifelse语句都默认只控制一条语句,如果要if和else语句同时控制多条语句,就需要使用{}将多条语句括起来。

如下:

#include <stdio.h>
int main()
{
	int age = 0;
	printf("请输入一个年龄:");
	scanf("%d", &age);
	if (age >= 18)
	{
		printf("成年了。\n");
		printf("可以独立自主了。\n");
	}
	else
	{
		printf("未成年。\n");
		printf("好好学习,天天向上。\n");
	}
	return 0;
}
输入:
23
输出:
请输入一个年龄:23
成年了。
可以独立自主了。

嵌套if语句:在if else语句中,else可以与另一个if语句连用,构成多重判断。

如下:

#include <stdio.h>
int main()
{
	int num = 0;
	scanf("%d", &num);
	if (num == 0)
		printf("输入的数字是0\n");
	// 这里的if相当于嵌套在else语句中,形成嵌套结构
	else if (num > 0)
		printf("输入的数字是正数\n");
	else
		printf("输入的数字是负数\n");
	return 0;
}
输入:
1
输出:
1
输入的数字是正数

再如:

#include <stdio.h>
int main()
{
	int num = 0;
	scanf("%d", &num);
	if (num > 0)
	{
		if (num % 2 == 0)
			printf("偶数\n");
		else
			printf("奇数\n");
	}
	else
	{
		printf("非正数\n");
	}
	return 0;
}
输入:
23
输出:
23
奇数

悬空else问题:如果有多个ifelse,可以记住一条规则,else总是跟最接近的if匹配。

#include <stdio.h>
int main()
{
	int a = 0;
	int b = 2;
	if (a == 1)
		if (b == 2)
			printf("hehe\n");
	else
		printf("haha\n");
	return 0;
}
没有输出

2、switch语句

分支结构除了if语句,还有switch语句。

switch语句:用于判断条件有多个结果的情况,是一种特殊形式的if...else结构。

语法形式如下:

switch (expression)
{
    case value1: statement;
    case value2: statement;
    default: statement;
}

上面代码中,根据表达式expression不同的值,执行相应的case分支。如果找不到对应的值,就执行default分支。

注:

1、switch后的expression必须是整型表达式。

2、case后的值,必须是整形常量表达式。

例1:输入任意一个整数值,计算除3之后的余数。

// if语句
#include <stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);
	if (n % 3 == 0)
		printf("整除,余数为0\n");
	else if (n % 3 == 1)
		printf("余数是1\n");
	else
		printf("余数是2\n");
	return 0;
}
输入:
5
输出:
5
余数是2
// switch语句
#include <stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);
	switch (n % 3)
	{
	case 0:
		printf("整除,余数为0\n");
		break;
	case 1:
		printf("余数是1\n");
		break;
	case 2:
		printf("余数是2\n");
		break;
	}
	return 0;
}
输入:
6
输出:
6
整除,余数为0

上述的代码,值得注意是:

1、case和后边的数字之间必须有空格。

2、每一个case语句中的代码执行完成后,需要加上break,才能跳出这个switch语句。

如果case语句后面没有break语句,代码就会继续执行下去,可能执行其他case语句中的代码,直至遇到break语句或者switch语句结束。

例2:输入1-5,输出“工作日”,输入6-7,输出“休息日”

#include <stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
		printf("工作日\n");
		break;
	case 6:
	case 7:
		printf("休息日\n");
		break;
	}
	return 0;
}
输入:
1
输出:
1
工作日

上面的练习,应该从实际的情况出发,灵活使用break,完成实际的需求。

在使用switch语句的时候,如果switch后的表达式中的值无法匹配代码中的case语句的时候,这时候要么不做处理,要么在switch语句中加入default子句。

例3:输入1-5,输出“工作日”,输入6-7,输出“休息日”,输入不是1-7的值,输出“输入错误”

#include <stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
		printf("工作日\n");
		break;
	case 6:
	case 7:
		printf("休息日\n");
		break;
	default:
		printf("输入错误\n");
		break;
	}
	return 0;
}
输入:
8
输出:
8
输入错误

switch语句中的casedefault的顺序问题:

switch语句中,case语句和default语句是没有顺序要求的,只要顺序是满足实际需求即可。

不过通常是把default子句放在最后处理的。

2、操作符

1、关系操作符

关系表达式:C语言用于比较的表达式。

关系运算符:关系表达式里面使用的运算符。

主要有6个:

关系运算符含义
>大于运算符
<小于运算符
>=大于等于运算符
<=小于等于运算符
==相等运算符
!=不相等运算符

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

C语言中,0表示假,所有非零值表示真。比如,20>12返回112>20返回0

关系表达式常用于ifwhile结构。

如下:

if (x == 3)
{
	printf("x is 3.\n");
}

值得注意是,相等运算符==与赋值运算符=是两个不一样的运算符。

有时候可能会写出这个代码:

if (x = 3)...

上面的示例,这个式子表示对变量x赋值3,它的返回值为3,所以if判断总是为真。

为了防止这个错误,可以这样写:

if (3 == x)...

上面的示例,如果把==误写成=,编译器就会报错。

还有另一个值得注意是,多个运算符不宜连用

i < j < k

上面的示例,虽然是合法表达式,编译器不会报错,但通常得不到想要的结果。因为实际执行是:

(i < j) < k

上面的式子,i < j返回01,所以最终是01与变量k进行比较。

正确写法是:

i < j && j < k

如果这样写:

#include <stdio.h>
int main()
{
	int age = 0;
	scanf("%d", &age);
	if (18 <= age <= 36)
		printf("青年\n");
	return 0;
}
输入:
10
输出:
10
青年

上面的示例,当输入10,输出青年。这是因为,先拿18age比较,表达式返回值为0,再拿036比较,0<=36为真,因此打印青年

为了防止这个错误,代码应该这样写:

#include <stdio.h>
int main()
{
	int age = 0;
	scanf("%d", &age);
	if (age >= 18 && age <= 36)
		printf("青年\n");
	return 0;
}
输入:
23
输出:
23
青年

2、条件操作符

条件操作符:也叫三目操作符,需要接受三个操作数。语法形式如下:

exp1 ? exp2 : exp3

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

例1:

#include <stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d", &a);
	b = a > 5 ? 3 : -3;
	printf("%d\n", b);
	return 0;
}
输入:
6
输出:
6
3

例2:使用表达式实现找两个数中较大值。

#include <stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	int m = a > b ? a : b;
	printf("%d\n", m);
	return 0;
}
输入:
2 3
输出:
2 3
3

3、逻辑操作符

逻辑运算符:提供逻辑判断功能,用于构建更复杂的表达式。

主要有三个运算符:

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

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

例1:

#include <stdio.h>
int main()
{
	int flag = 0;
	if (!flag)
		printf("hello\n");
	return 0;
}
输出:
hello

上面的代码意思是,flag为假,!flag为真,执行if语句中的代码。

&&与运算符,是一个双目操作符。

例2:3月到5月是春天。

#include <stdio.h>
int main()
{
	int month = 0;
	scanf("%d", &month);
	if (month >= 3 && month <= 5)
		printf("春季\n");
	return 0;
}
输入:
5
输出:
5
春季

这里表达的意思是,month既要大于等于3,又要小于等于5,必须同时满足。

||或运算符,也是一个双目操作符。

例3:12月或者1月或者2月是冬天。

#include <stdio.h>
int main()
{
	int month = 0;
	scanf("%d", &month);
	if (month == 12 || month == 1 || month == 2)
		printf("冬季\n");
	return 0;
}
输入:
12
输出:
12
冬季

例4:输入一个年份year,判断year是否是闰年

闰年判断的规则:

1、能被4整除并且不能被100整除是闰年

2、能被400整除是闰年

// 代码1
#include <stdio.h>
int main()
{
	int year = 0;
	scanf("%d", &year);
	if (year % 4 == 0 && year % 100 != 0)
		printf("是闰年\n");
	else if (year % 400 == 0)
		printf("是闰年\n");
	return 0;
}
输入:
2024
输出:
2024
是闰年
// 代码2
#include <stdio.h>
int main()
{
	int year = 0;
	scanf("%d", &year);
	if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
		printf("是闰年\n");
	return 0;
}
输入:
2024
输出:
2024
是闰年

值得注意是,C语言逻辑运算符有一个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是保证的。

如果左边的表达式满足逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为短路

如前面的代码:

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

表达式中&&的左操作数是month >= 3,右操作数是month <= 5,当左操作数month >= 3的结果是0的时候,右边操作数就不再执行。

再如前面的代码:

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

如果month == 12的结果是真,则不用再判断后面的操作数。

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

例5:阅读代码,计算代码输出的结果

#include <stdio.h>
int main()
{
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++ && ++b && d++;
	// i = a++ || ++b || d++;
	printf("i = %d\n", i);
	printf("a = %d\n", a);
	printf("b = %d\n", b);
	printf("c = %d\n", c);
	printf("d = %d\n", d);
	return 0;
}
输出:
i = 0
a = 1
b = 2
c = 3
d = 4

3、循环

1、while循环

C语言提供了3种循环语句,while语句就是其中一种。

while语句的语法结构和if语句非常相似:

// if和while的对比
if (表达式)
    语句;
    
while (表达式)
    语句;

例1:

// 代码1:if语句
#include <stdio.h>
int main()
{
    // if后边条件满足,打印一次hello
	if (1)
		printf("hello\n");
	return 0;
}
输出:
hello
// 代码2:while语句
#include <stdio.h>
int main()
{
    // while后边条件满足,死循环打印hello
	while (1)
		printf("hello\n");
	return 0;
}
输出:
死循环

以上是if语句和while语句的区别,从中知while语句可以实现循环效果。

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

例2:打印1-10的值

#include <stdio.h>
int main()
{
	int i = 1;
	while (i <= 10)
	{
		printf("%d ", i);
		i = i + 1;
	}
	return 0;
}
输出:
1 2 3 4 5 6 7 8 9 10

例3:

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

例如:

输入:1234,输出:4 3 2 1

输入:521,输出:1 2 5

解析:

1、要得到n的最低位,用n%10的运算,得到的余数是最低位,如:1234%10得到4。

2、要去掉n的最低位,找出倒数第二位,用n=n/10的运算,可以去掉最低位,如:n=1234/10得到123。

3、循环1和2两个步骤,在n变成0之前,能得到所有的位。

#include <stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);
	while (n)
	{
		printf("%d ", n % 10);
		n = n / 10;
	}
	return 0;
}
输入:
24
输出:
24
4 2

2、for循环

for循环是三种循环中使用最多的,语法形式如下:

for (表达式1; 表达式2; 表达式3)
    语句;
  • 表达式1:用于循环变量的初始化

  • 表达式2:用于循环结束条件的判断

  • 表达式3:用于循环变量的调整

for是如何循环的?

首先执行表达式1,进行初始化循环变量,接下来执行表达式2的判断,如果表达式2的结果为0,循环结束;如果表达式2的结果为非0,执行循环语句,执行完后,再去执行表达式3,调整循环变量,然后再执行表达式2进行判断,表达式2的结果是否为0,决定循环语句是否继续。

整个循环中,表达式1只被执行1次,剩下的表达式2循环语句表达式3在循环。

例1:

#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
		printf("%d ", i);
	return 0;
}
输出:
1 2 3 4 5 6 7 8 9 10

while循环和for循环的对比

// while循环
#include <stdio.h>
int main()
{
	// 初始化
	int i = 1;
	// 判断
	while (i <= 10)
	{
		printf("%d ", i);
		// 调整
		i = i + 1;
	}
	return 0;
}
输出:
1 2 3 4 5 6 7 8 9 10
// for循环
#include <stdio.h>
int main()
{
	int i = 0;
    // 初始化、判断、调整
	for (i = 1; i <= 10; i++)
	{
		printf("%d ", i);
	}
	return 0;
}
输出:
1 2 3 4 5 6 7 8 9 10

forwhile在实现循环的过程中,都有初始化、判断、调整这三个部分,但是for循环的三个部分非常集中,易于代码的维护。

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

#include <stdio.h>
int main()
{
	int i = 0;
	int sum = 0;
	for (i = 1; i <= 100; i++)
	{
		if (i % 3 == 0)
			sum += i;
	}
	printf("%d\n", sum);
	return 0;
}
输出:
1683

优化:省去多余的循环和判断

#include <stdio.h>
int main()
{
	int i = 0;
	int sum = 0;
	for (i = 3; i <= 100; i += 3)
		sum += i;
	printf("%d\n", sum);
	return 0;
}
输出:
1683

3、do-while循环

在循环语句中do while语句的使用最少,语法形式如下:

do
	语句;
while (表达式);

do while如何循环,以及和whilefor的区别?

whilefor这两种循环都是先判断,满足条件可进入循环语句。

do while循环是先执行循环语句,然后再判断表达式,如果表达式为真,就会执行下一次循环语句,如果表达式为假,则不再继续循环。

因此,do while语句中的循环语句是至少执行一次,这是do while循环比较特殊的地方。

例1:

#include <stdio.h>
int main()
{
	int i = 1;
	do
	{
		printf("%d ", i);
		i = i + 1;
	} while (i <= 10);
	return 0;
}
输出:
1 2 3 4 5 6 7 8 9 10

例2:

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

例如:

输入:1234 输出:4

输入:12 输出:2

#include <stdio.h>
int main()
{
	int n = 0;
	scanf("%d", &n);
	int cnt = 0;
	do
	{
		cnt++;
		n = n / 10;
	} while (n);
	printf("%d\n", cnt);
	return 0;
}
输入:
54321
输出:
54321
5

4、break和continue语句

在执行循环的过程中,如果需要提前终止循环,那么breakcontinue能解决这个问题。

  • break的作用是用于永久的终止循环,只要break执行,直接跳出循环。

  • continue的作用是跳过本次循环continue后面的代码,在for循环和while循环中有所差异。

例1:while的break举例

#include <stdio.h>
int main()
{
	int i = 1;
	while (i <= 10)
	{
		if (i == 5)
			// 当i等于5,执行break,循环终止。
			break;
		printf("%d ", i);
		i = i + 1;
	}
	return 0;
}
输出:
1 2 3 4

例2:while的continue举例

#include <stdio.h>
int main()
{
	int i = 1;
	while (i <= 10)
	{
		if (i == 5)
			// 陷入死循环
			continue;
		printf("%d ", i);
		i = i + 1;
	}
	return 0;
}
输出:
死循环

continue可以帮助我们跳过某一次循环continue后面的代码,直接到循环变量的判断,如果循环变量的调整是在continue后面的话,可能会造成死循环。

例3:for的break举例

#include <stdio.h>
int main()
{
	int i = 1;
	for (i = 1; i <= 10; i++)
	{
		if (i == 5)
			break;
		printf("%d ", i);
	}
	return 0;
}
输出:
1 2 3 4

例4:for的continue举例

#include <stdio.h>
int main()
{
	int i = 1;
	for (i = 1; i <= 10; i++)
	{
		if (i == 5)
			continue;
		printf("%d ", i);
	}
	return 0;
}
输出:
1 2 3 4 6 7 8 9 10

for循环中,continue的作用是跳过本次循环的continue后的代码,直接到循环的调整地方。

在这里能感受到while循环和for循环中的continue的区别,主要在于循环的调整地方。

例5:do while的break和continue

#include <stdio.h>
int main()
{
	int i = 1;
	do
	{
		if (i == 5)
			break;
		printf("%d ", i);
		i = i + 1;
	} while (i <= 10);
	return 0;
}
输出:
1 2 3 4
#include <stdio.h>
int main()
{
	int i = 1;
	do
	{
		if (i == 5)
			continue;
		printf("%d ", i);
		i = i + 1;
	} while (i <= 10);
	return 0;
}
输出:
死循环

do while循环中的breakcontinue的作用和while循环中几乎一模一样。

5、循环的嵌套

学完三种循环whiledo whilefor,如果把这三种循环嵌套一起,那么这种方式称之为循环嵌套

例1:

找出100~200之间的素数,并打印在屏幕上。

注:素数又称为质数,只能被1和本身整除的数字。

解析:

1、先有100~200之间的数,用循环解决,循环变量为i

2、先判断i是否为素数,需要在2`i-1`之间的数字去试除,需要产生`2`i-1之间的数字,用循环解决。

3、如果2~i-1之间有数字能整除i,则i不是素数,如果都不能整除,则i是素数。

#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 100; i <= 200; i++)
	{
		int j = 0;
		int flag = 1;
		for (j = 2; j < i; j++)
		{
			if (i % j == 0)
			{
				flag = 0;
				break;
			}
		}
		if (flag == 1)
			printf("%d ", i);
	}
	return 0;
}
输出:
101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199

6、goto语句

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

例1:

#include <stdio.h>
int main()
{
	printf("hello\n");
	goto next;
	printf("haha\n");

next:
	printf("跳过haha的打印\n");
	return 0;
}
输出:
hello
跳过haha的打印

goto语句如果使用不当,就会导致函数内随意跳转,打乱程序的执行流程,goto语句一般用于在多层循环的代码中,目的是快速跳出多层循环。如下:

	for (...)
	{
		for (...)
		{
			for (...)
			{
				if (...)
					goto error;
			}
		}
	}
error:
	//...

for循环想提前退出使用break,但一个break只能跳出一层for循环,如果3层循环嵌套就得使用3个break才能跳出循环,所以在这种情况下使用goto语句就会更加便携。


完。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值