C 语言 —— 循环结构
C语言有3种循环:while、do while、for。
为什么要用循环结构?
现在我们有这样一个需求,想要打印一个如下所示的图形:
#
##
###
####
#####
用我们之前学习的方法来实现,代码如下:
printf("#\n");
printf("##\n");
printf("###\n");
printf("####\n");
printf("#####\n");
按照以前学习的方法很容易打印出上面要求的图形,但是我们可以看到,其实这个过程没啥技术含量,完全是复制粘贴,然后在 printf 语句中添加一个 ‘#’,如果现在要我们打印 100 行的图形,难道还要一行一行的添加吗?即使你不嫌麻烦地写了 100 行代码,现在需求编程了打印 10000 行,你还要一行一行的写吗?
循环结构就为我们提供了解决这样的问题的方法。
while 循环
1. 简介
我们来学习一下 while 循环。在学习之前,再体会一下不使用循环的局限性。
#include <stdio.h>
#define ADJUST 7.31 // 字符常量
int main(void)
{const double SCALE = 0.333;// const变量 double shoe, foot; shoe = 9.0; foot = SCALE * shoe + ADJUST; printf("Shoe size (men's) foot length\n"); printf("%10.1f %15.2f inches\n", shoe, foot); return 0;
}
上面的代码实现了将鞋码转换成英寸的功能,程序使用了乘法和加法,假定用户穿 9 码的鞋,以英寸为单位打印用户的脚长。你可能会说:“这太简单了,我用笔算比敲程序还要快。”说得没错。写出来的程序只使用一次(本例即只根据一只鞋的尺码计算一次脚长),实在是浪费时间和精力。如果写成交互式程序会更有用,但是仍无法利用计算机的优势。
计算机的优势就在于做一些重复计算的工作,我们使用 while 循环改进后的程序:
#include <stdio.h>
#define ADJUST 7.31 // 字符常量
int main(void)
{const double SCALE = 0.333;// const变量 double shoe, foot; printf("Shoe size (men's) foot length\n"); shoe = 3.0;while (shoe < 18.5) /* while循环开始 */ { /* 块开始 */ foot = SCALE * shoe + ADJUST; printf("%10.1f %15.2f inches\n", shoe, foot); shoe = shoe + 1.0; } /* 块结束 */ printf("If the shoe fits, wear it.\n"); return 0;
}
下面是shoes2.c程序的输出(…表示并未显示完整,有删节):
Shoe size (men’s) foot length
3.0 8.31 inches
4.0 8.64 inches
5.0 8.97 inches
6.0 9.31 inches
…
16.0 12.64 inches
17.0 12.97 inches
18.0 13.30 inches
If the shoe fits, wear it.
下面解释一下while循环的原理。当程序第 1 次到达 while 循环时,会检查圆括号中的条件是否为真。该程序中,条件表达式是:shoe < 18.5
。变量 shoe 被初始化为 3.0,显然小于 18.5。因此,该条件为真,程序进入块中继续执行,把尺码转换成英寸。然后打印计算的结果。下一条语句把 shoe 增加 1.0,使 shoe 的值为 4.0: shoe = shoe + 1.0;
此时,程序返回 while 入口检查条件。
为何要返回 while 的入口部分?因为上面这条语句的下面是右花括号(}),代码使用一对花括号({})来标出 while 循环的范围。花括号之间的内容就是要被重复执行的内容。 花括号以及被花括号括起来的部分被称为块(block)。
现在,回到程序中。因为 4 小于 18.5,所以要重复执行被花括号括起来的所有内容(用计算机术语来说就是,程序循环这些语句)。该循环过程一直持续到 shoe 的值为 19.0。此时,由于 19.0 小于 18.5,所以该条件为假:
shoe < 18.5
出现这种情况后,控制转到紧跟 while 循环后面的第 1 条语句。该例中,是最后的 printf() 语句。
可以很方便地修改该程序用于其他转换。例如,把 SCALE 设置成 1.8、ADJUST 设置成 32.0,该程序便可把摄氏温度转换成华氏温度;把 SCALE 设置成 0.6214、ADJUST 设置成 0,该程序便可把公里转换成英里。注意,修改了设置后,还要更改打印的消息,以免前后表述不一。
2. while 语句
while 语句常用格式:
while(循环条件表达式)
{循环执行的语句;循环条件更新;
}
写 while 循环的时候最重要的一点就是更新循环条件,否则,循环就不会停止,我们称之为死循环。(PS:事实上,不更新循环条件,也是可以通过 if 语句和 break 来终止循环的,这个在之后会讲,目前我们还只能通过更新循环条件,让循环条件表达式结果为假来终止循环)
考虑下面的例子:
int i = 1;
while(i <= 5)
{printf("%d\n", i);
}
上面的程序段将打印无数次 1。为什么?因为循环中 i 的值一直都是原来的值 1,不曾变过。现在,考虑下面的程序段:
int i = 1;
while(--i <= 5)
{printf("%d\n", i);
}
这段程序也好不到哪里去。虽然改变了 i 的值,但是改错了!不过,这个版本至少在 i 减少到其类型到可容纳的最小负值并变成最大正值时会终止循环。
3. C 风格的读取循环
int num;
while (scanf("%d", &num) == 1)
{/*循环行为*/
}
上面的代码同时使用 scanf() 的两种不同的特性。首先,如果函数调用成功,scanf() 会把一个值存入 num。然后,利用 scanf() 的返回值(0或1,不是 num 的值)控制 while 循环。因为每次迭代都会判断循环的条件,所以每次迭代都要调用 scanf() 读取新的 num 值来做判断。换句话说,C 的语法特性让你可以用下面的精简版本替换标准版本: 当获取值和判断值都成功,处理该值。
利用 C 语言中非零值为真的特性,可以进一步精简,将循环条件表达式中的 == 1 省略。
int num;
while (scanf("%d", &num))
{/*循环行为*/
}
4. 小测验
判断下面的几段代码是否存在问题?
代码1:
int i = 0;
while(i = 3)
{printf("hello\n");i++;
}
答案:有问题,循环测试条件是一个赋值语句,而不是关系表达式,因此测试条件 i = 3
的值一直是 3,因此循环会一直进行,是死循环。应该将 i = 3
修改为 i == 3
或者 i < 3
。
代码2:
int i = 0;
while(i = 0)
{printf("hello\n");i++;
}
答案:不会出现死循环,并且循环语句永远不会被执行。因为循环条件表达式中赋值语句的值是 0,while 判断是假,不执行循环语句。
不确定循环和计数循环
一些 while 循环是不确定循环(indefinite loop)。所谓不确定循环,指在测试表达式为假之前,预先不知道要执行多少次循环。例如,C 风格的读取循环。我们事先并不知道用户会结束输入整数。另外,还有一类是计数循环(counting loop)。这类循环在执行循环之前就知道要重复执行多少次。下面的代码就是一个简单的计数循环。
#include <stdio.h>
int main(void)
{const int NUMBER = 22; int count = 1; // 初始化 while (count <= NUMBER) // 测试 {printf("Be my Valentine!\n"); // 行为 count++; // 更新计数 }return 0;
}
虽然上面的代码运行情况良好,但是定义循环的行为并未组织在一起,程序的编排并不是很理想。我们来仔细分析一下。
在创建一个重复执行固定次数的循环中涉及了3个行为:
- 必须初始化计数器;
- 计数器与有限的值作比较;
- 每次循环时递增计数器。
while 循环的测试条件执行比较,递增运算符执行递增。代码中,递增发生在循环的末尾,这可以防止不小心漏掉递增。因此,这样做比将测试和更新组合放在一起(即使用 count++ <= NUMBER)要好,但是计数器的初始化放在循环外,就有可能忘记初始化。实践告诉我们可能会发生的事情终究会发生,所以我们来学习另一种控制语句 —— for 循环,可以避免这些问题。
for 循环
学习过 while 循环,我们再来接触一下 C 语言的另一种循环:for 循环。for 循环把上述3个行为(初始化、测试和更新)组合在一处。
#include <stdio.h>
int main(void)
{const int NUMBER = 22; for (int count = 1; count <= NUMBER; count++) printf("Be my Valentine!\n"); return 0;
}
for 语句
for 语句常用格式:
for(初始化语句;循环条件表达式;表达式更新)
{/*循环语句*/
}
关键字 for 后面的圆括号中有3个表达式,分别用两个分号隔开。第 1 个表达式是初始化,只会在 for 循环开始时执行一次。第 2 个表达式是测试条件,在执行循环之前对表达式求值。如果表达式为假时,循环结束。第 3 个表达式执行更新,在每次循环结束时求值。
for 圆括号中的表达式也叫做控制表达式,它们都是完整表达式,所以每个表达式的副作用(如,递增变量)都发生在对下一个表达式求值之前。
对于计数循环,for 循环的第一行包括了循环所需的所有信息:初始值,终值,每次循环的增量。
for 语句的灵活性
for 循环中的三个表达式给予了 for 循环对于计数循环很强的灵活性。
- 除了计数器递增,还可以使用递减运算符来递减计数器。
for (secs = 5; secs > 0; secs--)
- 可以让计数器每次递增、递减指定长度的增量,而不只是 1。
for (n = 2; n < 60; n = n + 13)
- 可以用字符代替数字计数。
for (ch = 'a'; ch <= 'z'; ch++)
- 除了测试迭代次数之外,还可以测试其他条件。
for (num = 1; num*num*num <= 216; num++)
- 可以让递增的量几何增长,而不是算术增长。
for (debt = 100.0; debt < 150.0; debt = debt * 1.1)
- 第3个表达式可以使用任意合法的表达式。无论是什么表达式,每次迭代都会更新该表达式的值。
for (x = 1; y <= 75; y = (++x * 5) + 50)
- 可以省略一个或多个表达式(但是不能省略分号),只要在循环中包含能结束循环的语句即可。
for (n = 3; ans <= 25;) // 更新表达式放在了{}中
- 循环体中的行为可以改变循环头中的表达式。
do while 循环
while 循环和 for 循环都是入口循环,即在循环的每次迭代之前检查测试条件,所以有可能根本不执行循环体中的内容。而 do while 循环是出口循环,即在循环的每次迭代之后检查测试条件,这保证了至少执行循环体中的内容一次。
#include <stdio.h>
int main(void)
{const int secret_code = 13; int code_entered; do{printf("To enter the triskaidekaphobia therapy club,\n"); printf("please enter the secret code number: "); scanf("%d", &code_entered); } while (code_entered != secret_code); printf("Congratulations! You are cured!\n"); return 0;
}
下面是do while循环的通用形式:
dostatement
while ( expression );
如何选择循环
如何选择循环?
首先,确定是需要入口条件循环还是出口条件循环。通常,入口条件循环用得比较多。有几个原因,其一,一般原则是在执行循环之前测试条件比较好。其二,测试放在循环的开头,程序的可读性更高。其三,在许多应用中,要求在一开始不满足测试条件时就直接跳过整个循环。因此,我们通常是 while 循环和 for 循环中选择一个。
那么,到底是选择 while 循环还是 for 循环?这取决于个人喜好,因为二者皆可,要让 for 循环看起来像 while 循环,直接将第一个表达式和第三个表达式省略即可。要让 while 循环像 for 循环,直接在 while 前面初始化变量,在 while 循环体中包含更新语句。
一般而言,当循环涉及初始化和更新变量时(例如计数循环),用 for 循环比较合适,而在其他情况下用 while 循环更好。
嵌套循环
还记得我们刚开始的打印图形的例子吗?
#
##
###
####
#####
我们用之前学习的循环结构可以打印指定数目的 ‘#’ 字符了。
for(int i = 0; i < n; i++)printf("#");
其中 n 是指定打印几个 ‘#’ 字符。
如果想要打印上面指定的图形,就需要用到嵌套循环了。
int i = 0, j = 0;
int n = 5;
while(i < n)
{j = 0;while(j <= i){printf("#");j++;}printf("\n");i++;
}
如果我们想要打印 100 行图形,只需要将 n 修改为 100 即可。
C 语言 —— 循环结构相关推荐
- c语言中循环结构的作用,C语言循环结构知识点
C语言循环结构知识点 引导语:循环结构可以减少源程序重复书写的工作量,用来描述重复执行某段算法的问题,这是程序设计中最能发挥计算机特长的程序结构.以下是百分网小编分享给大家的C语言循环结构知识点,欢迎 ...
- 循环结构作业c语言,c语言循环结构练习题带答案
c语言循环结构练习题带答案 第5章 循环结构程序设计 5.1 基本知识点 Øwhile语句的使用格式和注意事项 Ødo-while语句的使用格式和注意事项 Øfor语句的使用格式和注意事项 Øbrea ...
- 循环结构作业c语言,C语言循环结构练习题带答案(最新整理)
<C语言循环结构练习题带答案(最新整理)>由会员分享,可在线阅读,更多相关<C语言循环结构练习题带答案(最新整理)(10页珍藏版)>请在人人文库网上搜索. 1.第 5 章循环结 ...
- 一起学习C语言:C语言循环结构(三)
上一篇 <一起学习C语言:C语言循环结构(二)> 中,我们了解了while.do-while语法和continue语句的应用场景.本篇文章中,我们分析循环结构嵌套使用,并通过几个示例分析c ...
- 一起学习C语言:C语言循环结构(二)
前言: 前一段时间发表的<["天才"必经之路]>文章非常热门,虽然我知道它会是一篇成功的文章,但,它的火爆程度还是超出了我的预期.前几日,我写了这个系列的第二篇文章,文 ...
- 一起学习C语言:C语言循环结构(一)
上一章 <一起学习C语言:C语言基本语法> 系列内容中,我们了解了if语句.switch语句的使用方式以及不同运算符的优先级等内容.本章节,我们学习C语言循环结构用法. 章节预览: 1. ...
- c语言构成循环结构的是,C语言循环结构选择题
计算机二级的资料 C语言循环结构选择题 1.在C语言中,下列说明正确的是 A) 不能使用 do-while构成的循环 B) do-while构成的循环必须用break才能退出 C) do-while构 ...
- 加法接力赛C语言算法,C语言循环结构
<C语言循环结构>由会员分享,可在线阅读,更多相关<C语言循环结构(47页珍藏版)>请在人人文库网上搜索. 1.UML和需求建模,第六章,循环控制,UML和需求建模,主要内容, ...
- c语言循环上机题,c语言循环结构上机习题
c语言循环结构上机习题 下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览.不比对内容而直接下载带来的问题本站不予受理. 2.下载的文档,不会出现我们的网址水印. 3.该文档所得收入 ...
- c语言break习题,C语言循环结构练习题.doc
C语言循环结构练习题C语言循环结构练习题 第5章 循环结构程序设计 5.1 基本知识点 (while语句的使用格式和注意事项 (do-while语句的使用格式和注意事项 (for语句的使用格式和注意事 ...
最新文章
- 巧用360加快您的开机速度
- 多倍体单体型组装算法研究
- CLOUD 04:zookeeper,kafka,hadoop高可用
- 青岛市教师职称计算机考试成绩查询系统,吴春雷
- 2021-07-03
- 部署LAMP论坛平台(Linux,Apache,MySQL,PHP)
- IDC关于使用JBoss Fuse的商业价值的报告(与Apache Camel一起使用)
- Qt|OpenGL-天空盒子的创建
- Python | 多种编码文件(中文)乱码问题解决
- 【VMCloud云平台】SCSM(六)SCSM创建服务
- andriod环境搭建
- git的基本使用和多人协作合并管理
- 文档流、脱离文档流分析
- STS热部署,springboot项目中修改代码不用重新启动服务
- 为什么计算机连不上无线网络,电脑总是连不上无线怎么回事
- 超酷炫技:10 个牛逼的单行代码编程技巧
- 2021全网最全接口测试及常用接口测试工具
- TCP/IP协议栈Lwip的设计与实现:之三
- Bluetooth技术学习笔记 ——蓝牙核心系统架构
- 审批流程设计方案-介绍(一)
热门文章
- 计算机信息计量单位G的单位,计算机中的有些计量单位例如G、MB是表示什么意思?...
- FileUriExposedException: file:////XXXXXXXX g exposed beyond app through ClipData.Item.getUri()问题的解决
- 解决Android Studio Gradle慢的方法
- Perseus-BERT——业内性能极致优化的BERT训练方案【阿里云弹性人工智能】 1
- 二叉树的深度和广度优先
- Hackthebox靶场连接
- mac如何打开php文件夹,苹果Mac系统怎么打开隐藏文件夹Library?_苹果MA
- composer设置镜像
- 21考研:你是为了什么考研?
- python画柱形图显示数值_python画柱状图--不同颜色并显示数值的方法