本节目录
1°循环的嵌套
2°阶乘和
3°break
循环的嵌套
上节简单提到了for循环和for和if的结合,这节来讨论下for和for的循环。
还记得上节的“我是一个复读机”吗?现在我如果想要输出一个每行10个,一共10行的“我是一个复读机”,难道我就需要用for循环10次,每次循环中输出10次“我是一个复读机”?
就像这样?
for(int i = 0; i < 10; i ++){ cout<<"我是一个复读机"; cout<<"我是一个复读机"; cout<<"我是一个复读机"; cout<<"我是一个复读机"; cout<<"我是一个复读机"; cout<<"我是一个复读机"; cout<<"我是一个复读机"; cout<<"我是一个复读机"; cout<<"我是一个复读机"; cout<<"我是一个复读机"; cout<<endl; }
当然不用那么麻烦,可以使用两个for循环嵌套在一起,外面的for循环10次,里面的for循环循环10次,外面的负责列,里面的负责行,那么10*10的“我是一个复读机”就出现了。
也就是这样:
for(i→10){ for(j→10){ cout<<"内容 "; } cout<<endl; }
其中第五行的endl是用于在每输出一行后,用于换行的,这里一共会输出10次换行,每隔10个内容换一次行,也就实现了10行10列的“我是一个复读机”。
完整代码也就是这个样子的;
#include <iostream> using namespace std; int main() { for(int i = 1; i <= 10; i ++){ for(int j = 1; j <= 10; j ++){ cout << "我是一个复读机"; } cout << endl; } return 0; }
上面的代码实现了打印一个10*10的矩阵内容,但是实际上可能不会那么简单,比如我想实现这个:
# # # # # # # # # # # # # # #
就有点复杂了,但是不着急,用简单的方式分析一下。
第一行有一个,第二行有两个,第三行有三个。。。
首先先把输出行的循环写出来
for(int i = 1; i <= 5; i++){ }
现在就要来尝试实现列的输出了。需要满足每行的列数等于行数
也就是说,每行的 j 的最大值要和所在的第 i 行的 i 相等
比如,第1行有1列,只要让j循环1次,第二行有2列,要让j循环2次。
把代码补充完整:
for(int i = 1; i <= 5; i++){ for(int j = 1; j <= i; j++){ cout << "#"; } }
核心部分就完成啦!
如果想要完成这样的输出呢?
1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1
这满是0和1的输出,仔细观察一哈
如果以右上角的0为原点,向右为x轴方向,向下为y轴方向,建立坐标系
那么1的左边分别是:(0,0),(1,1),(2,2),(3,3),(4,4)
1出现在横坐标等于纵坐标的地方。
首先,先把输出5*5个0的程序写出来
for(int i = 0; i < 5; i++){ for(int j = 0; j < 5; j++){ cout << 0 ; } }
现在再在第二个循环内增加一个判断,当i==j时,输出1而不是0
for(int i = 0; i < 5; i++){ for(int j = 0; j < 5; j++){ if(i == j){ cout << 1; }else{ cout << 0; } } }
这样就实现了!
总结一下,循环的嵌套规律:首先,找出每一行之间的规律,其次,找出每一列之间的规律,在用i,j,或更多的for来表示出来就好了。
难题来了:我需要输出一个n*n的菱形,比如n=4时:
* * * * * * * * * * * * * * * *
首先,找每一行的规律:先是3个空格,1个,然后2个空格,2个,到1个空格,3个,最后0个空格4个,再倒着输出一编。
特别注意:这里会发现,每个*空面也是有空格的!!!
首先,来解决前n - 1行。写成框架:
for(int i = 1; i <= n -1; i++){ }
每一行,需要先输出空格,在输出相应的*号,n = 4时第一行3个空格,第二行2个空格,第三行一个空格,空格数加上行数等于n。所以空格数=n-i
输出空格:
for(int i = 1; i <= n -1; i++){ for(int j = 1; j <= n - i; j++){ cout << " "; } }
然后输出,的个数和行数是相同的。别忘了加换行!
for(int i = 1; i <= n -1; i++){ for(int j = 1; j <= n - i; j++){ cout << " "; } for(int j = 1; j <= i; j++){ cout << "* "; } cout << endl; }
前三行输出完了,我需要输出第四行,惊奇的发现,第4行也是遵循前三行的规律的,所以只需要调整i的范围既可。
for(int i = 1; i <= n; i++){ for(int j = 1; j <= n - i; j++){ cout << " "; } for(int j = 1; j <= i; j++){ cout << "* "; } cout << endl; }
好啦,现在已经输出了一般咯!还有一个小的倒三角!
观察第5行,有1个空格,3个*,
观察第6行,有2个空格,2个*,
观察第7行,有3个空格,1个*。
发现了什么规律?
自己写一些试试!
答案
你会发现,行数减去空格数为n,所以:
for(int i = n; i <= 2 * n - 1; i++){ for(int j = 1; j <= i - n; j++){ cout << " "; } }
空格数加上*数等于n,所以空格数为2*n - i
for(int i = n; i <= 2 * n - 1; i++){ for(int j = 1; j <= i - n; j++){ cout << " "; } for(int j = 1; j <= 2 * n - i; j++){ cout << "* "; } cout << endl; }
把前后两端合并并补全,看看有没有正常输出结果?
阶乘和
数学老师给小于出了道题:计算由1到n每一个数字的阶乘和。由于n可能较大,需要使用long long(第二节有讲过!!!)
所以,需要一次枚举1到n,然后再枚举计算n的阶乘。
首先,枚举n
long long ans; for(int i = 1 ; i <= n; i++){ }
然后,申明一个变量a来输出i的阶乘
long long ans; for(int i = 1 ; i <= n; i++){ int a = 1; }
写一个for循环计算i的阶乘
别忘了把a加入ans!
long long ans; for(int i = 1 ; i <= n; i++){ int a = 1; for(int j = 1; j <= i; j++){ a *= j; } ans += a; }
最后,输出ans就是答案啦!
break
这回,小于需要计算出小于200的所有质数,并输出。
首先,一个1到200的for循环是少不了的。
判断一个n是不是质数,我们需要把n依次对2到n-1的数进行去模运算,一旦有一个模为0,也就是可以整除,这个数字就不是质数。
首先,循环200次。
for(int i = 1; i <= 200; i++){ }
然后,我们需要让j从2循环到i - 1。
for(int i = 1; i <= 200; i++){ for(int j = 2; j <= i - 1; j ++ ){ } }
下面来写if,判断i对j取模是否等于0
for(int i = 1; i <= 200; i++){ for(int j = 2; j <= i - 1; j ++ ){ if(i % j == 0){ } } }
如果进入了if,也就说明它不是质数,如果没有进入if,也就说明它是质数。
那么该如何实现上述功能呢?
还记得之前学习的bool型吗?我们可以在第一个循环下面定义一个bool型,用来储存i是质数的“情况”。
可以把这个bool型变量的默认为true,当进入if时,我们就把它变为false。
如果没有进入if,在第二层循环结束后,它依旧是true,也就说明它是质数。
只需要在第二层循环后,判断bool型变量的值,如果是true,就输出既可。
for(int i = 1; i <= 200; i++){ bool is_prime = true; for(int j = 2; j <= i - 1; j ++ ){ if(i % j == 0){ is_prime = false; } } if(is_prime){ cout << i; } }
比如,当i为6时,j从2开始判断,发现j=2时,6 % 2=0,也就说明了6不是质数,此时,就不需要再判断6 % 3,6 % 4, 6 % 5的值了。毕竟,只要有一个可以整除,就说明他不是质数。
所以,这里引入一个新的函数---break,他能够让我们跳出循环,不用再做接下来的循环了。
小于有一天一直在做相同的作业,突然,老师对他说:break!小于就停下笔,不用再继续做这枯燥而又无聊的作业了。
for(int i = 1; i <= 200; i++){ bool is_prime = true; for(int j = 2; j <= i - 1; j ++ ){ if(i % j == 0){ is_prime = false; break; } } if(is_prime){ cout << i; } }
这样,程序就可以再发现可以整除后,直接跳出了。
有同学看可能会对if(is_prime)有疑问,他就和if( is_prime == true)是相同的,由于is_prime是一个bool型变量,所以可以直接这么用,当这个bool型变量是true时,这个判断也就成立。
当然,if括号内直接放一个int变量也是可以的,当int为0时,为false,其余情况为真。想不起来的同学可以翻一翻之前的教程。
今日:我还没想好有什么作业!