当前课程知识点:C/C++:从基础语法到优化策略 > Final Exam > Final exam > 3.2 for loop
返回《C/C++:从基础语法到优化策略》慕课在线视频课程列表
我们这一部分来讲一讲 for 循环
为什么要有循环这个东西
是因为我们计算机的任务里面很多东西事情是要重复去做
所以我们可以用循环来完成
而且刚才我说的这些重复的动作很多时候是几乎相同的
而且很多的任务我们都有这样的流程
就是我们可以用循环来做
那么我们来看一个简单例子
for循环的例子
这里面呢 就会用到前面我们讲的++这个操作符
我们来看 forloop.cpp
我们来看这里面的
代码我们首先定义一个变量 i
我个人倾向把 i 定义在这里
把前面就可以删掉
前面可以删掉
他们有什么区别呢 以后我们来讲
那么我们来看在这里呢
我们定义那个循环 for
for 的话这个括号里面是他的
第一个是初始化 第二个是test 第二项上面写的
第三项是update
然后这个里面从0开始一直循环到5
i 每次加 1 那么就会循环 5 次
每次他就会打印这个字符串
那也就是说 这个字符串将会打印五次
打印完之后呢 第六次打印就是这个循环就结束了
就是再打一个其他字符串
同时这个地方实际上是可以加一个花括号的
这个地方可以加个花括号把它包起来
如果你的这个循环体只有一行的话
你可以不用加这个花括号
这两个是没有区别的
当然这个地方空一行也没区别
只不过是不漂亮 我们改一下
那么我们来看编译一下 forloop.cpp
然后运行一下 那么就是打印了五次
就是这个循环
循环他的这个语法定义就是for循环的语法定义是这样的
for后面加这个括号
括号里面用分号分三段
第一段是初始化 他会做一些初始化的动作
像刚才我们就是对 i 进行赋值
而且赋成 0 这个初始化你可以把它视为不存在还是可以
你只要写个分号 前面是空着是没问题就不做初始化
第二部分是这个test-expression
就是来条件判断
就是判断一下这个条件是不是成立
如果成立就去执行body
如果不成立就退出循环
那么
最后一段呢就是update-expression 就说
每次他去做什么
就是条件成立之后他要做什么
他会再做一次 update
也就是我们再回到刚才这个代码来看
我们首先去初始化了 i = 0 这是第一步
然后就开始做这件事情
做打印这件操作
什么时候才做
条件满足的时候
什么叫条件满足
就是这个表达式是true的时候
那第一 0是true 对吧
一次
一是就做完零之后 然后 i 就会增量就会被加一
然后1234一直做到四
做到四的时候
然后还是成立的
再来一次五 当 i 等于五的时候
这个地方就不会来执行了 就结束了
那么在这儿我有一个问题
如果我在这边print i
用cout
这个地方 i 应该等于几
i 应该等于几
第一次是 0 还是 1 呢
就是先做这个操作 加法操作
还是先进来把这个循环体执行了才去做呢
当然 这个地方有两行代码了
所以说你就要花号把它包起来
那这个地方是从12他会打印出12345还是01234呢
我们来看一看
i等于零 i=1 i =2 =3 =4
也就是说明他循环体执行完之后
才去执行这个update操作
那么下一个问题是
如果我把这个打印在这会怎么样
那他的值是多少呢
打印的这他的值是多少
我们来编译一下看一看
编译出错
error: use of undeclared identifier 'i;
就是说 这个i变量没有定义
我不是在这定义了吗
这定义的它的有效范围作用域
只是在这个花括号里面
他不会到花括号外面去
如果你要想要了解到 i 的话
你如果想要知道 i 在循环体外面的值是多少
有的时候你可能循环了多少次
你想知道在循环体外想知道它循环了多少次
那我们就可以这样打印出来
那就这样
你刚才我手误多写了一个分号
其实这个分号写上去和没写上去 结果是一样的
好我们来看
所以说循环体结束之后
整个五次循环结束之后
i的值就会变成了5
这个地方i的s值是5这是这个
好 这是这个for 循环
for循环里面呢
我们刚才用的是++ 同样我们可以用--
也就是说
我们来看这个例子 这个例子
这个循环里面
这个循环是这样的
我们来看一下代码
先让你输入一个整数
输入一个数值
这个只是个整数
这个整数是limit
然后我们把limit赋给 i 初始化
初始化之后条件是 i
这条件是 i 是什么意思
如果他是true话
如果他是true的话
那就循环持续做
那么什么时候 i 是true呢
其实还只要 i 不等于零 不管正与负都是true
就非零值 当 i 非零的时候
这样 i--
然后 i-- 就是说他每次循环
他要做一次减法 做一次减法
然后把这个打印出来
这个时候我们来看
那么这个程序 我们编译一下num_test.cpp
然后运行比如说
他让我输一个整数 那我输个4吧
4的话 它首先它的值是四对吧
limit是4然后3 2 1
零会不会做零条件不满足那肯定不会打印出来对吧
然后就结束了
结束之后这个地方他在说你还是零就会打印出来 应该是这样
结果是这样 i 等于4321
结束循环体之后 i 变成零
因为这个 i-- 起作用了
这个地方不管是 i-- 还是 --i 都是没有区别的
完全相同他们的效果是完全相同的
因为这里没有赋值
那么我们刚才这个程序我们再运行一下
如果我不小心输入了一个负数 -2 会怎么办
大家可以按这个逻辑
首先 i 是 -2 这边没有说必须输入正数吧
那么负二就会赋给limit i 等于-2 -2是0吗 不是
所以循环执行 i--
那就是变成什么-3 -3循环过来还不是0
那就一直循环循环循环循环一直在循环
是这样吗我们来看
这就变成死循环吗 这个循环
至少这个循环的次数会远超你的预期远超你的预期
他还在运行
所以说写循环的时候要特别的小心
你要防止这个条件失效
防止这个条件失效
一旦你这个条件失效了 那你就糟糕了
怎么办呢 我先把它杀死吧
他还在运行 他一直要运行
大家可以算一算一直减减减下去
最后i会什么时候会变成零会不会变成零
还要多久才能停下来
我不等他了杀死他
好这个是这个例子
还有呢 就是在C++11标准里面11标准里面
有一个新的写法loop for 循环的 有个新的写法
那么他就用了一个冒号就是他没有三段
这样的话就其实他是为了避免这样的问题发生
就是说你有多少个元素那你去做多少
我们来看看这个例子
这个例子里面我们来看
我们来看
这个例子里面 我们先定一个数组
这个数组里面有五个元素
有五个double的数值
如果我们想要把这五个数打印出来
那么我们按照前面的语法就是int i=0 i < 5 i++
这样的话 就可以把这个下面的值打印出来
那就等这样来打印
我来打印出来吧
那打印它的值分别是
prices[i]取第 i 个元素
然后这样就可以把这个打印出来了
但是这里面就是一个很容易犯错的地方
因为你可能这个地方不小心手一抖写成了个15
那就出问题了就出问题了
这个打印会出问题 因为会越界
我们来看把下面注释掉
就这个吧
那么就整个来说 它只有五个元素就会越界
还有有可能你不小心把这个循环写成刚才那个负数了
然后写错了
那循环就变成了有可能是变成死循环永远跳不出来
如果你写错了条件那这个时候我们来看看这个
运行
这个结果好像打印了15次
那么第一是四十六点 前面这个五个值是对的
那么第六个值是一些很乱的数 很乱的数
那么这些值是多少呢
为什么会打印出来 是因为C和C++加语言的话
你对这种数组越界不会进行检查
他会继续往后面去取后面那块内存里有什么他就取什么
就把它取过来
所以说会出来一些乱七八糟的数我们再来运行一下
我们来看刚才的话
第六个值是一点四乘以十的-266次方
在这儿第二次运行 它的值又变了
所以说这个值是不稳定的
但是这个程序从编译到运行 他并没有给你报一丝的bug
一切看上去正常 但只是这个值不对
所以说在这种情况下 一旦数组越界你是很难去debug的
很难去debug的
所以说为了让大家少犯错
c11里面定义的这个标准
我要把这个注释取消掉
定义了这个规则 double x : prices 这个是个数组的话
那么也就是他的意思就是从prices里面把他的元素取出来
赋给x 然后我要打印出来 把他打印出来
那么在这种情况下
他就不会产生越界的行为 越界的行为
那么我们就可以这个打印的结果 那就按
很明显啊 我们这就不掩饰了
我们来看下一个例子 下一个例子跟上一个例子类似
唯一不同的时候 这加了个&符号
那他表示什么呢 这个知识点我们后面会讲
在这里稍微提醒一下 他表示引用
引用就是说在这里 他是个赋值
他会把第0个元素拷贝出来赋给x
那么如果你对x做的修改是不影响这里面的数值的
那么在这里面呢 它是一个引用 它直接引用数组里面的第 i 个元素
那么如果你对这个s进行修改
它就会修改数组里面的值
也就是说它只有一份拷贝
这个地方它有两份拷贝
变量x和数组里面的值
这里面只有一份 x 指向了这个数组里面的值
所以呢
在这你如果是i乘以0.8打八折
然后x乘以0.8再付给x的话
那么这个时候你会看x值
就会打了八折
原来数组里面的这个值
数组里面的值也会被打折
为什么这个值 那是第几个 我们在这定一个变量i++
那么就是 i=0 的时候
那么它会取出第几个元素来取出第零个元素来
prices[0]先刚才++我们讲的
先取他的值他的赋值操作他的值就是零
零取完之后再加一所以说会把这个第零个取出来
我们来看是不是打八折
这儿也会打八折我们来看是不是这样的
warning这有两个warning也说他说这个是C++11的这个标准
然后警告 那么我们怎么办
加上这个也可以运行 没有问题的
你最好把这个警告去掉
按这个c++11标准 那他编译就不会有有问题了
出来了
我们来看这里面有两个for循环
第一个for循环的值跟这里是一样的
第二个for循环我们看全部打八折x被打八折
因为x跟数组里面值是一样的
所以说这个数组被修改了被修改了
如果你可以自己去测一下
如果你把这个&符号去掉
这也可以去掉 就这样的
你会发现还会不会被修改 我们再来看一下
我们来看 这x被打八折 但数组没有被修改
这是他们的区别这个地方
所以说大家要理解好这个
这个点 我们后面还会讲 后面还会讲 大家可以提前预习一下
好了
还有呢 我们这儿来介绍一个更复杂的例子 更复杂的例子
这个例子呢 就是说
我们学过这个阶乘 阶乘就是0乘以1乘以2乘以3
n的阶层就是从1一直乘到n它的乘法
那么对于零来讲
零的阶层我们就定义为1
剩下的那么就是累乘起来就是了
我们看如果要实现这样的一个
这个什么 我们可以怎么做
在这儿
这个复杂一点点
首先我们先定一个数组 它的长度是16
它的类型是long long 我们全部就说我们这个来存这个结果 存这个结果
我们来看来看 我们要算16的阶乘 假如 16
应该是15的阶层 那么它的0的阶乘那就是1
1的阶乘呢 也是1
0和1我们先初始化它
这种两个等号连起来写也是赋值
把这个1赋给0
0数组和1数组
然后呢从2数组开始就开始怎么办
那么2数组就是2这个数组等于当前的2乘以上一个阶乘的结果就是1
这里面1其实我们在这边从一开始也是没问题的
我们这可以只初始化一个都是可以的
然后i =3的时候 那么i = 3那就是数组3就等于3乘以数组2
那这样的话就可以把阶乘的结果全部存到数组里面去
数组0就是0的阶层 数组1元素是1的阶乘
数组2就是2的阶乘
这样就可以乘完
所以这个地方大家注意 有个
我们这个数组元素是个long long类型
i是个int类型
所以它会被生成long long 然后再做乘法运算
这样话就可以使它的范围变得更大 变得更大
那么我们可以把它的结果打印出来 这就是打印
然后把这个数组打印出来
表示 i 的叹号 i的阶乘等于这个结果
我们来运行一下这个程序
我们来看这个结果打印的时候就0的阶乘等于1
1的阶乘等于1 2的阶乘等于2
乘以三等于六六乘以四等于二十四 二十四乘以五等于120这样乘下去
大家看这个数字增的特别快 很快
大家可以做个实验 n等于几的时候long long 就会爆掉 就是超出范围
大家可以试一下
for循环的最后一个例子是关于step的步长 步长是什么
bigstep
我们前面的例子里面 我们这个条件基本上都是i++ 或者i--每次度长是1
这个地方其实是个update 是个修改值 你可以做什么都可以
你可以把i去做增量 你可以干别的
只要是个运算就可以
这个地方你可以做其他的
那我们在这个里面呢 我们实际上是增大一下step
我们可以说这个step每次增加多少加一还是加二加三
那么我们可以通过我们指定一个值
就是说从 i=0 开始 i小于100 然后呢 每次增加多少
如果每次增加1 那就会打印出0123456一直到99
如果每次增加10呢 会怎么样 我们来看
编译运行
那么我们要输入步长 我们输入1 这一下子就就打印出来了大家看
就从一直从0一直打印到100
那么我们如果能写个十呢 步长是十大家可以看
零 十 二十 三十 四十 五十 六十 七十 八十 九十没有一百
因为它的条件是小于100所以没有100
那么如果你不小心写个零呢
那么这个循环呢 永远不会停止
这个循环永远不会停止为什么
因为step等于零 i的值永远是零
也就是说他永远满足条件100
这个时候 这个时候
你的这个程序就一直在这里面循环
一直做打印操作不会停止不会停止
所以我们编程的时候 一定要小心 千万别写成死循环
也不要写成循环到不该循环的地方
我强烈杀死他
-Quiz 1
-Quiz 2
-3.3 Relational expressions (> < ==)
-3.5 Branching statements (if else)
-3.8 break and continue statements
-Quiz 3
-4.4 Structures, Unions and Enumerations
-Quiz 4
-5.3 Allocate memory: C++ style
-Quiz 5
-6.3 Recursion and pointer to functions
-Quiz 6
-Quiz 7
-8.1 C/C++ with ARM development board
-Quiz 8
-9.2 Constructors and destructors
-Quiz 9
-10.1 Operators in cv::Mat in OpenCV
-10.4 Automatic conversions and type casts for classes
-Quiz 10
-11.1 Dynamic memory and classes
-11.2 New and improved String class
-11.3 Using pointers to objects
-Quiz 11
-12.2 Static and dynamic binding
-12.3 Access control: protected
-12.4 Inheritance and dynamic memory allocation
-Quiz 12
-13.1 Constructor and assignment
-13.2 Classes with object members
-Quiz 13
-14.1 CNN for image classification
-Quiz 14
-15.3 RTTI and type cast operators
-Quiz 15
-Final exam

