C语言之分支语句和循环语句

前言

一、什么是语句?

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

2.1 if语句

2.2 switch语句

三、循环语句

3.1 while循环

3.2 break与continue语句

3.3 getchar()与putchar()

3.3.1 缓冲区

3.4 for循环

3.4.1 一些for循环的变种

3.5 do...while循环

四、goto语句


前言

本章将详细介绍分支语句(选择结构)和循环语句。


一、什么是语句?

C语言语句可分为以下五类:

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

本博客将介绍控制语句。

控制语句用于控制程序的执行流程,以实现程序的各种结构方式(在C语言中有三种结构:顺序结构、选择结构、循环结构),它们又特定的语句定义符组成,C语言中有九中控制语句。

可以分为以下三类:

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

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

什么是分支语句,通俗来讲就是选择。

2.1 if语句

if语句为C语言中一种最常见的分支语句,其语法如下:

语法结构:
//单分支
if(表达式)
    语句;

//双分支
if(表达式)
    语句1:
else
    语句2;

//多分支
if(表达式1)
    语句1;
else if(表达式2)
    语句2;
else
    语句3;

其中表达式最终只有两个值,分别为真和假,C语言中规定,0为假,非0为真,下面用代码分别演示:

int main()
{
	int age = 0;
	scanf("%d", &age);
	//单分支
	if (age < 18)
	{
		printf("未成年\n");
	}

	//双分支
	if (age < 18)
	{
		printf("未成年\n");
	}
	else
	{
		printf("成年\n");
	}

	//多分支
	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");
	}
	return 0;
}

在C语言中,if语句中为单条语句时可以不加大括号{},多条语句必须加大括号{},但我建议不管是单条还是多条语句,都加上大括号{},养成编程好习惯。

另外,我们还要区分以下多分支语句的情况:

//区分if...if 与 if else...if的区别
int main()
{
	int age = 0;
	scanf("%d", &age);
	//if...if多分支
	if (age < 18)
	{
		printf("少年\n");
	}
	if (age >= 18 && age < 30)
	{
		printf("青年\n");
	}
	if (age >= 30 && age < 50)
	{
		printf("中年\n");
	}
	if (age >= 50 && age < 80)
	{
		printf("老年\n");
	}
	else
	{
		printf("寿星\n");
	}

	//if else if多分支
	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");
	}
	return 0;
}
多分支if...ifif  else..if
功能提供多种情况提供多种情况
执行方式逐一执行,每条if语句都会进行判断直接进入为真的语句,并不会逐一执行

看看下列代码:

//悬空else
int main()
{
	int a = 0;
	int b = 2;
	if (a == 1)  //1
		if (b == 2) //2
			printf("hehe\n");
	else
		printf("haha\n");
	return 0;
}

你觉得打印结果是什么呢?打印结果什么都没有。为什么呢?这是因为代码风格的问题,在使用if语句时,必须要注意的一个问题是else和if的匹配问题,上述代码中的else是与第2个if匹配的,因为在C语言中规定,else总是与离得最近的if匹配,故什么都没有打印,下列为改正代码:

int main()
{
	int a = 0;
	int b = 2;
	if (a == 1)
	{
		if (b == 2)
			printf("hehe\n");
	}
	else
	{
		printf("haha\n");
	}
	return 0;
}

因此,适当的加上大括号{},能更好的理解代码,以上的else将与第1个if匹配,这样就通俗易懂了。

并且,在书写if语句时,要编写逻辑清晰的代码,列如以下代码:

//代码1
if(condition)
{
    return x;
}
return y;

//代码2
if(condition)
{
    return x;
}
else
{
    return y;
}

//代码3
int num = 1;
if(num == 5)
{
    printf("hehe\n");
}

//代码4
int num = 1;
if(5 == num)
{
    printf("hehe\n");
}

上述代码中,逻辑是相同的,但代码2与代码4的风格更好,逻辑性更强,不容易出错。

当我们想用变量与常量作为表达式时,推荐用代码4形式,不容易出错:

int num = 1;
if (num = 1)
{
	printf("haha\n");
}

程序不会报错,但逻辑错误

程序会报错,这样可以防止我们出错,故推荐用以下形式:

int num = 1;
if(1 == num)
{
    printf("haha\n");
}

2.2 switch语句

switch适合用于处理多分支情况,常常用于有唯一取值的情况,而if语句更经常用于处理范围。

语法结构:

