C语言日记 书P53 例 3-21:输出图案

 例3-21

编写程序输出以下图案。

1f6210f85ff347d8b9859266ffeb00d3.png

我编的(只写了前四行的,当然后面也发现里面有错误)

第一阶段

#include<iostream>
using namespace std;
int main()
{
    int i, L = 1, j;
        for (j = 1; j <= 30, L <= 8; j++)
        {
            cout << ' ';
        }
        L += 1;
        for (j = 1; j <= 8 - 2L, L <= 4; j++)
        {
            cout << ' ';
        }
        L += 1;
        for (j = 1; j <= 2L - 1, L <= 4; j++)
        {
            cout << '*';
        }
        L += 1;
}

结果就g了

为什么呢?原因如下:

在for语句的 表达式2(判断退出循环)中,不要放入多个限制语句。否则放入左侧的语句就会被忽略(放了也白放)。

dce8feecbe4b48d4b289ce7a78493c05.png

修改过程:

1.通过提醒,想到:多个语句可用“&&”串联起来判断,但是具体落实到这里的语句结构过于复杂,不适合。

2.将该程序修改所有程序的步骤模块化:

(第二阶段)

模块1:
先构建好整个程序图案最左侧8行30列的空格区域。

为了显化是否我们所有输出的空格真的已经输出了这里我们先用“*”代替空格的位置。

第一阶段:

#include<iostream>
using namespace std;
int main()
{
    int i, l = 1, j; 
    for (l = 1; l <= 8; l++)
    {
        for (i = 1; i <= 30; i++)
            cout << '*';
    }
}

结果:

2c6b7b75fd5b436085bde5dc63b6e102.png

为什么会这样?                                                 答案:

忘了加换行符。

根据书上的标准答案依葫芦画瓢:

#include<iostream>
using namespace std;
int main()
{
    int i, l = 1, j; 
    for (l = 1; l <= 8; l++)
    {
        for (i = 1; i <= 30; i++)
            cout << '*';
        cout << endl;
    }
}

049f2184f1d547be8aedfccb5f10e609.png

OK,那么我们现在不妨思考一下(他)为什么这么设计这样加换行符:

l 符合for语句条件,且i 符合for语句条件时,一直输出“ * ”

一行30个*输出完了(i == 30)以后,

跳出(for (i = 1; i <= 30; i++) cout << '*'; )的for循环

然后再开始运行(cout << endl;)语句。

在这里的核心(key point)在于:

在for循环末尾存在多个语句且没有花括号({ })的情况下,

程序是只把其后面的第一个语句记入for循环内

还是把后面的两个语句或多个语句全部记入for循环内?

当然,通过上面的具体例子已经说明:

程序是只把其后面的第一个语句记入for循环内,但是我们还需要通过具体实践验证才能证明该结论:

例1:

#include <iostream>
using namespace std;
int main()
{
    int i;
    for (i = 1; i <= 3; i++)
        cout << "1" << ' ';
    cout << "2" << endl;
}

d24b0c55ce47485497802400294d66d6.png

例2:

#include <iostream>
using namespace std;
int main()
{
    int i;
    for (i = 1; i <= 3; i++)cout << "1" << ' ';cout << "2" << endl;
}

d24b0c55ce47485497802400294d66d6.png

例3:

#include <iostream>
using namespace std;
int main()
{
    int i;
    for (i = 1; i <= 3; i++)
    {
        cout << "1" << ' ';
        cout << "2" << endl;
    }
}

bd3005c4218e426ba265ee6150f396c9.png

 通过例1例2例3,我们不难看出

在for循环末尾存在多个语句且没有花括号({ })的情况下,

程序只把其后面的第一个语句记入for循环内(其他语句记入循环外)

 OK,after all:

模块一的程序应为:

#include<iostream>
using namespace std;
int main()
{
    int i, l = 1, j; 
    for (l = 1; l <= 8; l++)
    {
        for (i = 1; i <= 30; i++)
            cout << ' ';
        cout << endl;
    }
}

