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

news2025/1/19 14:18:15

前言

一、什么是语句?

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

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()中只能是整形,不能是其它类型,有人会问,为什么也看见可以放字符型呢?因为字符也是整形的一类。

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 语句的写法。

以下为一个利用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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1568853.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java运行时内存

从jdk1.7以及以后&#xff0c;静态变量和常量池存在堆空间。

【TSP旅行商问题】改进的大邻域搜索算法LNS

课题名称&#xff1a;基于改进的大规模邻域搜索算法LNS求解TSP问题 版本时间&#xff1a;2024-04-01 程序运行&#xff1a;直接运行LNS_TSP.m 文件即可 代码获取方式&#xff1a; QQ&#xff1a;491052175 VX&#xff1a;Matlab_Lover 模型介绍&#xff1a; 第一步&…

[AutoSar]BSW_Memory_Stack_004 创建一个简单NV block并调试

目录 关键词平台说明背景一、需求二、配置2.1 NvMBlockDescriptors2.2 NvMFeeRef2.3 FeeBlockConfigurations 三、code3.1 声明和定义3.2 调试 关键词 嵌入式、C语言、autosar、OS、BSW 平台说明 项目ValueOSautosar OSautosar厂商vector &#xff0c; EB芯片厂商TI 英飞凌编…

SpringBoot -- 外部化配置

我们如果要对普通程序的jar包更改配置&#xff0c;那么我们需要对jar包解压&#xff0c;并在其中的配置文件中更改配置参数&#xff0c;然后再打包并重新运行。可以看到过程比较繁琐&#xff0c;SpringBoot也注意到了这个问题&#xff0c;其可以通过外部配置文件更新配置。 我…

钉钉事件订阅前缀树算法gin框架解析

当钉钉监测到发生一些事件&#xff0c;如下图 此处举例三个事件user_add_org、user_change_org、user_leave_org&#xff0c;传统的做法是&#xff0c;我们写三个if条件&#xff0c;类似下图 这样字符串匹配效率比较低&#xff0c;于是联想到gin框架中的路由匹配算法&#xff0…

利用Spark将Kafka数据流写入HDFS

利用Spark将Kafka数据流写入HDFS 在当今的大数据时代&#xff0c;实时数据处理和分析变得越来越重要。Apache Kafka作为一个分布式流处理平台&#xff0c;已经成为处理实时数据的事实标准。而Apache Spark则是一个强大的大数据处理框架&#xff0c;它提供了对数据进行复杂处理…

Linux操作系统之nfs网络文件系统

目录 一、NFS简介 1.2 安装配置NFS 一、NFS简介 nfs类似于windows文件共享 将linux的一个目录共享到网络中&#xff0c;网络中的其他所有主机都可以使用这个共享目录中的文件 samba 文件共享 可以在linux中通过samba共享一个目录&#xff0c;然后在linux中可以访问这个共享 …

55 npm run serve 和 npm run build 的分包策略

前言 这里我们来看一下 vue 这边 打包的时候的一些 拆分包的一些策略 我们经常会使用到 npm run build 进行服务的打包 然后 打包出来的情况, 可能如下, 可以看到 chunk-vendors 是进行了包的拆分, 我们这里就是 来看一下 这里 npm run build 的时候的, 一个分包的策略 测试…

【HTML】简单制作一个唱片动画效果

目录 前言 开始 HTML部分 CSS部分 效果图 总结 前言 无需多言&#xff0c;本文将详细介绍一段代码&#xff0c;具体内容如下&#xff1a; 开始 首先新建文件夹&#xff0c;创建两个文本文档&#xff0c;其中HTML的文件名改为[index.html]&#xff0c;CSS的…

Matlab|储能辅助电力系统调峰的容量需求研究

目录 1 主要内容 目标函数 约束条件 2 部分代码 3 程序结果 4 下载链接 1 主要内容 该程序参考文献《储能辅助电力系统调峰的容量需求研究》&#xff0c;主要是对火电、风电和储能等电力设备主体进行优化调度&#xff0c;在调峰能力达不到时采用弃负荷&#xff0c;程序以…

第十四届省赛大学B组(C/C++)子串简写

原题链接&#xff1a;子串简写 程序猿圈子里正在流行一种很新的简写方法&#xff1a; 对于一个字符串&#xff0c;只保留首尾字符&#xff0c;将首尾字符之间的所有字符用这部分的长度代替。 例如 internationalization 简写成 i18n&#xff0c;Kubernetes 简写成 K8s&#…

【贪玩巴斯】Mac的M芯片(M1/2...)下载homebrew方法(24年最新且已验证可行)

1. 按照目前广为流传的方法&#xff08;M1会出现一些问题&#xff09;&#xff1a; 终端输入&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 使用国内镜像下载。 2. 输入后按照要求步骤执行即可&#xff…

docker-compose运行springinitializr用来创建springboot2

前言 spring initializr官方的地址是: https://start.spring.io/ &#xff0c;这是一个用来创建springboot脚手架的一个工具&#xff0c;但是目前这个工具已经更新到springboot3&#xff0c;而我还没学springboot3&#xff0c;目前还想继续创建springboot2&#xff0c;我就想能…

如何预防自己网站被流量劫持?HTTPS加密是否可行?

如何预防自己网站被流量劫持&#xff1f;HTTPS加密是否可行&#xff1f; 文章背景&#xff1a; 所谓的流量劫持&#xff0c;就是利用各种恶意软件修改浏览器、锁定主页或不停弹出新窗口&#xff0c;强制用户访问某些网站&#xff0c;从而造成用户流量损失的情形。 流量劫持是一…

前端三剑客 —— CSS (第一节)

目录 CSS 什么是CSS CSS的几种写法&#xff1a; 行内样式 内嵌样式 外链样式 import 加载顺序 CSS选择器*** 基本选择器 ID选择器 标签选择器 类选择器 通用选择器 包含选择器 上节内容中提到了 前端三剑客 —— HTML 超文本标记语言&#xff0c;这节内容 跟大家…

开发一个Java项目常用的工具类推荐

文章目录 新建Java项目pom.xml添加依赖添加代理仓库项目打jar包并上传配置Springboot依赖MySQL数据库相关依赖lombok接口文档Swagger相关其他常用工具类Hutool插件 完整的pom参考其他参考&#xff1a; 每次新起一个Java项目&#xff0c;都需要经历一系列的繁琐步骤去初始化这个…

jupyter Notebook 默认路径修改

1. anaconda prompt 中运行 jupyter notebook --generate-config 命令&#xff0c;将在 C:\Users\Think\.jupyter文件下生成 jupyter_notebook_config.py 文件。 2.在jupyter_notebook_config.py 文件中&#xff0c;找c.NotebookApp.notebook_dir 这个变量&#xff0c; (1)若…

基于Python的微博舆论分析,微博评论情感分析可视化系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

【SaaS,PaaS? XaaS -微参考】

介绍 以下是关于各种云服务模式的简要介绍&#xff0c;包括全称、定义、典型场景和应用&#xff1a; 缩写全称定义关键词典型场景和应用SaaSSoftware as a Service将软件以服务的形式交付给用户&#xff0c;用户通过互联网访问软件。提供软件电子邮件、在线办公套件&#xff…

Golang | Leetcode Golang题解之第3题无重复字符的最长子串

题目&#xff1a; 题解&#xff1a; func lengthOfLongestSubstring(s string) int {// 哈希集合&#xff0c;记录每个字符是否出现过m : map[byte]int{}n : len(s)// 右指针&#xff0c;初始值为 -1&#xff0c;相当于我们在字符串的左边界的左侧&#xff0c;还没有开始移动r…