输出图案类问题的思路

问题导入——编写一个程序,只用两条输出语句,生成一个像半个5*5正方形形状(直角三角形)的#符号图案:

#####

####

###

##

#

我们可以采用消减法,先把它想象成一个5*5的矩形。

第一行:##### 的实现代码(一个for循环即可)

1 for(int hashNum = 1;hashNum <= 5;hashNum++)
2     {
3         printf("#");
4     }
5     printf("\n");

所以,要想打印出一个5*5的矩形,只需将上述代码循环5次即可,即:

1 for(int row = 1;row <= 5;row++)
2     {
3         for(int hashNum = 1;hashNum <= 5;hashNum++)
4         {
5         printf("#");
6         }
7         printf("\n");
8     }

到目前为止,我们可以打印出一个5*5的矩形了,已经接近最终的解决方案了。

那么,接下来应该怎样修改代码,使它产生半正方形的图案呢?

如果我们观察上面的程序清单并把它与自己所需要的半正方形的输出进行比较,可以发现问题在于条件表达式hashNum <= 5上。这个条件产生了5个相同的、由5个#符号所组成的行。所以我们需要一种机制,调整每行所生成的符号数量,使第一行为5个符号,第二行为4个符号,以此类推。

接下来,我们要进行另一个消减程序的试验:写一段代码,功能:显示数字从5到1,每个数字出现在单独的一行中

分析:我们必须找到一种表达式,在第一行时其值为5,在第二行时其值为4,接下来以此类推。如果我们需要一个当行号递增时其值递减的表达式,首先想到的可能是在行号前面加个符号,相当于把它乘以-1.这种方法可以产生递减的数字,却不是我们所需要的数字。我们可以把对问题的分析通过一张表格来总结下


行号


所需的值


行号*-1


行号与所需值之差


1


5


-5


6


2


4


-4


6


3


3


-3


6


4


2


-2


6


5


1


-1


6

差是一个固定值6。这意味着我们所需要的表达式是 row*-1 + 6。简化为6 - row。

所以“显示数字从5到1,每个数字出现在单独的一行中”的代码为:

1     for(int row = 1;row <= 5;row++)
2     {
3         printf("%d\n",(6-row));
4     }

所以打印半个5*5正方形形状(直角三角形)的#符号图案的完整代码为

 1 #include<stdio.h>
 2 int main()
 3 {
 4     for(int row = 1;row <= 5;row++)
 5     {
 6         for(int hashNum = 1;hashNum <= 6-row;hashNum++)
 7         {
 8             printf("#");
 9         }
10         printf("\n");
11     }
12 } 

问题延伸——编写一个程序,只用两条输出语句产生一个类似侧三角形形状的#符号图案:

#

##

###

####

###

##

#

根据前一个问题的分析,我们知道做法如下:

1,使用一个循环,显示一行特定长度的符号。

2,使用嵌套循环显示一系列的行。

3,使用代数表达式而不是固定值,为每一行创建不同数量的符号。

4,通过试验和分析,发现正确的代数表达式。

解决各形状问题所需要的各个组成部分

#####                                   #####     5

####                                     #####     4

###            #####               #####     3

##                                         #####     2

#                                           #####     1

#                                            ####      1

##                                         ####      2

###                                       ####      3

####          ####                 ####      4

###                                      ####      3

##                                        ####      2

#                                          ####      1

解决“侧三角形”问题所需要的各个组成部分

1    7     3    3  #

2    6     2    2  ##

3    5     1    1  ###

4    4     0    0  ####

3    3    -1    1  ###

2    2    -2    2  ##

1    1    -3    3  #

(a) (b) (c)  (d) (e)

分析:在“半正方形”问题中,用一个较大的整数减去行号是可行的,所以我们这次用8 - row(行号)得到(b)的结果,但这并不是我们想要的。在前一个问题中,我们需要从大到小的数而不是从小到大的数,因此用一个较大的数减去循环变量就可以了。在这个问题中,我们先是从小到大然后再从大到小。可以试着找到一个中间值,所以我们把前面的8 - row 替换成4 - row,可以得到(c)的结果。这个结果也不正确,但是如果忽略最后3个数左边的负号,它就是我们所需要的结果。如果我们使用绝对值函数去掉这些负号会怎么样?表达式abs(4 - row)产生结果(d),就是我们想要的结果了。

延伸分析:如果我们是对空格而不是#号进行计数会怎么样呢?(d)列就是我们对空格进行计数的正确的值序列。为了得到正确数量的#符号,可以把每行看成有4个格子,然后减去空格的数量。如果每行有4个格子,其中abs(4 - row)为空格的数量,则具有#符号的格子的数量就可以用4 - abs(4 - row)获得。

