【C语言】分支与循环语句

什么是语句?

C语句可分为以下五类:

  1. 表达式语句
  2. 函数调用语句
  3. 控制语句 (本篇重点介绍)
  4. 复合语句
  5. 空语句

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

  • 顺序结构
  • 选择结构
  • 循环结构

它们由特定的语句定义符组成,C语言有九种控制语句。可分成以下三类:

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

分支语句(选择结构)

if语句的语法结构可以分为单分支结构,双分支结构和多分支结构。

   单分支                    双分支                       多分支
 
if(判断表达式)           if(判断表达式)                  if(判断表达式1)
{                       {                             {
    语句列表;                语句列表1;                   语句列表1}                       }                             }
                        else                          else if(判断表达式2)
                        {                             {
                             语句列表2;                   语句列表2}                             }
                                                      else
                                                      {
                                                          语句列表3}  
这里的一对{}称为一个代码块,建议无论语句列表是一句代码还是多句,都带上{}

如果表达式的结果为真,则语句执行。在C语言中,0表示假,非0表示真。实例如下:

  1. 在单分支结构中:若判断表达式结果为真,则执行if中的语句;若判断表达式的结果为假,不执行if中的语句,按照源程序的顺序接着执行。
    在这里插入图片描述
  2. 双分支结构中:若判断表达式结果为真,则执行if后大括号内部的语句1;若判断表达式的结果为假,执行else中的语句2。
    在这里插入图片描述
  3. 多分支结构中:若判断表达式1的结果为真,则执行if后大括号内部的语句1;若判断表达式1的结果为假,则进入判断表达式2,若结果为真,执行语句2,若结果为假,执行else中的语句3;再次说明,多分支的分支个数并不止图例中3个,可能更多,请根据实际情况进行操作。

    在这里再对多分支语句进行强调,也是非常重要的一点,无论大家在使用多分支时在 if 和 else 中间使用多少 else if , 它归咎到底还是一条语句,只会进入符合条件的那一个选项中。其次不建议大家将 else if 写为 if (根据题目要求进行理性选择),虽然效果相同,但是在程序真正执行时 if–else if–else语句最少判断一次,最多判断(假设有3个else if)4次,而使用 if 替代 else if 后,无论判断表达式为真或为假,它都要进去判断一次,及判断次数永远包含所有情况,判断效率大大下降,希望大家能够理解。

悬空else

else 与离它最近的 if 匹配。

适当地使用{}可以使代码的逻辑更清楚,避免一些阅读程序的误会。

代码风格非常重要,好的代码风格不但可以让阅读代码的读者清晰的理解,而且可以使自己的思维逻辑更加清晰不容易出错,推荐书籍《高质量的C/C++编程》。

简单举两个例子(两个例子中的代码1和代码2输出结果均相同):
在这里插入图片描述
在这里插入图片描述

if书写形式的对比

用{}使代码误读率下降。

    代码1                               代码2
 
if(判断表达式)                      if(判断表达式)
{                                  {
    return x;                          return x;
}  
else                               }
{
    return y;                      return y;
}
//推荐                             //不推荐

在比较变量和常量是否相等时,写为 常量==变量 的形式,可以有效避免一些代码问题。

   代码1                                  代码2
 
int num = 1 ;                          int num = 1;
if(5 == num)                           if(num == 5)
{                                      {
    printf("JX\n");                        printf("JX\n");    
}                                      }
//推荐                                 //不推荐

switch语句

switch语句也是一种分支语句。常常用于多分支的情况。

switch的构造如下:

switch 在圆括号中的表达式值是一个整数值(包括char类型),case 标签必须是整数类型(包括char类型)的常量或整形常量表达式,不可以用变量来作为 case 的标签。

switch(整形表达式)                        
{
    case 常量1:
         语句;
    case 常量2:
         语句;
    default:
         语句;
}

switch语句中的 break

在switch语句中,我们没办法直接实现分支,搭配break使用才能实现真正的分支。

