当前位置: 首页 > news >正文

Day5语法:循环-分支语句

目录

  • 1. 语句
  • 2. C 程序结构
  • 3. 分支语句
    • 3.1 if 语句
      • 3.1.1 形式一:单分支 if
      • 3.1.2 形式二:if-else
      • 3.1.3 形式三:if-else if-else
      • 3.1.4 练习
      • 3.1.5 if 语句总结
    • 3.2 switch
      • 3.2.1 语法形式
      • 3.2.2 注意事项
      • 3.2.3 作业
  • 4. 循环语句
    • 4.1 简介
    • 4.2 goto 语句
    • 4.3 while 语句
    • 4.4 do-while 语句
    • 4.5 for 循环
    • 4.6 循环的嵌套
    • 4.7 break 和 continue

1. 语句

C 语言中,语句(指令)就是表达程序员某个操作的意图。语句是 C 程序的基本执行单元,它表示一个完整的操作,每一条语句都是以;结束。语句可以分为单语句复合语句

单语句常见形式:

  • 赋值语句:int a = 10;
  • 函数调用语句:printf("hello world\n");
  • 空语句:;,什么都不做

复合语句是由一对花括号{}括起来的语句块(代码块),可以包含多个语句:

{ a = 22; b = a + 13; c = a + b; // ...... }

常见的流程控制语句包括ifswitchwhiledo whilefor等。C 程序主体由函数组成,函数内部由 C 语句组成。

2. C 程序结构

结构化程序设计提供三种控制结构:

  • 顺序结构:所有语句按照线性顺序执行。
  • 分支结构(选择结构):例如在 A、B 之间做出选择。
  • 循环结构:重复执行指定的语句。

早在 1966 年,就已经证明以上三种基本结构可以构成任意复杂的算法。

3. 分支语句

分支结构(选择结构)用于在多个分支中做出选择。C 语言中的分支语句主要包括if语句和switch语句。

3.1 if 语句

if 语句用于条件判断,满足条件时,就执行指定的语句。if 语句有三种基本形式。

3.1.1 形式一:单分支 if
if(表达式) 语句

如果“表达式”为真(非 0),表示条件成立,则执行后面的“语句”。合法的表达式就一定会有值。常见的表达式有:

  • 算术表达式:a + b
  • 逻辑表达式:a > b
  • 函数调用:sum(a, b)

if 条件成立时,表达式的值为非 0;if 条件不成立时,表达式的值为 0。

分析如下程序的结果:

示例 1:

int a = 3, b = 6; if(a > b) a = 4; // a > b 结果为假,此句没有执行 b = 3; // 执行 printf("a:%d b:%d \n", a, b); // 输出:a:3 b:3

规则:if 语句的作用域仅限于其后面的单条语句。如果希望多条语句被 if 管理,可以使用{}指定:

if(a > b) { a = 4; b = 3; }

示例 2:

int a = 4, b = 3; if(a < b); // 此处有分号 ; 代表一个空语句 a = 5; printf("a: %d\n", a);

编程建议:为了避免上述混乱情况,提高程序可读性,建议不管 if 后面有没有语句,都先加上{}确定范围:

if(xxx) { // 语句块; }
3.1.2 形式二:if-else
if(条件1) { 语句1 } else { 语句2 }

假设条件 1 成立(非 0),则执行对应的语句 1;否则执行语句 2。else 不能单独存在,一定要和一个 if 匹配。

练习:从键盘获取用户输入的一个整数,利用 if-else 语句,判断其是否为偶数。

if(n % 2 == 0) { printf("偶数\n"); } else { printf("奇数\n"); }
3.1.3 形式三:if-else if-else
if(条件1) { 语句1 } else if(条件2) { 语句2 } else if(条件3) { 语句3 } else { // 如果上述条件都不满足,则执行此处 }

这种结构适用于需要按优先级顺序逐个检查的情况。在每个条件后面跟随一个 else if,只有在前一个条件为假时,才会继续检查下一个条件;如果所有的表达式都不成立,则进入 else。

示例:根据学生成绩 score 打出对应的等级分。

if(score >= 90) { printf("A\n"); } else if(score >= 80) { printf("B\n"); } else if(score >= 60) { printf("C\n"); } else { printf("D\n"); }

用户输入 90 分时,仅输出 A。各个条件按照优先级查找,满足条件时执行对应的代码块。

区别于以下写法:

if(score >= 90) { printf("A\n"); } if(score >= 80) { printf("B\n"); } if(score >= 60) { printf("C\n"); } else { printf("D\n"); }

用户输入 90 分时,A、B、C 都会输出。

3.1.4 if 语句总结

1. 并列条件与互斥条件:

// 并列条件 if(条件1) { ... } if(条件2) { ... } if(条件3) { ... } // 互斥条件 if(条件1) { ... } else { ... }

2. if 语句的嵌套:在某个大的条件下再细分条件。在 if 语句中包含一个或者多个 if,称之为 if 嵌套。

if(A) { if(C) { } else if(D) { } else { } } else { }

注意 else 匹配原则:else 总是与它上面最近的、同级的、未配对的 if 语句匹配。

练习:判断从键盘输入的内容是否为字母(A~Z、a~z),如果是小写字母则输出其大写,如果是大写字母则输出其小写。

提示:

  • ASCII 码(虚拟机终端输入man ascii查看,按 q 退出)。
  • scanf("%c", &ch);用于获取输入。
// 获取用户输入,判断是否为字母 char ch; printf("请输入一个字母: ...\n"); scanf("%c", &ch); if((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { printf("输入的字符是字母\n"); // 进一步判断是大写还是小写 if(ch >= 'A' && ch <= 'Z') // 大写 { ch = ch + ('a' - 'A'); // 大写转小写 printf("转换为小写: %c\n", ch); } else if(ch >= 'a' && ch <= 'z') { ch = ch - ('a' - 'A'); // 小写转大写 printf("转换为大写: %c\n", ch); } } else { printf("输入的字符不是字母\n"); }

3.2 switch

switch 用来列举表达式所有可能的情况并进行匹配。

3.2.1 语法形式
switch(表达式) { case 常量表达式1: 语句1 break; // 跳出 case 常量表达式2: 语句2 break; case 常量表达式m: 语句m break; default: // 建议将 default 写在最后 语句 break; }

常量表达式是程序运行期间值不会改变的表达式。例如,下面的 case 写法都是正确的:

#define N 122 switch(num) { case N: // define 在预处理阶段替换,相当于 case 122: case 5: case 'A': case 'z': case 3 + 5: case 'a' + 32: break; }

错误示例:

int a = 3; switch(num) { case a + 1: // 错误:case 后不能使用变量 break; }

switch 让“表达式”和 case 后面的“常量表达式”做匹配。一旦匹配成功(值相等),则从那个 case 后面开始执行,直到遇到 break。如果所有的 case 都没有匹配成功,则匹配 default。

3.2.2 注意事项

1. switch 后面的“表达式”必须是一个可以列举的值,表达式的类型必须是整数值:整型 int、字符型 char、枚举。

int num; switch(num) { // ... }

2. case 后面的“常量表达式”也必须是一个整数值,不能是变量,并且每个 case 后面的常量表达式的值必须不同。

// 正确写法 switch(num) { case 1: break; case 2: break; } // 错误写法:case 1 出现了两次 switch(num) { case 1: // AAAAA break; case 1: // BBBBB break; }

3. 各个 case 和 default 出现的次序不影响匹配结果。一旦匹配成功,就从此处往下执行,直到遇到 break 或者 switch 语句结束。

int a = 5; switch(a) { // default 是所有 case 都不匹配时才会执行 default: ... case 1: ... case 2: ... case 5: a = 20; // 匹配此处并执行 break; // 此处跳出 case 6: ... }

4. “语句”可以省略,多个 case 可以共用一组语句:

switch(a) { case 1: case 2: // a 为 1 或者 2 时都执行此处 ... case 3: ... }

5. switch 中的 break 用来跳出它所属的 switch 语句:

switch(a) { case 1: case 2: ... case 3: break; default: ... }

4. 循环语句

先看一个场景:通过程序实现求 1+2+3+4+5+...+n 的和。

int sum = 0; // 用于保存累加的值 int n = 1; // 要加的数 sum = sum + n; // 0+1 n++; // 1-->2 sum = sum + n; // 1+2 n++; // ...... // 如果求到 n,就需要重复执行 n 次 // ----> 循环

4.1 简介

循环的本质是重复。所有重复的代码,都可以用循环来实现。

在 C 程序中,能够起到循环效果的语句如下:

  • ifgoto构造循环
  • while语句
  • do while语句
  • for语句

其中ifgoto并不算严格意义上的循环语句,只是起到循环效果。

4.2 goto 语句

goto语句可以让 CPU 跳转到指定位置执行,是一种无条件跳转语句。

goto 行标识;

“行标识”用于标识一行代码,需要符合 C 语言标识符的命名规则:由字母、数字、下划线组成,不能以数字开头,不能和关键字冲突。本质上它就代表了一个地址。

loop: sum = sum + n; n++; goto loop;

通过 goto 实现十次循环,打印 1-10:

int main() { int n = 1; loop: printf("loop: n %d\n", n); n++; if(n <= 10) { goto loop; } printf("loop end\n"); return 0; }

注意:goto 类似于汇编代码的无条件跳转,通常被认为是不好的编程风格,会让代码难以调试和阅读,因此平时尽量不要使用 goto 来做循环。

4.3 while 语句

while(表达式) { // 语句块 }

当“表达式”的值为真(非 0)时,执行“语句块”,然后跳回 while 处继续判断,如此重复,直到“表达式”的值为假(0)为止。

“表达式”可以是任意合法的 C 表达式,只要有值。“语句块”是循环体,是重复执行的部分,可以是单语句,也可以是复合语句。

int sum = 0; int i = 1; while(i <= 100) sum += i; i++; // 此句不会参与循环

编程建议:不管 while 后面有没有语句,都先加上大括号{}确定范围:

while(xxx) { // 要循环的内容 }

练习 1:逆序输出一个 3 位正整数。输入 123,输出 321。

int main() { int a = 0; // 用于获取用户输入的数 int d = 0; // 用于存储每一个位 printf("请输入一个三位的正整数\n"); scanf("%d", &a); // a 不为 0 则继续循环 while(a) { d = a % 10; // 取出末位 printf("%d", d); // 打印末位 a = a / 10; // 处理剩余位数 } return 0; }

练习 2:求 100 以内 3 的倍数的和。

int main() { int n = 1; // 表示 100 以内的某个数 int sum = 0; // 用于累计它们的和 while(n <= 100) { if(n % 3 == 0) { sum += n; } n++; } printf("sum :%d\n", sum); return 0; }

4.4 do-while 语句

do // 语句 while(表达式);

程序先执行“语句”,然后再判断“表达式”的值。当值为真(非 0)时,跳转到上面继续执行“语句”,如此重复,直到“表达式”的值为假(0)为止。

翻译成 goto 语句:

loop: 语句 t = 表达式; if(t) { goto loop; }

示例:

int i = 0; int sum = 0; do i++; sum += i; while(i < 100); printf("sum %d\n", sum);

如果 do 后面不加花括号,上述代码会报错:error: expected ‘while’ before ‘sum’。应改成:

int i = 0; int sum = 0; do { i++; sum += i; } while(i < 100); printf("sum %d\n", sum);

编程建议:使用 do-while 时,先给 do 后打一对{}确定范围:

do { } while();

while 和 do-while 的区别主要在于条件判断的时机:while 在每次循环开始前判断,do-while 在每次循环结束后判断。如果希望至少执行一次循环,可以使用 do-while;如果希望每次开始前先判断,可以使用 while。

特殊示例 do while(0):遇到复杂逻辑需要分步提前退出时,可以尝试使用 do-while(0)。

int a = 0, b = 0, c = 0; // 用于存储边长 scanf("%d%d%d", &a, &b, &c); do { if(a + b < c) { printf("no\n"); break; } if(a + c < b) { printf("no\n"); break; } if(b + c < a) { printf("no\n"); break; } // 当上述任意一个条件不满足时,会提前 break 退出 printf("最终: 满足三角形要求\n"); } while(0);

4.5 for 循环

for(initialization; continuation; action) { statement; }

其中 initialization 是初始化表达式,用于初始化循环变量,只执行一次;continuation 是判断表达式,只要为真就会不断执行循环体;action 是循环变量处理表达式,每轮循环结束后执行,使得循环变量产生变化。

更常见的形式:

for(表达式1; 表达式2; 表达式3) { 语句 }

先执行一次表达式 1,然后判断表达式 2 的值;如果为真,执行语句,再执行表达式 3,如此重复,直到表达式 2 为假。

三个表达式都可以省略,但两个分号不能省略:

for( ; ; ) { // 如果表达式 2 省略,表示 for 循环的执行条件永远为真 }

for 和 while 的区别:一般来说 while 更注重循环条件,for 更注重循环次数,两者可以互相替换。

练习:求“水仙花数”。水仙花数是三位数(100-999),且个位、十位、百位的立方和等于其本身。

int x = 100; int a, b, c; // 表示 x 的每一位 for(x = 100; x <= 999; x++) { a = x % 10; // 个位 b = (x / 10) % 10; // 十位 c = x / 100 % 10; // 百位 if((a * a * a + b * b * b + c * c * c) == x) { printf("找到水仙花数: %d\n", x); } }

附:C 中使用pow做幂运算:

double pow(double x, double y); int a = 3; // 例如求 3 的 4 次方 printf("%.0f\n", pow((double)a, 4.0)); // 在 Ubuntu 中使用 gcc 编译时需要连接 -lm // gcc 1.c -lm

4.6 循环的嵌套

示例:打印 3 行 6 列全为 0 的矩阵。

for(int j = 0; j < 3; j++) { for(int i = 0; i < 6; i++) { printf("0 "); } printf("\n"); }

4.7 break 和 continue

break跳出当前的循环或 switch 语句;continue结束本次循环,继续下一次循环。

示例 1:continue

int i = 10; int sum = 0; while(i--) { if(i > 5) { continue; sum += i; // 不会执行到此处 } else { sum += i; } } printf("sum %d\n", sum); // 5+4+3+2+1

示例 2:break

int i = 10; int sum = 0; while(i--) { if(i > 5) break; // 直接跳出整个 while 循环 else sum += i; } printf("sum %d\n", sum); // 0
http://www.jsqmd.com/news/1402927/

相关文章:

  • 南宁防水修缮品牌怎么选?漏水维修科普、避坑与靠谱服务商参考 - 收录优先
  • PCB镀铜均匀性怎么做?工程师揭秘关键工艺
  • 停车场道闸系统选购避坑指南:选对设备,大幅降低后期运维难题
  • 纯WINDOWS API的C++2D小游戏Subterra(目前还未开发,实时更新)
  • 从PID到模型预测:管道小球摆杆控制的核心难点与工程实现
  • Linux vsftpd匿名FTP服务器搭建:安全配置与被动模式故障排查
  • OpenClaw像素风赛博办公室:AI Agent工作流可视化与实时监控实践
  • 华为eNSP设备启动失败:从虚拟化冲突到权限配置的完整排错指南
  • 工业陶瓷零件的材料选型与精度控制:从氧化锆到氮化硅的几个技术点
  • 【无标题】买房收房别只看颜值,这些坑你根本看不见 在本地房产交易活跃的当下,越来越多人意识到:房子表面光鲜不代表住得安心。尤其是二手房翻新或精装交付,墙面平整、地板漂亮背后,可能藏着水电隐患、防水失效
  • Quartus内置ModelSim‑Altera报错Error: Failure to obtain a Verilog simulation license. Unable to checkout
  • Cursor 修复循环校验翻车:3次追问后账单超预算200%,我这样设熔断
  • 居家如何养护艾草暖宫精油日常养护感受海艾独有的温润体感
  • PDF 临时处理总要四处找工具?常用操作放进一个工具箱
  • 脱皮腰果色选怎样减少黑斑、碎仁与异色料混入
  • 上海市口碑好的防水补漏维修公司怎么找_屋面防水本地维修队伍水准盘点,挑选要点深度剖析 - 雨婺虹修缮
  • 网络安全入门:小白必学的极简框架与实战指南
  • OpenClaw部署运维指南:从安装到稳定运行的AI智能体实践
  • Windows鼠标异常唤醒电脑的排查与解决全攻略
  • IDEA代码报红但能运行?深度解析索引缓存机制与系统化解决方案
  • Java枚举类深度解析:从常量管理到状态机设计的实战指南
  • Linux 服务器测速工具:speedtest‑cli 命令完整详解(命令行网速测试实战)
  • 40岁适合做什么创业项目?
  • 找个大佬带带我
  • 标书销毁怎么做?这几种方式最靠谱 - 生态测评师
  • RAG 召回率 95% 仍答错:Anthropic 重排机制差点让我交差一份科幻小说
  • 空地协同巡线系统:从仿真到实战的嵌入式与机器人视觉开发指南
  • 彻底解决Maven依赖爆红:从诊断到根治的系统化指南
  • Object.hasOwn 兼容性解析:从原理到工程化解决方案
  • 芯片ESD测试仪是什么?主要有哪几种不同类型?