C语言打印菱形实例详解
前言
打印菱形这道题对于初学编程者来说简直是噩梦,曾经我就是栽在这上面的,后来编程编多了之后对打印菱形也觉得不再那么难了,去年在公众号写了一篇推送是关于打印菱形的,觉得对一些师弟师妹还是有所帮助的,今天就把这道题分享出来。
以下是我遇到的各种各样的菱形:
普通菱形,输入n,输出n行n列的菱形
难度系数:♥
n行空心菱形,输入n,输出n行空心菱形
难度系数:♥♥
n行挖空菱形,输入n,输出n行n列空格菱形
难度系数:♥♥♥
n行数字菱形,输入n,输入n行数字从外到内递增的数字菱形
难度系数:♥♥♥♥
有边框空心菱形,输入n,输出n行带有边框的空心菱形
难度系数:♥♥♥♥♥
首先我们要明确这是一个随着n的大小改变的菱形,所以我们肯定要用到循环,并且循环的次数与n有关。如果题目要求是输出n行,那我们的循环就是0(n-1)或者1n;如果要求是输出(2n+1)行,那我们的循环就0-2n或者1~(2n+1)即可。(后面以输出n行为例分析)
第一个是普通的实心菱形,循环n行大家都懂,问题就在列要怎样循环。难道是看出来的吗?不错,我就是通过看得出来的循环次数。具体怎么看呢?
根据图直接看有点难度,所以我们根据各行数据来看
我们需要将整个菱形分成四块来考虑,从上到下空格的个数先从n/2递减到0后递增到n/2,而行循环因子i又从0递增到n,故自然可联想到用i与n/2来表示空格个数。因为空格个数是非负数,所以我们引进绝对值|n/2-i|表示空格个数。打完空格之后,我们就要正式用 ' * '打印菱形了。通过观察我们发现 * 号的个数为奇数,并且变化规律跟空格正好相反,所以号个数即是-2*(空格个数)+1+C(常数)=-2*(空格个数)+C(常数),通过观察我们发现这个常数C正好是n/2。于是第一种菱形就可以顺利完成了!
第二个是空心菱形,与实心菱形相似,可看成在实心菱形上再打了一个空格菱形。由于每行的号数不多,并且可以看到号正好位于空格菱形的外围,所以我们可以将打印号放在打印空格菱形前后顺便打印,即在打印空格菱形之前打号,打印完空格菱形之后再打印号。同样,我们将相关数据列出来然后观察规律。号前空格与实习菱形一致,而我们发现n-2|n/2-i|-2的值除了首尾两行外,其他都与空格菱形的空格个数一致,而首尾两行是-1表示在该处不需打空格反而需要退一个格,但由于我们当前位置为号,而退格后依旧要打号,所以我们可以直接判断是否为第一行或最后一行,是则少打印一个号即可。
第三个是挖空菱形,该菱形是上述两个的合体,我们可以看成把一个实心菱形的各个字符替换成另一种字符,再插入一个空心菱形。所以我们把该菱形分成输出空心菱形前后号和输出空心菱形两部分。通过数据对比,我们不难发现,输出空心菱形前后号的数据与实心菱形输出号前空格个数一致,然后就是输出一个空心菱形,最后要记得在输出空心菱形之后输出空心菱形之后的号,根据对称可知,空心菱形后号个数与空心菱形前号一致。
第四个是数字菱形,该菱形的特点是数字从外到内逐层递增。我们发现该菱形中轴线数字的变化规律是先从1递增到(n+1)/2,然后再递减到1,并且每一行的数字也是从1递增到中轴线,再递减到1,因此我们要找到中轴线所在的位置(方便判断循环因子是否到达中轴线)。通过列数据我们发现中轴线所在位置(j从0开始循环)为n/2-|n/2-i|,所以在每一行中我们的数字加到“j==n/2-|n/2-i|”处时应该转成递减,所以我们引进要填充的数字k,在每一行开始时k为1,在j从0到n/2-|n/2-i|-1中,k逐次递增,在j从n/2-|n/2-i|到n-2*|n/2-i|-1中k递减。然后将打印星号改为打印数字即可。
第五个是边框空心菱形。从名字可知,该菱形由边框和空心菱形组成,我们可以将边框和空心菱形分开来考虑。第一行和最后一行为边框,可直接用从0到n-1打印号实现。左右边框在每一行的开头和结尾打印号即可实现。中间即是空心菱形的领域,基本上跟打印空心菱形一样,只是要注意被边框覆盖的地方空格和号要省略。
将打印空格和打印号分开考虑,通过数字之间的关系特点,运用循环完成菱形的打印。
由于菱形是对称的,所以绝对值是最好的数据描述工具,要巧妙地运用绝对值,将对称部分的循环用同一个带有绝对值的表达式表示出来。
值得注意的是n/2为整数除,所以不会得到小数,也不是四舍五入。
中轴线所在位置(j从0开始循环)为n/2-|n/2-i|。
//挖空菱形 for(i=0;i<n;i++){ for(j=0;j<abs(n/2-i);j++) printf("*"); printf("*"); for(j=0;j<n-2*abs(n/2-i)-2;j++) printf(" "); if(j!=0) printf("*"); for(j=0;j<abs(n/2-i);j++) printf("*"); printf("\n"); } printf("\n"); //边框菱形 for(i=0;i<n;i++){ if(i==0||i==n-1){ for(j=0;j<n;j++) printf("*"); printf("\n"); } else{ printf("*"); for(j=0;j<abs(n/2-i)-1;j++) printf(" "); if(j!=0) printf("*"); for(j=0;j<n-2*abs(n/2-i)-1;j++) printf(" "); if(j!=0) printf("*"); for(j=0;j<abs(n/2-i)-1;j++) printf(" "); if(j!=0) printf("*"); printf("\n"); } } //数字菱形 for(i=0;i<n;i++){ int k=1; for(j=0;j<abs(n/2-i);j++) printf(" "); for(j=0;j<n-2*abs(n/2-i);j++){ printf("%d",k); if(j<n/2-abs(n/2-i)) k++; else k--; } printf("\n"); } //实心菱形 for(i=0;i<n;i++){ for(j=0;j<abs(n/2-i);j++) printf(" "); for(j=0;j<n-2*abs(n/2-i);j++) printf("*"); printf("\n"); } printf("\n"); //空心菱形 for(i=0;i<n;i++){ for(j=0;j<abs(n/2-i);j++) printf(" "); printf("*"); for(j=0;j<n-2*abs(n/2-i)-2;j++) printf(" "); if(j!=0) printf("*"); printf("\n"); }
总结