#include <stdio.h>                         #include<stdio.h>
int main()                                 int main()
{                                          {
    int day = 0;                               int day = 0;    
    scanf("%d",&day);                          scanf("%d",&day);
    switch(day)                                switch(day)       
    {                                          {
    case 1case 1:
        printf("星期一\n");                    case 2:      
        break;                                 case 3:
    case 2:                                    case 4:
        printf("星期二\n");                    case 5:
        break;                                     printf("周内\n");
    case 3:                                        break;
        printf("星期三\n");                    case 6:
        break;                                 case 7:
    case 4:                                        printf("周末\n");
        printf("星期四\n");                         break;
        break;                                 default:                           
    case 5:                                        printf("输入错误\n");
        printf("星期五\n");                        break;
        break;                                 }                 
    case 6:                                    return 0;          
        printf("星期六\n");                }      
        break;
    case 7:
        printf("星期天\n");
        break;                              好习惯:
    default:                       < —————— 在 switch 语句中都放一条default子句,
        printf("选择错误\n");              可以在后面加一个breakbreak;
    }
    return 0;
}

break语句实际效果是把语句列表划分为不同的分支部分。break 语句是 switch 语句的出口,让程序离开 switch 语句,跳转到其下一条语句,如果没有 break 语句,就会从匹配标签的第一个case开始一直执行到 switch 末尾。

顺便总结一下,break 语句既可以用于循环语句中同时也可以用于 switch 语句中,但 continue 只能用于循环中。如果 switch 语句在一个循环中,continue 就可以作为 switch 语句的一部分,就像在其他循环一样,continue 让程序跳出循环的剩余部分,包括 switch 语句的其他部分。

default子句

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

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

阅读代码,提升理解

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

最终结果为 m = 5, n = 3,你答对了吗?

循环语句

while 循环

while的语法结构:         while(判断表达式)
                         {
                              循环语句;
                         }             

具体实现为,如果判断表达式为真,执行循环语句一次,然后返回判断表达式再次判断;在判断表达式为假之前,循环的判断和执行一直重复进行,每一次循环都被称为一次迭代。图解如下:
在这里插入图片描述
了解了while的工作流程,就来实现一下在屏幕打印1~10的数字。
在这里插入图片描述

while语句中的break和continue

break介绍

在这里插入图片描述

break在while循环中的作用:

其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。所以:while中的break是用于永久终止循环的。

continue介绍

在这里插入图片描述

continue在while循环中的作用就是:

continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。

getchar() 和 putchar()

对于scanf和getchar这样的输入函数,它们若想得到输入的内容,是这样进行的:你先在键盘上将所输入的东西打到缓冲区中,然后再将缓冲区中的内容传递给了输入函数。也就是说还有一个缓冲区。
在这里插入图片描述
由于 getchar() 和 putchar() 这两个函数只处理字符,所以它们比通用的 scanf() 和 printf() 函数更快、更简洁。并且这两个函数不需要转换说明,因为它们只处理字符。它们定义在 stdio.h 头文件中,比较特殊的是,getchar() 和 putchar() 通常是预处理宏,不是真正的函数。

在这里插入图片描述

  1. scanf()函数默认是读取到空白字符停止或在结尾处停止(其中键盘敲击的\n不会被读取)。
  2. getchar() 和 putchar() 一次只读取一个字符(又像是逐字符进行读取),并且将其转化为 int 类型(对应ASCLL码值)赋给ch。

在这里插入图片描述
在这里插入图片描述

for循环

语法

for(表达式1(变量初始化); 表达式2(判断表达式); 表达式3(调整变量))
{
    循环语句;
}
  • 表达式1为初始化部分,用于初始化循环变量的。
  • 表达式2为条件判断部分,用于判断循环时候终止。
  • 表达式3为调整部分,用于循环条件的调整。
    在这里插入图片描述
    在while循环中也存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹;for循环使用的频率也最高。

for循环中的break和continue

我们发现在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。但是结果就不一样了。在这里插入图片描述
在这里插入图片描述

for语句的循环控制变量

建议:

  1. 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
  2. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
int i = 0;
//前闭后开的写法
for(i=0; i<10; i++)
{...}
//两边都是闭区间
for(i=0; i<=9; i++)
{...}

一些for循环的变种

for循环中的初始化部分,判断部分,调整部分是可以省略的,但是不建议初学时省略,容易导致问题。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

