C讲坛之分支与循环语句

大家好,今天带大家认识C语言中的循环与分支语句
(编译环境:VS2019)


——————————————————————————

一. 前言:什么是语句?

C语句可分为以下五类:

  1. 表达式语句
  2. 函数调用语句
  3. 控制语句
  4. 复合语句
  5. 空语句

博主这次将根大家分享的是我们的控制语句
控制语句用于控制程序的执行流程,以实现程序的各种结构方式,它们由特定的语句定义符组成,C语言有九种控制语句。
可分成以下三类:

  1. 条件判断语句也叫分支语句:if语句、switch语句;
  2. 循环执行语句:do while语句、while语句、for语句;
  3. 转向语句:break语句、goto语句、continue语句、return语句。

二.分支语句(选择结构)

2.1 if语句

if语句的结构

1.if(表达式)
      语句;
2.if(表达式)
      语句1;
  else
      语句2;
3.//多分支
  if(表达式1)
      语句1else if(表达式2) //也可以直接if
      语句2;
  else
      语句3;    

举例

//代码1
#include <stdio.h>
int main()
{
 int age = 0;
    scanf("%d", &age);
    if(age<18)
   {
        printf("未成年\n");
        //单分支语句可以省略{}
   }
}
//代码2
#include <stdio.h>
int main()
{
 int age = 0;
    scanf("%d", &age);
    if(age<18)
   {
        printf("未成年\n");
   }
    else
   {
        printf("成年\n");
   }
}
//代码3 多分支if语句
#include <stdio.h>
int main()
{
    int age = 0;
    scanf("%d", &age);
    if(age<=18)
   {
        printf("少年\n");
   }
    else if(age>=18 && age<30)
   {
        printf("青年\n");
   }
    else if(age>=30 && age<50)
   {
        printf("中年\n");
   }
    else if(age>=50 && age<80)
    {
        printf("老年\n");
    }
    else if(age>=80 && age<100)
    {
        printf("老寿星\n");
    }
    else if(age>=100)
    {
        printf("仙人\n");
    }        

当条件成立,需要执行多条语句时,需要将这些语句放在代码块里
(一个{}就是一个代码块)

2.1.1 悬空else

我们来看一下这个代码的运行结果会是什么呢?

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

可能你会这么想:判断第一个if语句中的表达式为假,所以不会进入第二个if语句直接跳到else语句中打印haha。即最终的运行结果会在屏幕上打印haha。

但实际的运行却是
在这里插入图片描述
什么都没有

这是因为else的匹配符合一个原则:else语句是和它离的最近的if匹配的 所以在判断第一个if语句中的表达式为假后,直接return 0;因此什么也没有打印

更改后

#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.2 switch语句

switch语句也是一种分支语句。
常常用于多分支的情况。
如果我们想打印
输入1,输出星期一
输入2,输出星期二
输入3,输出星期三
输入4,输出星期四
输入5,输出星期五
输入6,输出星期六
输入7,输出星期日
而使用if…else if…else if…else…的形式会非常复杂麻烦。
这个时候我们就可以使用switch语句。

#include <stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:printf("今天是星期一\n"); break;
	case 2:printf("今天是星期二\n"); break;
	case 3:printf("今天是星期三\n"); break;
	case 4:printf("今天是星期四\n"); break;
	case 5:printf("今天是星期五\n"); break;
	case 6:printf("今天是星期六\n"); break;
	case 7:printf("今天是星期日\n"); break;
	}
	return 0;
}

结合上面的例子我们可以更好理解switch语句的语法形式。

switch(整型表达式)
{
      语句项;
}

而语句项又是什么呢?

//是一些case语句:
//如下:
case 整形常量表达式:
    语句;

而整形常量表达式又是啥子嘞?

整形常量表达式指的是表达式中的操作数都是整数类型的, 这里的整数类型不仅仅是int类型, 还包括char, (unsigned) short, (unsigned) long等类型. 整型常量表达式中的操作数在编译时就已经确定了他的值。