模块2:在模块一的基础之上,先把该程序的前四行图像输出完(整)。

#include<iostream>
using namespace std;
int main()
{
    int i, l = 1, j; 
    for (l = 1; l <= 8; l++)
    {
        for (i = 1; i <= 30; i++)
            cout << ' ';
        cout << endl;
    }
    for (l = 1; l <= 4; l++)
    {
        for (i = 1; i <= 8 - 2l; i++)
            cout << ' ';
        cout << endl;
    }
    for (l = 1; l <= 4; l++)
    {
        for (i = 1; i <= 2l - 1; i++)
            cout << '*';
        cout << endl;
    }
}

结果出大问题:

3f5d78918bf94183957678986ccba126.png

 所以从这里这时候我们开始意识到:

当我们在这里进行完模块一的步骤后,

整个程序的操作位置已经在第8行第31列,

和也就是说这时我们已经无法再回到第一列了,所以我们从这个时候开始,我们需要重新设计模块一模块二。

也就是说,重新设计的模块一将执行完成前四行所有图案和空格的操作。

#include<iostream>
using namespace std;
int main()
{
    int i, l, j; 
    for (l = 1; l <= 4; l++)
    {
        for (i = 1; i <= 30; i++)
            cout << ' ';
        for (i = 1; i <= 8 - 2l; i++)
            cout << ' ';
        for (i = 1; i <= 2l - 1; i++)
                cout << '*';
        cout << endl;
    }
}

9f3c9b1e53a142c29b90e905e449bfad.png

 ???怎么回事???

对照书上的标准答案试着进行更改修正,结果加了俩*就正确了:

#include<iostream>
using namespace std;
int main()
{
    int i, l, j; 
    for (l = 1; l <= 4; l++)
    {
        for (i = 1; i <= 30; i++)
            cout << ' ';
        for (i = 1; i <= 8 - 2*l; i++)
            cout << ' ';
        for (i = 1; i <= 2*l - 1; i++)
                cout << '*';
        cout << endl;
    }
}

b7b6fad99eb445cea2076d08fb6cdc8e.png

并且

#include<iostream>
using namespace std;
int main()
{
    int i, l, j; 
    for (l = 1; l <= 4; l++)
    {
        for (i = 1; i <= 30; i++)
            cout << ' ';
        for (i = 1; i <= 8 - 2*l; i++)
            cout << ' ';
        for (i = 1; i <= 2l - 1; i++)
                cout << '*';
        cout << endl;
    }
}

结果是

1d2729ef51da40f48ea2575070d65cab.png