do…while()循环

do语句的语法

do
{
    循环语句;
}
while(判断表达式);

do语句的特点

循环至少执行一次,但使用的场景有限,所以不是经常使用。

在这里插入图片描述

do while 循环中的break和continue

跟前面的while和for几乎是一样的,直接上例子。

在这里插入图片描述
在这里插入图片描述

goto语句

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

例如:一次跳出两层或多层循环。

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

goto语言真正适合的场景如下:

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

下面是使用goto语句的一个关机程序,然后再使用循环的实现方式替换goto语句:

#include<stdio.h>
#include <stdlib.h>
#include <string.h>
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;
}

而如果不适用goto语句,则可以使用循环:

#include<stdio.h>
#include <stdlib.h>
#include <string.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;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MidJourney笔记(9)-daily_theme-docs-describe

/daily_theme 切换 #daily-theme 频道更新的通知。 但我发现在对话框那里,是没有这个命令的: 但官网是有介绍,不知道是不是版本问题还是这个命令已经无效。 但后来,我发现这个命令是要在Midjourney服务对话框那里才有,在我们后面添加的Mid

哈希桶的模拟实现【C++】

文章目录 哈希冲突解决闭散列 &#xff08;开放定址法&#xff09;开散列 &#xff08;链地址法、哈希桶&#xff09;开散列实现&#xff08;哈希桶&#xff09;哈希表的结构InsertFindErase 哈希冲突解决 闭散列 &#xff08;开放定址法&#xff09; 发生哈希冲突时&#xf…

MySQL数据库多版本并发控制(MVCC)

在数据库中&#xff0c;并发控制是确保多个事务能够同时执行&#xff0c;而不会导致数据不一致或冲突的关键机制。多版本并发控制(MVCC)是一种流行的并发控制方法&#xff0c;它可以允许多个事务同时读取同一数据项的不同版本&#xff0c;而不会相互阻塞。本文将讨论MVCC的原理…

【每日一题】LeetCode206.反转链表

个人主页&#xff1a;白日依山璟 专栏&#xff1a;Java|数据结构与算法|每日一题 文章目录 1. 题目描述示例1示例2示例3提示 2. 思路3.代码 1. 题目描述 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例1 输入&#xff1a;head [1…

FreeRTOS任务调度

开启任务调度器 vTaskStartScheduler(); 无参数, 无返回值. 作用是用于启动任务调度器&#xff0c;任务调度器启动后&#xff0c; FreeRTOS 便会开始进行任务调度 . 如果允许了静态创建任务, 则创建空闲任务和创建定时器任务都会变为需要程序员手动实现创建. 1.创建空闲任务(…

成为一名成功的互联网产品经理需要掌握哪些技能?

在现代互联网产业中&#xff0c;产品经理扮演着至关重要的角色。作为产品经理&#xff0c;需要不断地学习和提高自己的技能&#xff0c;以便为用户提供更佳的产品体验。以下是成为一名成功的互联网产品经理所需要掌握的技能&#xff1a; 1.产品设计技能 产品设计是产品经理的…

Linux 线程概念

文章目录 前言线程的概念线程的操作操作的原理补充与说明 前言 ① 函数的具体说明被放在补充与说明部分 ② 只说些基础概念和函数使用 线程的概念 网络回答&#xff1a;Linux 线程是指在 Linux 操作系统中创建和管理的轻量级执行单元。线程是进程的一部分&#xff0c;与进程…

使用数组创建链表的解决方案

因为在创建链表时用到了这种方法&#xff0c;后面发现这种方法创建链表做删除操作时不是很好&#xff0c;就打算删除&#xff0c;但是觉得这种方法可能对部分读者有参考意义&#xff0c;就基于数组创建链表的方法单独发了一篇&#xff0c;完整的~链表五大基础操作的实现方法可参…

2022 年全国职业院校技能大赛高职组云计算正式赛卷第二场-容器云

2022 年全国职业院校技能大赛高职组云计算赛项试卷 云计算赛项第二场-容器云 目录 2022 年全国职业院校技能大赛高职组云计算赛项试卷 【赛程名称】云计算赛项第二场-容器云 【任务 1】容器云平台搭建[5 分] 【任务 2】容器云应用部署&#xff1a; Docker Compose 编排部署[7.0…