因此只需要关注哪些值在编译时确定就可以了. 这包括以下几种情况:

  1. 单个字符, 比如’A’, ‘a’
  2. 单个整数数字以及由整数数字构成的表达式, 如123, 123 + 345
  3. 枚举常量
  4. 有sizeof 运算法返回的值, 如sizeof(int)
  5. NULL指针值
  6. 地址常量. 如0X12345678, 以及地址常量加上一个偏移
2.2.1 switch语句中的break

在switch语句中,我们没办法直接实现分支,搭配break使用才能实现真正的分支。
以刚刚输出星期几的代码举例:

#include <stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:printf("今天是星期一\n"); 
	case 2:printf("今天是星期二\n"); 
	case 3:printf("今天是星期三\n"); 
	case 4:printf("今天是星期四\n"); 
	case 5:printf("今天是星期五\n"); 
	case 6:printf("今天是星期六\n"); 
	case 7:printf("今天是星期日\n"); 
	}
	return 0;
}

在这里插入图片描述
没有break语句后,输入1后输出的结果是星期一到星期日,与我们期望的星期一并不相同,这就是break语句的作用。
break语句的实际效果是把语句列表划分为不同的分支部分
在完成对应分支后遇到break才会停止

2.2.2 default子句

当我们输入的值与所有的case标签的值都不匹配怎么办?

其实也没什么,结果就是所有的语句都被跳过而已。
程序并不会终止,也不会报错,因为这种情况在C语言中并不认为是个错误。但是,如果你并不想忽略不匹配所有标签的表达式的值时该怎么办呢?
你可以在语句列表中增加一条default子句,把下面的标签 default: 写在任何一个 case 标签可以出现的位置。 当 switch
表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。
所以,每个switch语句中只能出现一条default子句。
但是它可以出现在语句列表的任何位置,而且语句流会像执行一个case标签一样执行default子句。

#include <stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:printf("今天是星期一\n"); break;
	case 2:printf("今天是星期二\n"); break;
	case 3:printf("今天是星期三\n"); break;
	case 4:printf("今天是星期四\n"); break;
	case 5:printf("今天是星期五\n"); break;
	case 6:printf("今天是星期六\n"); break;
	case 7:printf("今天是星期日\n"); break;
	default:printf("输出错误,请重新输入\n");break;
	}
	return 0;
}

这次当我们输入一个与case标签的值都不匹配的值时
屏幕上就会打印“输出错误,请重新输入”
可能这个时候有人会想default子句后面的break有必要吗?
正如上面所说,default子句是可以出现在语句列表的任何位置的。
那当我们去掉default后面的break并把它放在第一排。
在这里插入图片描述
我们发现在输入一个不匹配的值后,直到完成打印“今天是星期一”后才结束

总结:也就是说如果我们把default子句放在语句项的最后一行,是可以省略break的,但是如果想把default子句放在其他位置,要注意在后面加上break,避免出现错误。

2.2.3 小练习
#include <stdio.h>
int main()
{
	int n = 1;
    int m = 2;
    switch (n)
    {
    case 1:
        m++;
    case 2:
        n++;
    case 3:
        switch (n)
        {//switch允许嵌套使用
        case 1:
            n++;
        case 2:
            m++;
            n++;
            break;
        }
    case 4:
        m++;
        break;
    default:
        break;
    }
    printf("m = %d, n = %d\n", m, n);
    return 0;
}

n=1 m=2—>进入switch语句 n=1 执行case 1—>m=3 无break 执行case 2—>n=2 m=3 没有break进入case 3—>执行case 2 m=4 n=3 break跳出第二个switch语句 无break—>执行case 4 m=5 n=3 遇到break 跳出打印结果。

即最后结果为m=5 n=3

三.循环语句

3.1 while循环

我们已经了解了if语句,当条件满足的情况下,if语句后的语句执行,否则不执行。 但是这个语句只会执行一次。
由于我们发现生活中很多的实际的例子是:同一件事情我们需要完成很多次。 那我们怎么做呢? C语言中给我们引入了: while 语句,可以实现循环。

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

注意:在while语句中进入循环条件的次数要比进入循环体多一次)

举例:在屏幕上打印1~10 的数字

#include <stdio.h>
int main()
{
 int i = 1;
 while(i<=10)
 {
 printf("%d ", i);
 i = i+1;
 }
 return 0;
}

