c++零基础新手入门(六)

本节目录

    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小弟说了一句break,for小弟就不需要继续循环了。
所以,我们在第二层循环的if语句中增加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,其余情况为真。想不起来的同学可以翻一翻之前的教程。

 

 

今日:我还没想好有什么作业!

点赞

发表评论