#include<iostream>
using namespace std;
int main()
{
    int i, l, j; 
    for (l = 1; l <= 4; l++)
    {
        for (i = 1; i <= 30; i++)
            cout << ' ';
        for (i = 1; i <= 8 - 2l; i++)
            cout << ' ';
        for (i = 1; i <= 2*l - 1; i++)
                cout << '*';
        cout << endl;
    }

结果是

33f4188d651342759279e0ea84892514.png

???

为什么?

原因如下:

L表示这是个long型常量:

2L表示2是长整型,-2L表示-2是长整型。

例:

long int a = -2L;  // 初始化的时候将-2转化为长整型后再赋给变量a

int a =-2L;// 初始化时-2L表示先将-2转化为长整型,但由于a是int类型,所以之后又转化为int类型赋值给变量a

没错,后面的L表示这是个long型常量,不加L默认是int型常量

这里我们对于这个l(其实就是自动类型转换和强制类型转换)再扩展延伸讲一点。

详见:

C语言日记 5 运算符和表达式_宇 -Yu的博客-CSDN博客

1.

前面这里的2l,相当于自动类型转换,把变量(输出的)类型自动转换为long类型。

类似举例,例如:a*1l,即把a的类型自动转换为long类型。

2.

l和L(即大写和小写)没有根本实际性的差别,最后效果(结果)一样。

3.

如果要(进行)强制类型转换,即运行(long)2或(long)a

4.

longlong类型和long的区别:

即(back to review):

#include<iostream>
using namespace std;
int main()
{
    int i, l, j;
    for (l = 1; l <= 4; l++)
    {
        for (i = 1; i <= 30; i++)
            cout << ' ';
        for (i = 1; i <= 8 - 2l; i++)
//即(等价于):for (i = 1; i <=6; i++)
            cout << ' ';
        for (i = 1; i <= 2l - 1; i++)
//即(等价于):for (i = 1; i <=1; i++)
            cout << '*';
        cout << endl;
    }
}

9f3c9b1e53a142c29b90e905e449bfad.png

#include<iostream>
using namespace std;
int main()
{
    int i, l, j;
    for (l = 1; l <= 4; l++)
    {
        for (i = 1; i <= 30; i++)
            cout << ' ';
        for (i = 1; i <= 8 - 2 * l; i++)
            cout << ' ';
        for (i = 1; i <= 2l - 1; i++)
//即(等价于):for (i = 1; i <=1; i++)
            cout << '*';
        cout << endl;
    }
}

结果是

1d2729ef51da40f48ea2575070d65cab.png

#include<iostream>
using namespace std;
int main()
{
    int i, l, j;
    for (l = 1; l <= 4; l++)
    {
        for (i = 1; i <= 30; i++)
            cout << ' ';
        for (i = 1; i <= 8 - 2l; i++)
//即(等价于):for (i = 1; i <=6; i++)
            cout << ' ';
        for (i = 1; i <= 2 * l - 1; i++)
            cout << '*';
        cout << endl;
    }
}

结果是

33f4188d651342759279e0ea84892514.png

解决该问题过程中的心得:

我们面对的问题更多的在于心理,而非物理

OK,简而言之,模块一的程序为:

#include<iostream>
using namespace std;
int main()
{
    int i, l, j; 
    for (l = 1; l <= 4; l++)
    {
        for (i = 1; i <= 30; i++)
            cout << ' ';
        for (i = 1; i <= 8 - 2*l; i++)
            cout << ' ';
        for (i = 1; i <= 2*l - 1; i++)
                cout << '*';
        cout << endl;
    }
}

下面(现在),我们只要把剩余的下半部分图像(模块二)补完就行:

#include<iostream>
using namespace std;
int main()
{
    int i, l, j;
    for (l = 1; l <= 4; l++)
    {
        for (i = 1; i <= 30; i++)
            cout << ' ';
        for (i = 1; i <= 8 - 2 * l; i++)
            cout << ' ';
        for (i = 1; i <= 2 * l - 1; i++)
            cout << '*';
        cout << endl;
    }
    for (l = 3; l >= 1; l--)
    {
        for (i = 1; i <= 30; i++)
            cout << ' ';
        for (i = 1; i <= 2 * l - 1; i++)
            cout << '*';
        for (i = 1; i <= 8 - 2 * l; i++) cout << ' ';
//这里这个for语句的小循环后面省略(忽略)也不要紧
//因为反正下面都换行了,你后面打不打空格都无所谓
        cout << endl;
    }
}

结果输出成功:

书上的标准答案,源程序:

#include<iostream>
using namespace std;
int main()
{
    const int N = 4;//输出前4行图案
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= 30; j++)
            cout << ' ';
        //在图案左侧空 30列
        for (int j = 1; j <= 8 - 2 * i; j++)
            cout << ' ';
        for (int j = 1; j <= 2 * i - 1; j++)
            cout << '*';
        cout << endl;
    }
    //输出后 3 行图案
    for (int i = 1; i <= N - 1; i++)
    {
        for (int j = 1; j <= 30; j++)
            cout << ' ';
        //在图案左侧空 30列
        for (int j = 1; j <= 7 - 2 * i; j++)
            cout << '*';
        cout << endl;
    }
    return 0;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值