由上面的代码我们可以得到while语句的基本语法

while(表达式)
      语句;
其中表达式是循环条件,语句为循环体。
3.1.2 while语句中break和continue的作用
#include <stdio.h>
int main()
{
 int i = 1;
 while(i<=10)
 {
 if(i == 5)
 break;
 printf("%d ", i);
 i = i+1;
 }
 return 0;
}

在这里插入图片描述
我们可以看到 当i=5时直接跳出循环
总结:
break在while循环中的作用:
在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。
所以:while中的break是用于永久终止循环的

接下来我们将break换成continue
continue示例1
在这里插入图片描述

可以看到最后的结果是1 2 3 4 但仍没有结束进程变成了死循环

当i=5时,遇到continue语句直接跳过了余下为执行的语句,又返回进行下一次循环条件判定,由于此时i仍等于5又满足了if语句的条件判定,再次遇见continue语句进入死循环。

continue示例2

#include <stdio.h>
int main()
{
    int i = 1;
    while (i <= 10)
    {
        i = i + 1;
        if (i == 5)
            continue;
        printf("%d ", i);
    }
    return 0;
}

在这里插入图片描述

观察示例2的结果,当i=5时,跳过余下尚未执行的语句,又重新进入循环判定条件,从6开始打印到10。

总结:
continue语句的作用是跳过本次循环体中余下尚未执行的语句,立即进行下一次的循环条件判定,可以理解为仅结束本次循环。
注意:continue语句并没有使整个循环终止。

3.2 for循环

for(表达式1; 表达式2; 表达式3)
    循环语句;

表达式1为初始化部分,用于初始化循环变量的。
表达式2为条件判断部分,用于判断循环时候终止。
表达式3为调整部分,用于循环条件的调整。
示例

//在屏幕上打印1~10
#include <stdio.h>
int main()
{
 int i = 0;
 //for(i=1/*初始化*/; i<=10/*判断部分*/; i++/*调整部分*/)
 for(i=1; i<=10; i++)
 {
 printf("%d ", i);
 }
 return 0;
}

for语句的循环流程图:
在这里插入图片描述
我们来对比一下实现相同的功能,while循环和for循环的差距。

#include <stdio.h>
int main()
{
    int i = 1;
   //初始化部分
  while(i<=10)//判断部分
  {
   printf("%d ",i);
   i = i+1;//调整部分
  }
  printf("\n");
  //实现相同的功能,for
  for(i=1; i<=10; i++)
  {
  printf("%d",i);
  }
}

可以发现在实现某些功能时,while循环中依然存在循环的三个必须条件,但显然使用for语句更加简洁,修改和查找也更加方便,这也是为什么for循环是循环中使用频率最高的原因。

3.2.1 for循环中的break和continue作用

我们发现在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。
但是还是有些差异:

//代码1
#include <stdio.h>
int main()
{
 int i = 0;
 for(i=1; i<=10; i++)
 {
 if(i == 5)
 break;
 printf("%d ",i);
 }
 return 0;
}
//代码2
#include <stdio.h>
int main()
{
 int i = 0;
 for(i=1; i<=10; i++)
 {
 if(i == 5)
 continue;
 printf("%d ",i);
 }
 return 0;
}

建议:

  1. 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
  2. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