代码如下:(注意调用abs函数时要提前添加stdlib.h头文件)

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 int main()
 4 {
 5     for(int row = 1;row <= 7;row++)
 6     {
 7         for(int hashNum = 1;hashNum <= 4-abs(4 - row);hashNum++)
 8         {
 9             printf("#");
10         }
11         printf("\n");
12     }
13 } 

如果再次遇到类似的图案输出类问题,以上这套组合拳还是非常有效的!^_^

时间: 2024-10-06 22:02:37

输出图案类问题的思路的相关文章

C语言实现for循环输出图案

输出图案: * *** ***** *** * #include <stdio.h>int main(){ int i, j; for (i = 1; i <= 3; i++) /*i从1到3表示图像的第一到第3行*/ { for (j = 1; j <= 2 * i - 1; j++) /*星号也是i的函数为2*1-1个*/ printf("*"); printf("\n"); } for (i = 0; i <= 1; i++) /

js控制台输出图案

控制台输出图案 console.log([ " _ooOoo_", " o8888888o", " 88\" . \"88", " (| -_- |)", " O\\ = /O", " ____/`---'\\____", " .' \\\\| |// `.", " / \\\\||| : |||// \\", " /

C#中的输入和输出与类和对象

一.C#输入和输出 1.输入--使用Console.ReadLine();  ReadLine()方法的返回类型是string 1.1 从键盘中输入字符串格式的内容 string 变量名=Console.ReadLine(); 1.2 从键盘中输入数字格式的内容 int 变量名=   int.Parse(Console.ReadLine()); int 变量名=   Convert.ToInt32(Console.ReadLine()); 2.输出  Console.Write();//输出不换

C++用重载输出一个类

还记得刚开始学习C++时候,对于 cout 可以直接输出各种类型的变量很好奇. 毕竟是大一刚学完C语言,知道如果要输出什么数据肯定是要指定类型输出的 printf(). 对于C++中的一个变量 string str,使用 cout 可以直接输出string, 然而采用C中使用的 printf("%s", str) 是绝对无法输出该变量的.因为 这里的 str 是 一个 class.而不是一个 char* 类型的变量.当然,如果非要用printf()输出 str 也不是 不可以.采用 p

输入和输出--RandomAccessFile类

RandomAccessFile 类 RandomAccessFile 类既可以读取文件内容,也可以向文件输出数据. RandomAccessFile 类支持 "随机访问" 的方式,程序可以直接跳到文件的任意地方来读写文件.所以说RandomAccessFile是IO流体系中功能最丰富的类.如果我们希望只访问文件的一部分内容,而不是把文件从头读到尾,使用这个类将是一个很好的选择.好多的多线程,断点的网络下载工具就是通过这个类来实现的,所有的下载工具在下载开始后都会建立2个文件:1个是与

输入和输出--File类

输入和输出 写在前面的:Java中的输入和输出还是比较重要的,之前我都没想整理IO和多线程的,但是在研究后面的好多东西时候,经常要读取资源文件,这个时候就不得不回过头来整理IO了.要玩熟Java的输入和输入,就必须先玩熟一个类:File.然后在就是Java.io包下的类和接口了.Java的IO主要包括了输入和输出2种流,每种输入和输出又分为字节流和字符流.值得注意和研究的是Java的IO流使用了一种装饰器设计模式,它将IO流分成底层节点流和上层处理流.除此之外,还要研究2个东西:1,Java对象

命令行窗口输出图案

#include "Graphic_fun.h" /* 功能:输出为 # # # # # # # # # # # # */ UINT32 Graphic_prismatic1( UINT32 u32_line, CHAR i8_m ) { UINT32 u32_i = 0u, u32_j = 0u; /* 上半部分 */ for ( u32_i = 1u; u32_i <= u32_line; u32_i++) { for (u32_j = 1u; u32_j <= (u3

Java 输入/输出——File类

File类是java.io包下代表与平台无关的文件和目录,也就是说,如果希望在程序中操作文件和目录,都可以通过File类来完成.值得指出的是,不管是文件还是目录都是使用File来操作的,File能新建.删除.重命名文件和目录,File不能访问文件内容本身.如果需要访问文件内容本身,则需要使用输入/输出流. File类相关的方法参考链接:https://docs.oracle.com/javase/9/docs/api/overview-summary.html Field Summary Fie

在屏幕上输出图案:*与空格拼出的菱形

#include<stdio.h> int main() {  int i,j;  for(i=1;i<=7;i++)  {   for(j=1;j<=7-i;j++)   {    printf(" ");   }   for(j=1;j<=(2*i-1);j++)   {    printf("*");   }   printf("\n");  }  for(i=1;i<=6;i++)  {   for(j