1.代码需求
编写一个C语言程序,输出以下图形
A
ABA
ABCBA
ABCDCBA
ABCDEDCBA
ABCDCBA
ABCBA
ABA
A
2.代码实现与讲解
能搜索到的方法大多以先输出左半边正金字塔,再输出右半边正金字塔,随后再按照这种方法输出倒金字塔为主
这里给出两种方法:第一种方法依旧是先输出正金字塔再输出倒金字塔,但是在每一行的输出上使用“偏移量”的方式,来获取该位置需要输出的字母。
先上一个可以直接移植的代码:
#include<stdio.h>
/*
* 定义了返回值为int值的min_ofAB函数,用于返回n1和n2中更小的那一个。
* @param n1 用户提供的妙妙数据1
* @param n2 用户提供的妙妙数据2
* c++中通过引用algorithm头文件 #include<algorithm>
* 可以使用std::min来比较两个整数的最小值,
*/
int min_ofAB(int n1 , int n2);
/*
* 定义了无返回值的out_char_pyramid函数,用于输出字母正三角或者倒三角。
* @param n 需要输出的三角形行数+1
* @param temp 决定了输出三角形的形式,temp = 1 则输出正向的字母三角形, temp = -1 则输出倒着的三角形
*/
void out_char_pyramid(int n , int temp);
int main(int argc ,char * argv[])
{
out_char_pyramid(5 , 1);
out_char_pyramid(4 , -1);
return 0;
}
void out_char_pyramid(int m , int temp)
{
int n = m + 1;
char ch = 'A';
int min = 0;
if(1 == temp)
{
for(int i = 1 ; i < n ; i++)
{
for(int j = 0; j <= n - i - 1; j++)
{
printf(" ");
}
for(int k = 0 ; k < 2 * i - 1 ; k++)
{
min = min_ofAB(k , 2 * i - k -2);
printf("%c" , ch + min * ('B' - 'A'));
}
printf("\n");
}
}
else if(-1 == temp )
{
for(int i = 1 ; i < n ; i++)
{
for(int j = 0; j <=i; j++)
{
printf(" ");
}
for(int k = 0 ; k < 2 * n - 2 * i -1 ; k++)
{
min = min_ofAB(k , 2 * n - 2 * i - 2 - k);
printf("%c" , ch + min * ('B' - 'A'));
}
printf("\n");
}
}
}
int min_ofAB(int n1 , int n2)
{
if(n1 > n2)
{
return n2;
}
else
{
return n1;
}
}
这段代码的核心就是在每一行输出字母字符时,使用了所谓“偏移量”的方法。
以第五行为例:ABCDEDCBA,
每个字母在ascii码上,相较于字母A的偏移量分别是“0 1 2 3 4 3 2 1 0”。
如果用分段式函数来看,这个序列相当于是 y = x 和 y = 8 - x 两个一次函数中的更小值。(计算的时候类似于数组,每行的第一个元素是从0开始,一共是0到8共九个元素)。
引入了min_ofAB函数,这个函数用于输出两个数值中更小值,在c++中可以调用std::min来实现
int min_ofAB(int n1 , int n2)
{
if(n1 > n2)
{
return n2;
}
else
{
return n1;
}
}
推广到每一行,正向三角形的第i行中共有2 * i - 1 个字母字符需要输出,这样可以得到输出字母字符的循环体:
for(int k = 0 ; k < 2 * i - 1 ; k++)
{
min = min_ofAB(k , 2 * i - k -2);
printf("%c" , ch + min * ('B' - 'A'));
}
倒向三角形的第 i 行中共有 2 * n - 2 * i + 1 个字符,其中n代表的是总倒三角形的行数
那么对应的两个一次函数是:y = x ; y = (2 * n - 2 * i + 1)- x ;对应的循环体是
for(int k = 0 ; k < 2 * n - 2 * i -1 ; k++)
{
min = min_ofAB(k , 2 * n - 2 * i - 2 - k);
printf("%c" , ch + min * ('B' - 'A'));
}
这样,这个问题就比较容易解决了。
3.另一种解决方案
同时,给出一种直接输出正金字塔和倒金字塔组合的代码:
#include<stdio.h>
/*
* 定义了返回值为int值的min_ofAB函数,用于返回n1和n2中更小的那一个。
* @param n1 用户提供的妙妙数据1
* @param n2 用户提供的妙妙数据2
* c++中通过引用algorithm头文件 #include<algorithm>
* 可以使用std::min来比较两个整数的最小值,使用std::min_element来找出数组、vector等序列的最小元素
*/
int min_ofAB(int n1 , int n2);
/*
* 定义了无返回值的show_pri函数,输出菱形的字符阵列
* @param n 用户提供的输出行数
* @param ch 用户提供的开始字符。
*/
void show_pri(int n , char ch);
int main(int argc, char * argv[])
{
show_pri(9, 'A') ;
return 0;
}
void show_pri(int n , char ch)
{
int m = n + 1;
int temp = 0;
int temp2 = 0;
for(int i = 1 ; i < m ; i++)
{
/*
* temp 是每一行要输出的字母字符数量
* temp 是 2 * i - 1 和 2 * m - 2 * i 的最小值
*/
temp = min_ofAB(i * 2 - 1 , (m - i) * 2 - 1);
/*
* 这个表达式的意思是,j< 4-i和i-5的最大值(当m=10的时候)
*(定值减两个数的最小值,就是函数“定值减最小值”的最大值)
*/
for(int j = 0; j < m / 2 - temp / 2 - 1 ; j++)
{
printf(" ");
}
/*
* 每一行的字符数是2i-1和19-2i的更小值(当m=10的时候)
* temp2是每一行第k(k从0开始,理解为数组的首个元素)个字符与'A'的偏差值
*/
for(int k = 0 ; k < temp ; k++)
{
/*
* temp2 是 k 和 temp - k - i 的最小值,
* 提供了每一行字符从‘A’开始的ascii码偏移量
*/
temp2 = min_ofAB(k , temp - k - 1);
ch = 'A' + temp2 * ('b' - 'a');
printf("%c" , ch);
}
printf("\n");
}
}
int min_ofAB(int n1 , int n2)
{
if(n1 > n2)
{
return n2;
}
else
{
return n1;
}
}