例3-21
编写程序输出以下图案。
我编的(只写了前四行的,当然后面也发现里面有错误)
第一阶段
#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(判断退出循环)中,不要放入多个限制语句。否则放入左侧的语句就会被忽略(放了也白放)。
修改过程:
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 << '*';
}
}
结果:
为什么会这样? 答案:
忘了加换行符。
根据书上的标准答案依葫芦画瓢:
#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;
}
}
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;
}
例2:
#include <iostream>
using namespace std;
int main()
{
int i;
for (i = 1; i <= 3; i++)cout << "1" << ' ';cout << "2" << endl;
}
例3:
#include <iostream>
using namespace std;
int main()
{
int i;
for (i = 1; i <= 3; i++)
{
cout << "1" << ' ';
cout << "2" << endl;
}
}
通过例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;
}
}
结果出大问题:
所以从这里这时候我们开始意识到:
当我们在这里进行完模块一的步骤后,
整个程序的操作位置已经在第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;
}
}
???怎么回事???
对照书上的标准答案试着进行更改修正,结果加了俩*就正确了:
#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 <= 2l - 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 - 2l; i++)
cout << ' ';
for (i = 1; i <= 2*l - 1; i++)
cout << '*';
cout << endl;
}
}
结果是
???
为什么?
原因如下:
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(其实就是自动类型转换和强制类型转换)再扩展延伸讲一点。
详见:
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;
}
}
#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;
}
}
结果是
#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;
}
}
结果是
解决该问题过程中的心得:
我们面对的问题更多的在于心理,而非物理
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;
}