任务内容
Description
特朗普当选了,网上流传着很多段子,也出了特朗普的头像。有人说,特朗普 的头像像一团云。所以今年马云去了美国和特朗普谈中美企业的发展。那么你能帮 忙打印出特朗普的头像吗? 抽象派认为,特朗普的头像上半部分可以由一些*组成。由上下对称的两个梯形 组成,梯形每一层之间相差1个星号。告诉你梯形的上边星号,梯形层数,你能打印 出来吗?。
Input
多组测试,输入2个整数,分别是梯形的上边星号,梯形层数
Output
输出头像。
解题思路详细解释
- 整体思路概述:
- 本题要求根据输入的梯形上边星号数量和梯形层数,动态生成并输出一个类似抽象派描述的特朗普头像上半部分(由上下对称的两个梯形组成)的图案。程序通过多个步骤,先绘制图案上半部分,再依据上半部分生成下半部分,最后输出整个图案,并在每次完成输出后清理用于存储图案的数组,以准备处理下一组输入数据。
- 变量定义部分:
- 定义了多个整型变量,
i
、j
主要用于在各种嵌套循环中控制行和列的计数,n
用于接收输入的梯形上边星号数量,m
用于接收梯形层数,这两个变量决定了图案的形状特征。p
变量用于在绘制图案上半部分时控制每行中空格的数量,实现梯形逐渐变宽的效果,u
变量则在绘制图案下半部分时,辅助定位要复制的上半部分图案对应的行,以保证下半部分与上半部分对称。
- 定义了多个整型变量,
- 图案上半部分绘制部分:
- 首先将
p
初始化为m - 1
,意味着最初每行前面的空格数量是梯形层数减 1,随着行数增加,空格逐渐减少,星号逐渐增多,形成梯形形状。 - 通过外层
for
循环控制行数(从第 0 行到第m - 1
行),对于每一行,内层for
循环控制列数(从第 0 列到第n + m - 1
列),根据当前列位置与空格数量p
的比较,决定在二维字符数组a
对应的位置填充空格(a[i][j] = ' '
)还是星号(a[i][j] = '*'
),每绘制完一行后,p
减 1,使得下一行的星号更靠右,逐步构建出上半部分的梯形图案。
- 首先将
- 图案下半部分绘制部分:
- 先将
u
初始化为m - 2
,因为要从图案上半部分倒数第二行开始,将其内容复制到下半部分与之对称的位置,以实现上下对称的效果。 - 通过外层
for
循环控制行数(从第m
行到第2 * m - 1
行),对于每一行,内层for
循环利用strcpy
函数将上半部分对应行(由u
控制)的内容复制到当前行(strcpy(a[i], a[u])
),每复制完一行,u
减 1,向上半部分更靠上的行获取内容进行复制,这样就构建出了与上半部分对称的下半部分梯形图案。
- 先将
- 图案输出部分:
- 通过两层嵌套的
for
循环,外层循环控制行数(从第 0 行到第2 * m - 1
行),内层循环控制列数(从第 0 列到第n + m - 1
列),使用printf
函数逐个输出二维字符数组a
中存储的字符(printf("%c", a[i][j])
),每输出完一行后,通过printf("\n")
进行换行操作,从而将整个上下对称的梯形组成的图案完整地输出显示出来。
- 通过两层嵌套的
- 数组清理部分:
- 使用
memset
函数将二维字符数组a
的所有元素清空(设置为'\0'
),这是为了在下一次输入新的梯形上边星号数量和梯形层数时,能够重新准确地绘制新的图案,避免上次图案残留的字符对新图案产生干扰,保证每次输出的图案都是根据当前输入参数独立生成的。
- 使用
#include<stdio.h>
#include<string.h>// 定义一个二维字符数组a,用于存储要打印的图案信息,这里假设图案最大尺寸为100x100
char a[100][100];int main(void)
{int i, j, n, m, p, u; // i、j用于循环计数,n表示梯形的上边星号数量,m表示梯形层数,p用于控制每行空格数量,u用于辅助复制上半部分图案到下半部分// 使用while循环持续读取输入,只要能成功读取两个整数(代表梯形的上边星号数量和梯形层数),就进行后续的图案绘制与输出操作,直到遇到文件结束符(EOF)停止循环while (scanf("%d%d", &n, &m) != EOF){p = m - 1; // 初始化空格数量,最初空格数量等于梯形层数减1,随着行数增加,空格逐渐减少// 外层循环控制行数,用于绘制图案的上半部分(梯形部分),从第0行开始,总共绘制m行for (i = 0; i < m; i++){// 内层循环控制每行的列数,用于填充字符(空格或星号),总列数为n + m - 1,这个数量与梯形的形状相关for (j = 0; j < n + m - 1; j++){// 如果当前列位置小于当前行对应的空格数量(即还没到该填充星号的位置),则在该位置填充空格if (j < p)a[i][j] = ' ';else// 否则,在该位置填充星号,以此来绘制出梯形形状a[i][j] = '*';}p--; // 每绘制完一行,空格数量减1,使得下一行的星号更靠右,形成梯形逐渐变宽的效果}u = m - 2; // 初始化用于复制上半部分图案的行索引,指向从上半部分倒数第二行开始,因为要复制到下半部分与之对称的位置// 外层循环控制行数,用于绘制图案的下半部分(与上半部分对称的梯形部分),从第m行开始,到2 * m - 1行结束,总共绘制m - 1行for (i = m; i < 2 * m - 1; i++){// 内层循环控制每行的列数,通过字符串复制函数strcpy,将上半部分对应行(由u控制)的内容复制到当前行,实现下半部分图案与上半部分对称的效果for (j = 0; j < n + m - 1; j++){strcpy(a[i], a[u]);}u--; // 每复制完一行,将复制的源行索引减1,向上半部分更靠上的行获取内容,以保证对称复制}// 外层循环控制行数,用于输出整个图案,从第0行开始,到2 * m - 1行结束,即输出整个上下对称的梯形组成的图案for (i = 0; i < m * 2 - 1; i++){// 内层循环控制列数,逐个输出当前行的每个字符,将图案内容打印出来for (j = 0; j < n + m - 1; j++){printf("%c", a[i][j]);}printf("\n"); // 每输出完一行,进行换行操作,以便下一行图案能正确显示}// 使用memset函数将二维字符数组a的所有元素清空(设置为'\0'),为下一次输入新的参数绘制新图案做准备,避免上次图案残留影响下次输出memset(a, '\0', sizeof(a));}return 0;
}