【C语言初阶(四)】分支和循环语句

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C语言学习分享⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习更多C语言知识

🔝🔝



分支和循环语句

  • [1. 前言](#1. 前言 "#1__15")
  • [2. 什么是语句?](#2. 什么是语句? "#2__21")
  • [3. 分支语句(选择结构)](#3. 分支语句(选择结构) "#3__41")
    • [3.1 if语句](#3.1 if语句 "#31_if_49")
      • [3.11 代码块{}的作用](#3.11 代码块{}的作用 "#311__153")
      • [3.12 悬空else](#3.12 悬空else "#312_else_178")
      • [3.13 练习](#3.13 练习 "#313__198")
    • [3.2 switch语句](#3.2 switch语句 "#32_switch_236")
      • [3.21 在switch语句中的 break](#3.21 在switch语句中的 break "#321_switch_break_293")
      • [3.22 switch语句中的default子句](#3.22 switch语句中的default子句 "#322_switchdefault_358")
      • [3.23 练习](#3.23 练习 "#323__371")
  • [4. 循环语句](#4. 循环语句 "#4__410")
    • [4.1 while循环](#4.1 while循环 "#41_while_417")
      • [4.11 while循环中的break](#4.11 while循环中的break "#411_whilebreak_437")
      • [4.12 while循环中的continue](#4.12 while循环中的continue "#412_whilecontinue_473")
    • [4.2 for循环](#4.2 for循环 "#42_for_532")
      • [4.21 for循环中的break](#4.21 for循环中的break "#421_forbreak_582")
      • [4.22 for循环中的continue](#4.22 for循环中的continue "#422_forcontinue_605")
      • [4.23 for语句的循环控制变量](#4.23 for语句的循环控制变量 "#423_for_626")
      • [4.24 一些for循环的变种](#4.24 一些for循环的变种 "#424_for_646")
    • [4.3 do...while语句](#4.3 do...while语句 "#43_dowhile_713")
      • [4.31 do while循环中的break和continue](#4.31 do while循环中的break和continue "#431_do_whilebreakcontinue_720")
  • [5. goto语句](#5. goto语句 "#5_goto_764")
  • [6. 练习](#6. 练习 "#6__816")
  • [7. 总结](#7. 总结 "#7__826")

1. 前言

从本章开始我们就要进入C语言的正式学习了,前面的章节我们分享了C语言中大概包含哪一些知识,现在我们来一章一章的深入探讨这些知识.本章分享的是分支和循环 ,分为:1.分支语句: if 和 switch语句,2.循环语句: for, while 和 do...while. 3. goto语句.




2. 什么是语句?

C语句可分为以下五类:

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

本章后面介绍的是控制语句。

控制语句用于控制程序的执行流程,以实现程序的各种结构方式(C语言支持三种结构:顺序结构、选

择结构、循环结构),它们由特定的语句定义符组成,C语言有九种控制语句。

可分成以下三类:

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



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

如果你好好学习,校招时拿一个好offer,走上人生巅峰。

如果你不学习,毕业等于失业,回家卖红薯。

这就是选择!



3.1 if语句

那if语句的语法结构是怎么样的呢?

第一种:

if(表达式)

语句;
这一种表示若if中表达式为真就执行下面语句,否则就跳过下面的语句
第二种:

if(表达式)

语句1;

else

语句2;
这一种表示如果if中表达式为真就执行语句1,否则就执行语句2;
第三种:

//多分支

if(表达式1)

... 语句1;

else if(表达式2)

... 语句2;

else

... 语句3;
这一种表示若表达式1为真就执行语句1,表达式2为真就执行语句2,表达式1.2都为假就执行语句3

比如:

c 复制代码
#include <stdio.h>
//代码1
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
#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
   {
        printf("老寿星\n");
   }
    
}

注意这个地方当我们想要表达age大于18但是age小于30的时候不能这么写:

c 复制代码
#include<stdio.h>
int main()
{
	int age;
	scanf("%d", &age);
	if (18 < age < 30) {
		printf("青年");
	}
   return 0;
}

假如我们输入age为40.这个地方代码将这样执行:先判断age是不是大于18,这里age大于18,所以为真,18<age这个整体的值就变成了1,再判断1是不是小于30,这个地方1小于30所以整个式子返回1,为真,但是事实上40岁并不是青年.所以我们一定不要用错了,这个地方要使用&&或者||符号来表示


3.11 代码块{}的作用

在上面的代码中我们可以发现 if 和 else 语句后面都加上了{}, 这是因为当我们不加上{}时,if 或者 else 语句只包含下面一条语句 ,比如:

c 复制代码
#include<stdio.h>
int main()
{
	int age;
	scanf("%d", &age);
	if (18 < age) 
		printf("青年\n");
	    printf("可以谈恋爱\n");
    
		if (age > 18)
		{
			printf("青年\n");
			printf("可以谈恋爱");
	    }
   return 0;
}

我们可以亲自去试一试.这个地方两个if语句是不一样的,上面的 if 语句没有{},所以只包含"青年",所以当我们输入的age小于18时也会打印"可以谈恋爱",所以当我们想要一条 if 或者 else 语句执行多条语句时.一定要记得用{}.

3.12 悬空else

我们说C语言的else总是与距离它最近且没有else匹配的if相匹配.当我们写出了下面代码:

c 复制代码
#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语句单只有一个else语句.这个地方很多人会出错,会认为程序打印的是"haha",我们理所当然的认为当a!=1时,执行else语句打印"haha",可能是因为我们看见else与第一个if是"对齐"的,但是事实并不是这样,else这里与第二个if相匹配,就像我们之前说的:C语言中的else总是与距离它最近且没有else匹配的if相匹配.所以这个地方什么都不打印.


3.13 练习

  1. 判断一个数是否为奇数
  2. 打印1到100之间的奇数
c 复制代码
#include <stdio.h>
int main()//判断一个数是不是奇数
{
	int n = 0;
	//输入
	scanf("%d", &n);
	if (n % 2 == 1)
	{
		printf("是奇数\n");
	}
	else
	{
		printf("不是奇数\n");
	}
	return 0;
}


int main()//打印1到100之间的奇数
{
	int i = 1;
	while (i <= 100)
	{
		//判断i是奇数的话,就打印i
		if(i % 2 == 1)
			printf("%d ", i);
		++i;
	}
	return 0;
}


3.2 switch语句

switch语句也是一种分支语句。

常常用于多分支的情况

比如我们想:

输入1,输出星期一

输入2,输出星期二

输入3,输出星期三

输入4,输出星期四

输入5,输出星期五

输入6,输出星期六

输入7,输出星期日

这个地方如果用 if 和 else 语句会显得很麻烦.这个时候我们就可以用switch语句来实现它.我们先来看看switch语句是如何实现的:


这里的语句项是一些 case 语句如下:

当我们switch括号中的整型表达式等于某个case后面的整型常量表达式的时候,就从这一个case执行命令

c 复制代码
#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;
}

假如这个地方我输入day为5,它就从case5开始执行命令,它就会打印"星期五","星期六",星期天",但是我只想这个地方打印一个天数,那就得使用到我们的break了;


3.21 在switch语句中的 break

就像我们之前说的一样,如果我们的switch语句中没有break,那它就会从一个case进去,一直执行下面所有case的语句.但是如果我们在每一个case语句最后加上一个break,那就只执行我们一个case中的语句了:

c 复制代码
#include <stdio.h>
int main()
{
    int day = 0;
    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语句来贴合我们的要求,比如:

有时候我们的需求变了:

  1. 输入1-5,输出的是"weekday";
  2. 输入6-7,输出"weekend"
    这个时候就不能一味的按照原先的思路了,应该修改代码:
c 复制代码
#include <stdio.h>
//switch代码演示
int main()
{
    int day = 0;
    switch(day)
   {
        case 1://空语句,什么都不执行直接跳到下一个case
        case 2:
        case 3:
        case 4:
        case 5:
            printf("weekday\n");//只要输入的数在1到5,就会跳到case5来打印weekday
            break;
        case 6:
        case 7:
            printf("weekend\n");
            break;
   }
    return 0;
}

3.22 switch语句中的default子句

如果表达的值与所有的case标签的值都不匹配怎么办?

其实也没什么,结果就是所有的语句都被跳过而已。

程序并不会终止,也不会报错,因为这种情况在C中并不认为是个错误。

但是,如果你并不想忽略不匹配所有标签的表达式的值时该怎么办呢?

你可以在语句列表中增加一条default子句,把下面的标签

default:

写在任何一个 case 标签可以出现的位置。
当 switch 表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。
所以,每个switch语句中只能出现一条default子句。
但是它可以出现在语句列表的任何位置,而且语句流会像执行一个case标签一样执行default子句


3.23 练习

看看下面代码将会输出什么结果?

c 复制代码
#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;//这个break跳出的是内层switch
		}
	case 4:
		m++;
		break;
	default://当所有条件都不符合,就跳出switch语句
		break;
	}
	printf("m = %d, n = %d\n", m, n);
	return 0;
}



4. 循环语句

当我们学的还不够好时,我们就反复学,当我们学有所成的时候我们就去公司应聘,这也是一个循环,跳出循环的条件是你已经学有所成:

我们一直在老实学习的循环中,直到我们学有所成或者买彩票中了500万后才能跳出这种循环.



4.1 while循环

先来看看while循环的语法:

当while后面的表达式为真,那么程序就会进入到我们的while循环中执行语句,当执行完一次语句后,又跳到while(表达式)判断表达式是不是为真,为真又进入while循环中执行语句.这个地方比如我们想打印1-10的数字:

c 复制代码
#include <stdio.h>
int main()
{
 int i = 1;
 while(i<=10)//打印到10时,这时的i=11;11<=10不成立就跳出while循环了
 {
 printf("%d ", i);
 i = i+1;
 }
 return 0;
}

4.11 while循环中的break

break介绍:

c 复制代码
//break 代码实例
#include <stdio.h>
int main()
{
 int i = 1;
 while(i<=10)
 {
   if(i == 5)//当i等于时,我们会直接跳出while循环
    {
      break;
    }
   printf("%d ", i);
   i = i+1;
 }
 return 0;
}

这里代码输出的结果是什么?

1 2 3 4

1 2 3 4 5

1 2 3 4 5 6 7 8 9 10

1 2 3 4 6 7 8 9 10

答案是只打印:1 2 3 4

因为当i=5时我们直接跳出了整个while循环
总结:
break在while循环中的作用:
其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。
所以:while中的break是用于永久终止循环的。



4.12 while循环中的continue

continue介绍:

c 复制代码
//continue 代码实例1
#include <stdio.h>
int main()
{
 int i = 1;
 while(i<=10)
 {
   if(i == 5)//当i等于5时,自动跳过本次循环下面的所有内容,注意不是跳过整个while循环
    {
      continue;
    }
   printf("%d ", i);
   i = i+1;
 }
 return 0;
}

这里代码输出的结果是什么?

1 2 3 4

1 2 3 4 5

1 2 3 4 5 6 7 8 9 10

1 2 3 4 6 7 8 9 10

答案也是打印1 2 3 4;

因为当i=5后,下面的printf语句和i=i+1的语句是不执行的,直接来到while的判断部分

这时我们的i是不变的,还是5,所以它又会跳过下面的语句一直这样死循环.


再来看一段代码:

c 复制代码
//continue 代码实例2
#include <stdio.h>
int main()
{
 int i = 1;
 while(i<=10)
 {
    i = i+1;//把i=i+1放在前面来了
    if(i == 5)
    {
      continue;
    }
    printf("%d ", i);
 }
 return 0;
}

这个地方会打印2 3 4 6 7 8 9 10 11
总结:
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,
而是直接跳转到while语句的判断部分。进行下一次循环的入口判断



4.2 for循环

先来看看for循环的语法:

1.表达式1:

表达式1为初始化部分,用于初始化循环变量的。
2.表达式2

表达式2为条件判断部分,用于判断循环时候终止。
3.表达式3

表达式3为调整部分,用于循环条件的调整。

我们先用代码来理解一下for循环里的表达式:

c 复制代码
#include <stdio.h>//打印1-10的数字
int main()
{
 int i = 0;
 //for(i=1/*初始化*/; i<=10/*判断部分*/; i++/*调整部分*/)
 for(i=1; i<=10; i++)
 {
 printf("%d ", i);
 }
 return 0;
}

我们再来对比一下while和for实现相同的功能:

c 复制代码
int i = 0;
//实现相同的功能,使用while
i=1;//初始化部分
while(i<=10)//判断部分
{
 printf("hehe\n");
 i = i+1;//调整部分
}
//实现相同的功能,使用for
for(i=1; i<=10; i++)
{
 printf("hehe\n");
}

可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较

远,这样

查找修改就不够集中和方便。所以,for循环的风格更胜一筹;for循环使用的频率也最高

4.21 for循环中的break

我们发现在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。

但是还是有些差异:

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

这个代码很好理解,就是当i等于5时直接跳出for循环,这里的break和while中的比较相似;


4.22 for循环中的continue

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

for循环中的continue和while中有一点区别,while中的判断是否为真为假的 i 变量的变化语句如果在continue之后,那么我们continue之后i的值就不会变了.但是for循环不一样,不管continue在for循环的什么位置,都不会影响我们i的变化.

4.23 for语句的循环控制变量

建议:

  1. 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
  2. 建议for语句的循环控制变量的取值采用"前闭后开区间"写法。

值得注意的是,我们有时候会看见这种写法:

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

它在for循环之前没有定义 i 变量,而是在for循环括号内定义 i 变量,这种写法是在C99标准中引入的,它的功能和在for循环外面定义 i 是一样的,两种写法都是可以的.


4.24 一些for循环的变种

我们用代码的形式来阐述:

c 复制代码
#include <stdio.h>
int main()
{
 //代码1
 for(;;)
 {
 printf("hehe\n");
 }
    //for循环中的初始化部分,判断部分,调整部分是可以省略的,但是不建议初学时省略,容易导致问题

for循环的初始化部分,判断部分,调整部分都是可以省略的(你可以一次只省略一个,也可以一次性都省略),值得注意的一点是:当我们的判断部分被省略后,那程序会默认我们的判断恒为真.


再来看看:

c 复制代码
//代码2
    int i = 0;
    int j = 0;
    //这里打印多少个hehe?
    for(i=0; i<10; i++)
   {
        for(j=0; j<10; j++)
       {
          printf("hehe\n");
       }
   }

这里for循环内部嵌套了一个for循环,相当于我们当 i 等于0时,进入内部循环会打印10个"hehe",当 i 等于1进入内部循环也是如此,所以这个地方一共会打印10*10=100个"hehe"


再来看看:

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

很多同学在第一次看这个代码的时候会出错,事实上我们这个地方只会打印10个"hehe"这是因为我们的 i 和 j这个地方是没有初始化的,当我们 i 等于0进入内层循环时,第一次进入内层循环会很好的打印10个"hehe"当 j 等于10时就停止打印程序再次回到外层循环判断,这时 i 等于1又一次进入内层循环,但是这个时候我们的 j 是没有初始化的,所以它的值还是保持在上一次循环,为10,所以这个地方不会进入内层循环!


再看看看:

c 复制代码
//代码4-使用多余一个变量控制循环
 int x, y;
    for (x = 0, y = 0; x<2 && y<5; ++x, y++)
   {
        printf("hehe\n");
   }
 return 0;
}

这里只会打印两个"hehe",也比较好理解.



4.3 do...while语句

先来看看语法结构:

其实从这个地方我们也能猜出,do...while循环是先执行语句再进行判断.它和while语句的区别就是 do...while至少执行一次循环内的语句,而我们的while有可能一次都不进行.


4.31 do while循环中的break和continue

我们用代码来阐述:

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

和while循环中是一样的效果.


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

break和continue都和while循环中的效果一样.




5. goto语句

C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。
从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。

但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。

例如:一次跳出两层或多层循环。
多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。

我们还是用代码的形式来举例:

c 复制代码
for(...)
    for(...)
   {
        for(...)
       {
            if(disaster==0)
                goto error;//当我们disaster等于0时,我们想跳出所有的for循环
       }                   //这里用break只能跳出一个for循环,所以我们用goto,
   }                       //直接跳到error的地方去就比较方便
    ...
 error: //这个error是自己创建的名字,可以自己修改,只要goto后面的变量名与你创建的相同就能实现相同的功能
.....

这里我们用goto语句实现一个自动关机的代码:注意!运行这个代码真的会关机!

c 复制代码
#include <stdio.h>
int main()
{
    char input[10] = {0};
    system("shutdown -s -t 60");//指系统会在60秒后关机
 again:
    printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
    scanf("%s", input);
    if(0 == strcmp(input, "我是猪"))//strcmp是判断字符串是否相同的函数
   {
        system("shutdown -a");//指令的意思是取消关机
   }
    else
   {
        goto again;
   }
    return 0;
}

如果你运行了此代码并且在1分钟之内不输入"我是猪"的话,电脑是会自动关机的这里关于shutdown命令的拓展由兴趣的朋友可以跳转:shutdown指令




6. 练习

有兴趣练练手的朋友可以尝试做一下下面的题(这里不放答案了,网上都能搜到)

练习

  1. 计算 n的阶乘。
  2. 计算 1!+2!+3!+......+10!
  3. 在一个有序数组中查找具体的某个数字n。(二分查找)


7. 总结

这里还要补充一点:switch语句中是没有continue这种用法的.这里关于我们分支和循环语句的详细知识已经讲解完了,一些更细节的地方我会在分享<<c和指针>>这本书的第四章给大家列出来.这里有什么写的不对的地方还请大家在评论区指出!

下节预告:函数

相关推荐
2035去旅行3 小时前
bootcmd 详细讲解
linux·嵌入式·arm·soc
陈希1234 小时前
Linux 防火墙配置实战:firewalld、iptables 与云安全组
linux·运维·服务器
女神下凡4 小时前
芯参谋(95):嵌入式文件系统_开发指南
linux·服务器·arm开发·驱动开发·设计规范
且从容.8 小时前
Ubuntu安装flume
linux·ubuntu·flume
承渊政道8 小时前
Linux网络学习【Reactor反应堆模式】
linux·网络·学习·ubuntu·reactor
且从容.11 小时前
ubuntu安装flink
linux·ubuntu·flink
爱和冰阔落13 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
程序员沉梦听雨13 小时前
WSL2的安装与使用
linux·wsl
微小的鱼13 小时前
Linux的渲染与显示系统链路
android·java·linux
lisanmengmeng13 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器