Python新手上路:“用Python和Pygame创造你的流星雨”

文章目录 一、前言二、下载安装过程1.官网下载安装包2.安装python过程第一步第二步第三步第四步第五步安装完成 3.简单测试Python3.1 检查 Python 版本号3.2 打开 Python 解释器3.3 输入你的第一个代码3.4 运行 Python 脚本 4.安装Pygame4.1 cmd命令安装Pygame4.2 pip升级4.3 安…

thinkcmf 文件包含 x1.6.0-x2.2.3 已亲自复现

thinkcmf 文件包含 x1.6.0-x2.2.3 CVE-2019-16278 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建漏洞利用 修复建议总结 漏洞名称 漏洞描述 ThinkCMF是一款基于PHPMYSQL开发的中文内容管理框架&#xff0c;底层采用ThinkPHP3.2.3构建。ThinkCMF提出灵活的应用机制&a…

k8s的二进制部署(二)网络

节点部署完成之后,节点的状态都是Notready&#xff0c;所以要部署k8s网络&#xff1a; k8s的网络类型&#xff1a; k8s中的通信模式&#xff1a; pod内部之间容器与容器之间的通信。 在同一个pod中的容器共享资源和网络&#xff0c;使用同一个网络命名空间&#xff0c;可以直…

设计模式(4)--对象行为(6)--备忘录

1. 意图 在不破坏封装的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在该对象之外保存这个状态。 这样以后可以将该对象恢复到原先保存的状态。 2. 三种角色 原发器(Originator)、备忘录(Memento)、负责人(Caretaker) 3. 优点 3.1 保持了封装边界。屏蔽了原发器的…

(13)Linux 进程的优先级、进程的切换以及环境变量等

前言&#xff1a;我们先讲解进程的优先级。然后讲解进程的切换&#xff0c;最后我们讲解环境变量&#xff0c;并且做一个 "让自己的可执行程序不带路径也能执行"的实践&#xff0c;讲解环境变量的到如何删除&#xff0c;最后再讲几个常见的环境变量。 一、进程优先级…

redis的搭建及应用(二)-redis的持久化策略

Redis的持久化策略 RDB RDB持久化是指在指定的时间间隔内将redis内存中的数据集快照写入磁盘&#xff0c;实现原理是redis服务在指定的时间间隔内先fork一个子进程&#xff0c;由子进程将数据集写入临时文件&#xff0c;写入成功后&#xff0c;再替换之前的文件&#xff0c;用二…

Spring对bean的管理

一.bean的实例化 1.spring通过反射调用类的无参构造方法 在pom.xml文件中导入坐标&#xff1a; <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.29<…

云手机引领社交平台运营新潮流

在网络高度发展的今天&#xff0c;社交平台已经成为企业宣传推广的关键渠道之一。传统的社交运营方式已经无法满足效率的要求&#xff0c;云手机因而开始引领社交平台运营的新潮流。本文将深入探讨云手机如何重新定义社交平台运营&#xff0c;为用户和企业带来更为便捷、智能的…

w7数据库基础之mysql函数

系统函数 1.version() --mysql版本 2.user() --当前登录的数据库用户名system_user() 3.database() --当前使用的数据库名。schema() 4.datadir --数据库路径 5.version_compile_os 操作系统版本&#xff0c;like 后面可以使用%%进行模糊查询。 6.hostname 当前机器…

BFS解决多源最短路相关leetcode算法题

文章目录 1.01矩阵2.飞地的数量3.地图中的最高点4.地图分析 1.01矩阵 01矩阵 class Solution {int dx[4] {0,0,1,-1};int dy[4] {1,-1,0,0}; public:vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {//正难则反&#xff0c;找0…

Apache Commons JCS缓存解决方案

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff01;今天&#xff0c;咱们来聊聊Apache Commons JCS&#xff0c;一个Java界里的缓存大杀器。缓存技术&#xff0c;对于提高应用性能来说&#xff0c;就像是给它加了一剂兴奋剂&#xff0c;能让数据访问变得快如闪电。…