int i = 0;
//前闭后开的写法
for(i=0; i<10; i++)
{}
//两边都是闭区间
for(i=0; i<=9; i++)
{}
3.2.2 for循环的一些变种
#include <stdio.h>
int main()
{
 //代码1
 for(;;)
 {
 printf("hehe\n");
 }
    //for循环中的初始化部分,判断部分,调整部分是可以省略的,但是不建议初学时省略,容易导致问题。中间的判断部分如果省略,意味着判断恒为真,就构成了死循环。
//代码2
    int i = 0;
    int j = 0;
    int count=0;
    //这里打印多少个hehe?
    for(i=0; i<10; i++)
   {
        for(j=0; j<10; j++)
       {
         printf("hehe\n");
       }
       printf("一共打印%d次",count);//用count检验打印次数
   }
   

运行后在屏幕上打印了100行hehe,count=100,所以在进入第一个for循环后里面嵌套的for循环作为第一个for循环的循环体,因此一共打印了100次。

  //代码3
  	int i = 0;
	int j = 0;
	int count = 0;
	//如果省略掉初始化部分,这里打印多少个hehe?
	for (; i < 10; i++)
	{
		for (; j < 10; j++)
		{
			printf("hehe\n");
			count++;
		}
	}
	printf("打印的次数为%d", count);

在这里插入图片描述

3.3 do…while循环

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

do…while的循环流程图
在这里插入图片描述
do…while循环的特点:循环至少执行一次
示例

#include <stdio.h>
int main()
{
 int i = 10;
 do
 {
 printf("%d\n", i);
 }while(i<10);
 return 0;
}
3.3.1 do…while循环中的break和continue
#include <stdio.h>
int main()
{
 int i = 10;
    
 do
 {
        if(5 == i)
            break;
 printf("%d\n", i);
 }while(i<10);
    
 return 0;
}
#include <stdio.h>
int main()
{
 int i = 10;
    
 do
 {
        if(5 == i)
            continue;
 printf("%d\n", i);
 }while(i<10);
    
 return 0;
}

3.4 goto语句

C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。
从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。
但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。
例如:一次跳出两层或多层循环。
多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。
goto语言真正适合的场景如下:

for(...)
    for(...)
   {
        for(...)
       {
            if(disaster)
                goto error;
       }
   }
    …
error:
 if(disaster)
         // 处理错误情况

四.练习

1.判断一个数是否为奇数

#include <stdio.h>
int main()
{
	int n = 0;
	printf("请输入:>");
	scanf("%d", &n);
	if (n % 2 == 1)

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

2.输出1~100之间的奇数

//输出1~100之间的奇数
#include <stdio.h>

int main()
{
	int i = 0;
	for (i = 1; i <= 100; i++)
	{
		if (i % 2 == 1)
		{
			printf("%d ", i);
		}
	}
	return 0;
}

3.输入两个整数及运算符,进行运算后输出运算结果

//输入两个整数及运算符,进行运算后输出运算结果
#include <stdio.h>
int main()
{
	int a = 0;
	int b = 0;
	char c = 0;
	scanf("%d%c%d", &a, &c, &b);
	switch (c)
	{
	case '+':printf("%d\n", a + b); break;
	case '-':printf("%d\n", a - b); break;
	case '*':printf("%d\n", a * b); break;
	case '/':
		if (b == 0)
			printf("除数不能为0");
		else
			printf("%f", a * 1.0 / b);
		break;
	case '%':printf("%d\n", a % b); break;
	default:printf("输出错误\n"); break;
	}
	return 0;
}

4.计算n的阶乘

#include <stdio.h>
int main()
{
	int n = 0;
	int i = 0;
	int ret = 1;//创造一个变量产生累计的效果
	scanf("%d", &n);
	for (i = 1; i <= n; i++)
	{
			ret = ret * i;
	}
	printf("%d\n",ret);
	return 0;
}

5. 计算 1!+2!+3!+……+10!

//求阶乘之和
#include <stdio.h>
int main()
{
	int n = 0;
	int i = 0;
	int ret = 1;//创造一个变量产生累计的效果
	int sum = 0;
	for (n = 1; n <= 10; n++)
	{
		ret = 1;
		for (i = 1; i <= n; i++)
		{
			ret = ret * i;
		}
		sum += ret;
	}
	printf("%d\n", sum);
	return 0;
}

6.编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则提示登录成功,如果三次均输入错误,则退出程序。)

#include <stdio.h>
#include <string.h>
int main()
{
	int i = 0;
	char password[20] = "";
	//假设密码是123456
	for (i = 0; i < 3; i++)
	{
		printf("请输入密码:>");
		scanf("%s", password);//password是数组名不需要取地址
		if (strcmp(password, "123456") == 0)//比较2个字符串是否相等不能==,要使用函数strcmp
		{
			printf("登录成功\n");
			break;
		}
		else
		{
			printf("密码错误\n");
		}
	}
	if (i == 3)
	{
		printf("密码错误超过三次,登录失败\n");
	}
	return 0;
}

  • 44
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白要努力变强.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值