switch(整数表达式/枚举类型)
{
    case 整形常量表达式/枚举常量:
        语句;
    .....
{

比如:

输入1输出星期一
输入2输出星期二
输入3输出星期三
输入4输出星期四
输入5输出星期五
输入6输出星期六
输入7输出星期七
//switch语句
int main()
{
	int num = 0;
	scanf("%d", &num);
	switch (num)
	{
	case 1:
		printf("星期一");
		break;

	case 2:
		printf("星期二");
		break;

	case 3:
		printf("星期三");
		break;

	case 4:
		printf("星期四");
		break;

	case 5:
		printf("星期五");
		break;

	case 6:
		printf("星期六");
		break;

	case 7:
		printf("星期天");
		break;
	default:
		printf("输入错误\n");
		break;
	}
	return 0;
}

语句中的break非常重要,如果我们少加或者不加break,上述代码将会执行不同的结果:

//switch语句
int main()
{
	int num = 0;
	scanf("%d", &num);
	switch (num)
	{
	case 1:
		printf("星期一");
	case 2:
		printf("星期二");
		break;

	case 3:
		printf("星期三");
		break;

	case 4:
		printf("星期四");
		break;

	case 5:
		printf("星期五");
		break;

	case 6:
		printf("星期六");
		break;

	case 7:
		printf("星期天");
		break;
	default:
		printf("输入错误\n");
		break;
	}
	return 0;
}

当我们输入1时,将会打印星期一星期二,这是因为我们在case1中没有加break,将会一直执行,直到遇到break,跳出。故我们要养成在每一个语句项加上break的情况,但面对不同情况我们也要懂得随机应变,比如以下需求:

输出工作日和周末:

//switch语句
int main()
{
	int num = 0;
	scanf("%d", &num);
	switch (num)
	{
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
		printf("工作日");
		break;
	case 6:
	case 7:
		printf("周末");
		break;
	default:
		printf("输入错误\n");
		break;
	}
	return 0;
}

很多人会疑问,switch的default语句是必须得吗?default语句是与case不匹配后执行的语句,default语句其实也不是必须的,但我们一般会加上,这是一种良好的编程习惯。


对于switch语句,我们要关注以下两个方面:

  1. switch(整形表达式/枚举类型)
  2. case 整形常量表达式/枚举常量

switch()中只能是整形,不能是其它类型,有人会问,为什么也看见可以放字符型呢?因为字符也是整形的一类。

枚举类型(enum)在C语言中实际上是一组命名的整数常量。

case 后跟整形常量表达式,注意是常量,不能放变量。


三、循环语句

while循环
for循环
do...while循环

while循环、for循环、do...while循环有一个共同的特点:

判断部分总是比循环体多执行一次。

3.1 while循环

while循环语法结构

while(表达式)

{
        循环语句;
}

while循环语句执行流程:

3.2 break与continue语句

作用作用域
break用于永久终止循环while、for、do...while、switch
continue跳过本次循环,执行下一次循环while、for、do...while

在for循环、while循环、do...while循环中,break的功能是一样的。

但对于continue,在for循环、while循环、do...while循环中根据代码情况是有一定的差异:

while循环与do...while循环情况相同

#include<stdio.h>
int main()
{
    int i = 1;
    while(i <= 10)
    {
        if(5 == i)
            continue; //此时的continue将跳过本次循环,执行下一次循环,但控制条件i,在continue 
                      //语句的后面,因此该程序将进入死循环状态
        i++;
        printf("%d ", i);
    }

    do
    {
        if(5 == i)
            continue; //此时的continue将跳过本次循环,执行下一次循环,但控制条件i,在continue 
                      //语句的后面,因此该程序将进入死循环状态
        i++;
        printf("%d ", i);
    }while(i <= 10);

    for(i=1; i<=100; i++)
    {
        if(5 == i)
            continue;  // 此时continue将跳过本次循环,执行下一次循环,for循环中的控制条件i是 
                       // 不受影响的
        printf("%d ", i);
    }
}

3.3 getchar()与putchar()

作用返回值
getchar()从键盘读取字符

返回类型为int,

成功:读取到字符后,返回该字符的ASCII码值

失败:读取返回EOF --> -1

putchar()打印字符int类型

3.3.1 缓冲区

        概念:我们进行从键盘输入时,并不是直接传递到了程序上,先是存放在缓冲区中。

//代码什么意思?
 #include <stdio.h>
 int main()
 {
     int ch = 0;
     while ((ch = getchar()) != EOF)
         putchar(ch);
     return 0;
 }

该代码是一种多组输入的形式,重复在键盘上进行输入然后读取打印,直到输入失败EOF结束。

 想要结束:Ctrl+z,具体的原理图如下:第一次缓冲区里有A\n,putchar()读取走了A,又继续输入B\n,此时缓冲区里有\nB\n,然后又进行读取,因此可以看到打印结果是字符换行字符换行.....

因此,getchar()常常用来清空缓冲区:

int main()
{

	printf("请输入密码:>");
	char password[20] = { 0 };
	scanf("%s", password);
	//清理缓冲区
	getchar()
	printf("请确认密码(y/n):>");
	int ch = getchar();
	if (ch == 'y')
	{
		printf("确认成功\n");
	}
	else
	{
		printf("确认失败\n");
	}
	
	return 0;
}

这份清空缓冲区的代码是有bug的,当scanf输入:123空格abc\n 时,getchar()只读取了空格,而空格后还有东西。

scanf()读取,默认遇到空格就停止

正确写法如下:

int main()
{

	printf("请输入密码:>");
	char password[20] = { 0 };
	scanf("%s", password);
	//清理缓冲区
	while (getchar() != '\n')
	{
		;
	}
	printf("请确认密码(y/n):>");
	int ch = getchar();
	if (ch == 'y')
	{
		printf("确认成功\n");
	}
	else
	{
		printf("确认失败\n");
	}
	
	return 0;
}

当然,如果想继续读取空格后的内容的话,可以参考如下代码:

int main()
{
	char arr[20] = {0};
	scanf("%[^\n]", arr);
	printf("%s\n", arr);
    return 0;
}

scanf("%[^\n]", arr);中的%[^\n]表示读取到\n停止,当然也可以将\n换成自己的需求。

3.4 for循环

for循环语法结构
for(表达式1; 表达式2; 表达式3)
{
    循环语句;
}

表达式1:为初始化部分,用于初始化循环变量的。(该部分仅仅首次循环执行)

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

表达式3:为调整部分,用于循环条件的调整。(执行完循环体后才执行该部分)

for循环的执行流程图:

对比一下for循环和while循环:

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循环的优点之一,修改起来更加方便。

看一下代码:

int i = 1;
for(i = 1; i<=10; i++)
{
    i = 0 // 可行吗??
}

这是不规范的代码,容易产生Bug,建议不可在for 循环体内修改循环变量,防止 for 循环失去控制。

在看以下两份代码:

int i = 0;
//前闭后开的写法
for(i=0; i<10; i++)
{}

//两边都是闭区间
for(i=0; i<=9; i++)
{}

你觉得那种定义更加直观呢?建议议for语句的循环控制变量的取值采用“前闭后开区间”写法。

前闭后开能更加直观的直到该循环执行多少次。(看判断条件就可以了)

3.4.1 一些for循环的变种

//代码1:for循环的三个部分均可以省略
//该程序是一个死循环,造成死循环的原因:省略了判断部分
//for循环中,判断部分不写,恒为真
for(;;)
{
    printf("hehe\n");
}

//代码2
int i = 0;
int j = 0;
//如果省略掉初始化部分,这里打印多少个hehe?
//3个。
//for循环省略掉初始化条件部分,会造成的影响,
//因为for循环中初始化部分在整个循环中只会执行一次,
//当程序结束,又一次执行内层循环时,本该为j重新赋值时,发现没有初始化部分,此时j已自增到3了
for(; i<10; i++)
{
     for(; j<10; j++)
     {
         printf("hehe\n");
     }
}


//代码3-使用多余一个变量控制循环
//此情况根据具体需求设定
int x, y;
for (x = 0, y = 0; x<2 && y<5; ++x, y++)
{
     printf("hehe\n");
}

针对代码2:

笔试题:

//请问循环要循环多少次?
#include <stdio.h>
int main()
{
     int i = 0;
     int k = 0;
     for(i =0,k=0; k=0; i++,k++)
         k++;
     return 0;
}

答:0次。因为判断部分k = 0 是一种赋值语句,因此判断部分为0,则为假,不进入循环体。

3.5 do...while循环

//do...while循环语法结构
do
  循环语句;
while(表达式); //注意结尾要加;

do..while语句执行流程:

do...while循环最大的特点:循环至少执行一次

四、goto语句

//goto语句语法结构
goto label;  //label可以是任何除C关键字以外的纯文本,它可以设置在C程序中goto语句的前面或者后面。
label:
    根据需求编写代码....

C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。 从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。 但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。列如:

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

注意:在任何编程语言中,都不建议使用 goto 语句。因为它使得程序的控制流难以跟踪,使程序难以理解和难以修改。任何使用 goto 语句的程序可以改写成不需要使用 goto 语句的写法。

shutdown其它用法参考

关机:shutdown -s -t 时间(秒)

取消关机:shutdown -a

以下为一个利用goto语句编写的关机程序:

#include <stdio.h>
#include <stdlib.h> //使用system()需要包含的头文件
int main()
{
    char input[10] = {0};
    system("shutdown -s -t 60");
    again:
     printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
     scanf("%s", input);
     if(0 == strcmp(input, "我是猪"))
     {
         system("shutdown -a");
     }
     else
     {
         goto again;
     }
     return 0;
}

使用循环实现:

#include <stdio.h>
#include <stdlib.h>
 int main()
 {
     char input[10] = {0};
     system("shutdown -s -t 60");
     while(1)
     {
         printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
         scanf("%s", input);
         if(0 == strcmp(input, "我是猪"))
        {
             system("shutdown -a");
             break;
        }
     }
     return 0;
}
  • 17
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值