C语言入门系列:流程控制
一,C代码执行顺序
默认情况下,C语言程序从main()函数开始执行,随后按源代码中语句出现的顺序逐一执行。
这意味着,如果不考虑任何控制结构,程序会自上而下,逐行执行每条语句,直到遇到函数调用、返回语句或程序结束。
但是,在实际编程中,很多任务和逻辑无法仅通过简单的从上到下的顺序执行来完成。以下通过几个典型场景来说明这一点:
1. 条件执行:决定性操作
假设你正在编写一个程序来判断一个数是正数、负数还是零。
如果不使用控制语句,程序将无法根据输入的数值做出不同的反应,因为所有的操作都将按顺序执行,无法选择性地执行特定代码。
使用if
语句,可以轻松实现这一点:
#include <stdio.h>int main() {int num = 5;if (num > 0) {printf("正数\n");} else if (num < 0) {printf("负数\n");} else {printf("零\n");}return 0;
}
2. 循环处理:重复性任务
如果你需要打印出1到10的数字,仅仅依靠顺序执行是不够的,因为你需要让相同的打印操作重复执行10次。
对于这个星期,调用10次printf
即可。但如果是重复1万次呢,在代码中调用1万次printf
,那也太傻了吧?
这时,循环控制语句(如for
循环)就显得尤为重要:
#include <stdio.h>int main() {for(int i = 1; i <= 10; i++) {printf("%d ", i);}printf("\n");return 0;
}
3. 跳出循环:提前结束或跳过
在某些情况下,可能需要在满足特定条件时提前结束循环,或者在循环内部的某些点跳过某些步骤。这时,break
和continue
控制语句就发挥了作用:
#include <stdio.h>int main() {for(int i = 1; i <= 10; i++) {if(i == 5) {printf("遇到5,提前结束循环\n");break; // 跳出循环}if(i % 2 == 0) {continue; // 跳过偶数,不打印}printf("%d ", i);}printf("\n");return 0;
}
二,控制类型
C语言中的流程控制语句可以大致分为以下几类:
- 条件分支语句
- 循环语句
- 跳转语句
- 其他控制
1. 条件分支语句
- if 语句:基于一个条件,决定是否执行某段代码。
- 三元运算符(条件运算符)
?:
:一种简洁的条件表达式形式,用于赋值操作,根据条件选择两个表达式之一。 - switch 语句:用于多路分支选择,根据不同的表达式值执行不同的代码块。
2. 循环语句
- while 语句:只要给定条件为真,就重复执行一段代码。
- do…while 结构:先执行循环体,然后检查条件是否为真,如果是,则继续执行循环。
- for 语句:一种复合循环结构,集成了初始化、条件检查和迭代更新于一身。
3. 跳转语句
- break 语句:用于提前退出循环或switch语句。
- continue 语句:跳过当前循环迭代的剩余部分,直接开始下一次迭代。
- goto 语句:允许程序跳转到同一函数内的指定标签处,虽然可用,但因其可能引起代码混乱和可读性差,现代编程实践中通常不鼓励使用。
4. 其他控制结构
- 虽然不是C语言标准库直接提供的流程控制语句,但通过组合基本的流程控制语句,可以实现更复杂的控制结构,如:
- 循环嵌套:一个循环内部包含另一个循环。
- 条件循环:在循环条件中使用逻辑表达式来控制循环的执行。
- 提前返回(return):在函数中使用,可以立即结束函数的执行并返回一个值(对于非void类型函数)。
三,条件分支语句
条件分支语句让程序能够根据条件跳过某些代码、执行特定代码
。
1. if 语句
基本语法
if语句用于条件判断,满足条件时,就执行指定的语句,不满足就跳过对应的语句。
if (expression) statement
上面式子中,表达式expression为真(值不为0)时,就执行statement语句,statment部分称之为代码块
。
if后面的判断条件expression外面必须有圆括号,否则会报错。代码块可以是一条语句或多条语句,多条语句必须包含在一对大括号内。
下面是一个一条语句例子。
if (x == 10) printf("x is 10");
上面示例中,当变量x为10时,就会输出一行文字。
为了更好的可读性,语句部分通常另起一行。
if (x == 10)printf("x is 10\n");
如果代码块包含多条语句,就需要把它们放在大括号里面,组成一个复合语句。
if (line_num == MAX_LINES) {line_num = 0;page_num++;
}
我们建议,无论是一行语句,还是多行语句,都用大括号包裹起来,有更好的可读性,避免出现意外的错误。
if (x == 10) {printf("x is 10\n");
}
if-else
if语句可以带有else分支,指定条件不成立时(表达式expression的值为0),所要执行的代码。
if (expression) statement
else statement
下面是一个例子。
if (i > j)max = i;
elsemax = j;
如果else的语句部分多于一行,同样必须把它们放在大括号里面。
多重判断
else可以与另一个if语句连用,构成多重判断。
if (expression)statement
else if (expression)statement
...
else if (expression)statement
elsestatement
如果有多个if和else,可以记住这样一条规则,else总是跟最接近的if匹配。
if (number > 6)if (number < 12)printf("The number is more than 6, less than 12.\n");
elseprintf("It is wrong number.\n");
上面示例中,else部分匹配最近的if(即number < 12),所以如果number等于6,就不会执行else的部分。
不过,为了提供代码的可读性,建议使用大括号,明确else匹配哪一个if。
if (number > 6) {if (number < 12) {printf("The number is more than 6, less than 12.\n");}
} else {printf("It is wrong number.\n");
}
强烈建议,if和else后的代码块不要省略大括号,哪怕在只有一行语句的情况下。
2. 三元运算符 ?:
三元运算符是if...else
的简写形式,用于简单的条件赋值。其语法结构如下。
<expression1> ? <expression2> : <expression3>
下面是一个示例。
#include <stdio.h>int main() {int score = 75;char result = (score >= 60) ? 'P' : 'F';printf("Your grade is: %c\n", result);return 0;
}
这段代码可以用if-else改写。
#include <stdio.h>int main() {int score = 75;char result;if (score >= 60) {result = 'P';} else {result = 'F';}printf("Your grade is: %c\n", result);return 0;
}
3. switch 语句
switch
语句根据不同的情况执行不同代码块,每个情况由一个或多个case标签指定。
switch 语句可以理解为一种特殊形式的 if-else 结构,switch 语句更易用、可读性更好。
switch (expression) {case value1: statement1case value2: statement2default: statement3
}
这个结构表达的是,expression 的值匹配到某个case后,执行对应的statement。
举例如下。
#include <stdio.h>int main() {int day = 3;switch(day) {case 1:printf("Monday\n");break;case 2:printf("Tuesday\n");break;case 3:printf("Wednesday\n");break;default:printf("Invalid day\n");}return 0;
}
上面switch语句表达的是,根据整数类型变量day的值选择执行特定的代码。若day的值是1,输出Monday
,如果是2,输出Tuesday
,如果是3,输出Wednesday
,如果都不是,执行default对应的语句,输出Invalid day
。因为上述代码中变量day的值是3,所以会执行printf("Wednesday\n");
,输出Wednesday
。
注意,每个case语句体的结尾,都应该有一个break语句,作用是跳出整个switch结构,不再往下执行。如果缺少break,就会继续执行下一个case或default分支。
上述代码在执行代码printf("Wednesday\n");
后,遇到break语句,跳出switch语句,执行其后的语句return 0;
。
如下代码,第2个case的代码块没有break语句。
#include <stdio.h>int main() {int day = 2;switch(day) {case 1:printf("Monday\n");break;case 2:printf("Tuesday\n");case 3:printf("Wednesday\n");break;default:printf("Invalid day\n");}return 0;
}
因为day的值是2,所以执行 printf("Tuesday\n");
,但由于没有break语句,会接着执行第三个case的代码块,即执行代码printf("Wednesday\n");
,然后因为break语句,跳出switch语句。
本意是当day值为3时,才输出Wednesday
,但因为第2个case后的代码块缺少break,导致错误发生。
如果要省略case后代码块的break,一定要明确不会出现意外的情况。
四,循环语句
1. while 语句
while语句用于循环结构,满足条件时,不断执行循环体。
while (expression)statement
statement部分称之为循环体。
上面代码中,如果表达式expression为非零值(表示真),就会执行statement语句,然后再次判断expression是否为零;如果expression为零(表示伪)就跳出循环,不再执行循环体。
下面代码的作用是判断一个整数有多少位,用while循环实现。
#include <stdio.h>int main() {int count = 0;int num = 2323233232;int tmpNum = num;while(tmpNum > 0) {count++;tmpNum= tmpNum / 10;}printf("num=%d是%d位数", num, count);return 0;
}
上述代码不够健壮,没有考虑临界情况,即当num = 0
时,程序不能得出正确结果。
在使用循环体时,要特别注意临界问题。
我们做如下优化:
#include <stdio.h>int main() {int count = 0;int num = 2323233232;int tmpNum = num;// 临界情况,特殊处理if (num == 0) {count++;}while(tmpNum > 0) {count++;tmpNum= tmpNum / 10;}printf("num=%d是%d位数", num, count);return 0;
}
注意,当循环体中只有一条语句时,可以省略大括号。有多条语句时,不能省略。但强烈建议,即便只有一条语句,也不要省略大括号。
#include <stdio.h>int
main ()
{int day = 2;// 省略大括号,语法正确while (day < 3)printf ("day=%d\n", day++);printf ("day=%d", day++);return 0;
}
加上大括号,可读性更强。
#include <stdio.h>int
main ()
{int day = 2;// 省略大括号,语法正确while (day < 3) {printf ("day=%d\n", day++);}printf ("day=%d", day++);return 0;
}
2. do…while 结构
与while
类似,最大的区别是do-while
先执行一次循环体,然后检查条件,所以其至少会执行一次循环体。
用do-while重写计算整数位数的例子。
#include <stdio.h>int main() {int count = 0;int num = 2323233232;int tmpNum = num;do {count++;tmpNum= tmpNum / 10;} while(tmpNum > 0)printf("num=%d是%d位数", num, count);return 0;
}
如果用do-while
,临界情况num = 0
就无需特殊处理。
同样,我们建议循环体始终包裹在大括号中。
3. for 语句
for语句是最常用的循环结构,通常用于精确控制循环次数。
for (initialization; continuation; action)statement;
上面代码中,for语句的条件部分(即圆括号里面的部分)有三个表达式。
- initialization:初始化表达式,用于初始化循环变量,只执行一次。
- continuation:判断表达式,只要为true,就会不断执行循环体。
- action:循环变量处理表达式,每轮循环结束后执行,使得循环变量发生变化。
#include <stdio.h>int main() {for(int i = 0; i < 5; i++) {printf("%d ", i);}printf("\n");return 0;
}
五,跳转语句
1. break 语句
break
用于立即退出最内层循环或switch
语句。
break语句有两种用法。
- 一种是与switch语句配套使用,用来中断某个分支的执行,这种用法前面已经介绍过了。
- 另一种用法是在循环体内部跳出循环,不再进行后面的循环了。
for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {printf("%d, %d\n", i, j);break;}
}
上面示例中,break语句使得循环跳到下一个i。
注意,break命令只能跳出循环体
和switch结构
,不能跳出if
结构。
if (n > 1) {if (n > 2) break; // 无效printf("hello\n");
}
上面示例中,break语句是无效的,因为它不能跳出外层的if结构,还会继续执行printf("hello\n")
。
注意事项
- 在多层循环中,
break
只跳出当前层循环。
2. continue 语句
continue
使程序跳过当前循环体剩余部分,直接开始下一次循环迭代。
#include <stdio.h>int main() {for(int i = 0; i < 10; i++) {if(i % 2 == 0) { // Skip even numberscontinue;}printf("%d ", i);}printf("\n");return 0;
}
上面示例中,只要是偶数,就用continue语句跳过该数字,执行下一次循环
3. goto 语句
goto
允许无条件跳转到标记的语句,但在现代编程中不鼓励使用,因为它可能导致代码结构混乱,不易理解,所以这里一笔带过。
#include <stdio.h>int main() {int i = 0;
start:printf("%d ", i);i++;if(i < 5) goto start; // 不推荐使用printf("\n");return 0;
}
尽量避免使用goto
,考虑使用循环或函数替代以提高代码质量。
六,其他控制结构
虽然不是C语言标准库直接提供的流程控制语句,但通过组合基本的流程控制语句,可以实现更复杂的控制结构,如:
- 循环嵌套:一个循环内部包含另一个循环。
- 条件循环:在循环条件中使用逻辑表达式来控制循环的执行。
- 提前返回(return):在函数中使用,可以立即结束函数的执行并返回一个值(对于非void类型函数)。
相关文章:
C语言入门系列:流程控制
一,C代码执行顺序 默认情况下,C语言程序从main()函数开始执行,随后按源代码中语句出现的顺序逐一执行。 这意味着,如果不考虑任何控制结构,程序会自上而下,逐行执行每条语句,直到遇到函数调用…...
【深度学习】NLP,Transformer讲解,代码实战
文章目录 1. 前言2. Transformer结构训练过程1. 输入嵌入和位置编码2. 编码器层2.1 单头的注意力机制(便于理解)2.2 多头的注意力机制(Transformer真实使用的)2.3 残差连接和层归一化2.4 前馈神经网络(FFN)2.5 残差连接和层归一化2.6 总结 3. 解码器层 推…...
ES6 .entries用法
.entries() 返回数组的可迭代对象itarator,可以通过for of 来遍历数组或对象的值。但是它们的写法不一样。 数组用法 obj [apple,bananer,orange] for(let [i,v] of obj.entries()){console.log(i)console.log(v) } //输出 // 0 // apple // 1 // bananer // 2 //orange对象…...
【LeetCode 动态规划】买卖股票的最佳时机问题合集
文章目录 1. 买卖股票的最佳时机含冷冻期 1. 买卖股票的最佳时机含冷冻期 题目链接🔗 🍎题目思路: 🍎题目代码: class Solution { public:int maxProfit(vector<int>& prices) {int n prices.size();ve…...
python学习:语法(2)
目录 对象的布尔值 分支结构 双分支结构 多分支结构 嵌套if的使用 条件表达式 Pass语句 range()函数的使用 流程控制语句 对象的布尔值 Python一切皆对象,所有对象都有一个布尔值,通过内置函数bool()获取对象的布尔值 这些…...
经典电源电路基础(变压-整流-滤波-稳压)
1.电源电路的功能和组成 电子电路中的电源一般是低压直流电,先把220v交流电变换成低压直流电,再用整流电路变成脉动的直流电,最后用滤波电路滤除掉脉动直流中的交流成分后才能得到直流电。有的电子设备对电源的质量要求很高,所以…...
生成式人工智能备案办理指南,深度解析大模型备案全流程
早在2023年年初,国家互联网信息办公室、工业和信息化部、公安部针对深度合成服务制定的《互联网信息服务深度合成管理规定》(“《深度合成管理规定》”)顺利施行,其明确了深度合成服务相关方的义务与主体责任,强化了对…...
1527. 患某种疾病的患者
1527. 患某种疾病的患者 题目链接:1527. 患某种疾病的患者 代码如下: # Write your MySQL query statement below select patient_id,patient_name,conditions from Patients where conditions like "DIAB1%" or conditions like "% DI…...
【C/C++】【学生成绩管理系统】深度剖析
可接各类C/C管理系统课设 目录 实现功能 部分1:系统设置和主菜单 1. 引入头文件 2. 定义结构体 3. 函数声明 4. 主函数 部分2:添加学生信息 部分3:删除学生信息 部分4:修改学生信息 部分5:查询学生信息 部分…...
C++作业第四天
#include <iostream> using namespace std; class Per { private: string name; int age; int *high; double *weight; public: //构造函数 Per() { cout << "Per的无参构造" << endl; } Per(str…...
设计模式之工厂方法模式(Factory Method Pattern)
目录 1.1、前言1.2、工厂方法模式简介1.2.1、工厂方法模式的主要特点1.2.2、工厂方法模式的主要结构1.2.3、使用工厂方法模式的好处 1.3、SpringBoot中那些场景使用了工厂方法模式1.4、日常工作中那些业务场景可以使用工厂方法模式1.5、工厂方法模式实战(以某商场一…...
API接口设计的18条规范
API接口设计的18条规范 签名 目的:防止数据被篡改 实现方法: 接口请求方将请求参数、时间戳和密钥拼接成一个字符串使用MD5等hash算法生成签名sign在请求参数或请求头中增加sign参数,传递给API接口API接口网关服务验证传递的sign值&#…...
adb简单使用命令
1. 查看当前连接的设备 adb devices 2. 文件路径 adb install apk 注意文件路径中不能有中文 3. adb shell ps Toplogcatlogcat可以结合greplogcat *:w 显示警告级别以上de 4. adb uninstall 软件名 1.软件名如何查看? 使用命令adb shell pm list packages会…...
构建 deno/fresh 的 docker 镜像
众所周知, 最近 docker 镜像的使用又出现了新的困难. 但是不怕, 窝们可以使用曲线救国的方法: 自己制作容器镜像 ! 下面以 deno/fresh 举栗, 部署一个简单的应用. 目录 1 创建 deno/fresh 项目2 构建 docker 镜像3 部署和测试4 总结与展望 1 创建 deno/fresh 项目 执行命令…...
数据库 | 数据库设计的步骤
1.需求分析 调查机构情况与熟悉业务活动,明确用户的需求,确定系统的边界,生成数据字典和用户需求规格说明书 2.概念结构设计 将从需求分析中得到的用户需求抽象为概念模型,设计E-R模型 3.逻辑结构设计 将E-R图转换为和DBMS相…...
改进YOLO系列 | CVPR 2021 | Involution:超越convolution和self-attention的神经网络算子
Involution:超越卷积和自注意力的新型神经网络算子(中文综述) 简介 Involuton是CVPR 2021上提出的新型神经网络算子,旨在超越卷积和自注意力,提供更高效、更具表达力的特征提取能力。 Involution原理 Involution的…...
落地速度与效果之争,通用VS垂直,我的观点和预测。
标题:AI大模型战场:通用VS垂直,谁将领跑落地新纪元? 摘要:随着人工智能技术的飞速发展,大模型的应用场景日益广泛。在这场竞赛中,通用大模型和垂直大模型各有优势,落地速度和可能性也…...
【Android面试八股文】在Android中,出现ClassNotFound的有可能的原因是什么?
在Android环境下类未找到的可能原因 在Android环境下,类未找到的可能原因包括但不限于以下几点: 类路径问题:Android应用使用的类通常存储在APK文件中。如果类所在的APK文件没有被正确加载,或者应用的类路径配置有误,就会导致类未找到的错误。 多DEX文件加载问题:在一些…...
模板引擎与 XSS 防御
在 View 层,可以解决 XSS 问题。在本书的“跨站脚本攻击”一章中,阐述了“输入检查” 与“输出编码”这两种方法在 XSS 防御效果上的差异。XSS 攻击是在用户的浏览器上执行的, 其形成过程则是在服务器端页面渲染时,注入了恶意的 H…...
vue3轮播图怎么做
先看效果 实现代码 <n-carouseleffect"card"dot-type"line"draggable:autoplay"!isHovered":current-index"currentIndex"prev-slide-style"transform: translateX(-150%) translateZ(-450px);opacity:1"next-slide-st…...
ubuntu中安装docker并换源
使用 Ubuntu 的仓库安装 Docker sudo apt update现在,你可以使用以下命令在 Ubuntu 中安装 Docker 以及 Docker Compose: sudo apt install docker.io docker-composeDocker 包被命名为 docker.io,因为在 Docker 出现之前就已经存在一个名为…...
HTML静态网页成品作业(HTML+CSS)—— 环保主题介绍网页(5个页面)
🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有5个页面。 二、作品演示 三、代…...
深入了解RSA加密算法
目录 前言 一、什么是RSA? 二、RSA加密的基本概念 1.非对称加密 2.密钥生成 3.加密和解密 三、RSA加密的工作原理 四、RSA的应用场景 五、RSA加密解密的实现 六、RSA算法的局限性及改进措施 前言 在当今的数字化时代,信息的安全性成为了人们关注…...
github基础使用
前言 将用到的github指令记录下来,持续更新,方便随时查找学习。 一、github用到的指令 1、我们从github克隆下来的代码版本一般都是master主分支,我们要建立自己的分支进行修改: //git branch //查看目前的分支/* * master /…...
Docker使用心得
Docker使用心得 最近使用Docker比较频繁,特此想记录一下,方便后续查找。 Docker常用命令Docker如何配置使用GPU环境?如何使用Dockerfile构建镜像?如何使用docker compose 实例化容器? Docker如何配置使用GPU环境 参…...
QListWidget 插入 item,item显示自定义界面
代码示意: class ItemWidget_action_cfg_w(QWidget):... # 如下方法是在指定item下插入新的item def __do_add_item(self, item):# 获取当前item rowrow self.__list_w.indexFromItem(item).row()# 注意这里没有父类,解释见后面说明new_item QList…...
Python写一个ERP系统和agent智能体协同仓库和订单的案例
这是一个关于使用Python编写一个简单的ERP系统,并与Agent智能体协同完成仓库和订单管理的案例。在这个案例中,我们将使用Python的第三方库sqlite3进行数据库操作,以及discord库实现与Agent智能体的通信。 1. 首先,安装所需库&…...
【计算机网络】已解决:“‘ping‘ 不是内部或外部命令,也不是可运行的程序或批处理文件”报错
文章目录 一、问题分析背景二、可能出错的原因三、错误代码示例四、正确解决方法与示例五、注意事项 已解决“‘ping’ 不是内部或外部命令,也不是可运行的程序或批处理文件”报错 一、问题分析背景 在Windows操作系统中,ping 命令是一个常用的网络诊断…...
Web前端学堂:深入探索前端开发的核心领域
Web前端学堂:深入探索前端开发的核心领域 在数字化时代的浪潮中,Web前端开发扮演着至关重要的角色。它不仅是连接用户与互联网世界的桥梁,更是创造丰富、互动网络体验的关键所在。本文将带领读者走进Web前端学堂,从四个方面、五个…...
Java数据结构与算法(0/1背包问题)
前言: 背包问题(Knapsack Problem)是组合优化问题中的一个经典问题,有多个变种。这里我们讨论的是 0/1 背包问题,这是最基本的一种形式。问题的描述如下: 给定 n 件物品,每件物品有一个重量 wi 和一个价值…...
东莞最好的网站建设价格低/广州seo培训
满心热情与兴奋,最后变成了遗憾和伤心。 嗯,还有尴尬。 给61级讲Prim,课件合起来的话大概做了有一天多吧。 虽然没什么东西,但还是很用心地给他们写解释、流程,找例题习题,甚至还给他们出了一道题。 给他们…...
团购网站怎么做推广/百度收录官网
报错:叫我们删除log4j-over-slf4j.jar, 选中项目 然后搜索对应的包,然后排除即可,我这边已经排除了,就ok了 ctrlF搜索哦! 版本问题,使用插件解决吧: https://yidajava.blog.csdn.net/article/details/103668676...
网站建设规划书模板/重庆高端品牌网站建设
题目描述 伦敦奥运会要到了,小鱼在拼命练习游泳准备参加游泳比赛,可怜的小鱼并不知道鱼类是不能参加人类的奥运会的。这一天,小鱼给自己的游泳时间做了精确的计时(本题中的计时都按24小时制计算),它发现自己…...
做三盛石材网站的公司/灰色词排名接单
转载自:https://www.cnblogs.com/bekeyuan123/p/6891875.html 数组的定义: // 3种定义方式int[] arr new int[5];int[] arr1 {1,2,3,4,5};int[] nums new int[]{1, 2, 3};long[] arr2 new long[6];String[] strs new String[5];// 数组可以存储引用…...
专业做网站/电子商务沙盘seo关键词
版权声明:本文为 小异常 原创文章,非商用自由转载-保持署名-注明出处,谢谢! 本文网址:https://blog.csdn.net/sun8112133/article/details/84350216 好久没写博客咯,今天来写一写今天写代码中遇到的一个问题…...
邢台做网站推广报价/杭州龙席网络seo
利用LVSKeepalived 实现高性能高可用负载均衡 背景: 随着你的网站业务量的增长你网站的服务器压力越来越大?需要负载均衡方案!商业的硬件如F5又太贵,你们又是创业型互联公司如何有效节约成本,节省不必要的浪费?同时实现…...