工程师思想之抽象化
前言
**问题:使用c语言编程向控制台打印矩形、空心矩形、等腰三角形、菱形和回字形。**针对这种问题,大多数程序员都习惯于直接for循环嵌套来做,外层for打印行,内层for打印列。对于简单的打印矩形,我们都还表现的游刃有余,可到了打印菱形和回字就开始显得力不从心了。
没有抽象化的程序
对于打印矩形,我是如此解答的:
#include<stdio.h>
int shiXingJuXing()
{
int i;
int j;
for (i = 0; i < 5; i++) {
for (j = 0; j < 5; j++) {
printf("*");
}
printf("\n");
}
return 0;
}
int main()
{
shiXingJuXing();
}
对于上述程序,相必刚学编成的小白都能看的明白。可是,如果程序变得更复杂一些呢?请看以下程序:
# include<stdio.h>
int main()
{
int i;
int j;
int k;
for (i = 0; i < 5; i++){
for (j = 4; j >= i; j--)
{
printf(" ");
}
for (k = 0; k < i*2; k++) {
printf("*");
}
printf("\n");
}
for (i = 5; i > 0; i--){
for (j = 5; j >= i; j--)
{
printf(" ");
}
for (k = 0; k < i*2-2; k++) {
printf("*");
}
printf("\n");
}
return 0;
}
对于上述程序大家能猜出有什么功能吗?想必一定有些吃力吧!上述程序的功能是打印一个菱形。就这么简单的功能实现的代码不仅让读者您有点蒙,作为写这个小程序的笔者我都快写的程序失控,调试了半天才做出想要的结果。那么有没有什么好的方法既能使程序写起来逻辑清晰,读者阅读起来也轻松明了呢?
抽象化后的程序
抽象化,按照笔者我的理解就是将一段很复杂的程序拆分成各个拥有独立功能的小模块,这些小模块之间尽量降低耦合性。这样一个很复杂的功能实现就可以有多个简单的小模块相互拼接而成!例如抽象化后的打印矩形程序:
//画横线
void drawLine(int length)
{
for (int i = 0; i < length; i++) {
printf("*");
}
printf("\n");
}
//画实心矩形
void drawRec(int d, int g)
{
for (int i = 0; i < g; i++) {
drawLine(d);
}
}
有没有感到相比之前逻辑更清晰了呢!有人可能想问了,“你这样不是平添了很多工作量吗?本来我只要写一个函数的。”没错,可大家是否想过如果我们拆分出的功能模块是可以被其他程序所利用的,这样自然而然降低了程序的冗余。例如我还要写一个画空心矩形的程序:
//画端点
void drawDD(int length)
{
printf("*");
for (int i = 0; i < (length - 2); i++) {
printf(" ");
}
printf("*\n");
}
//画空心矩形
void drawBlankRec(int d, int g) {
drawLine(d);
for (int i = 0; i < (g - 2); i++) {
drawDD(d);
}
drawLine(d);
}
你看上述程序就同样调用了**“画横线”**这个功能。
现附上我实现所画图形功能的源代码,大家体会一下吧!
#include<stdio.h>
//画横线
void drawLine(int length)
{
for (int i = 0; i < length; i++) {
printf("*");
}
printf("\n");
}
//画横线不换行
void drawL(int length)
{
for (int i = 0; i < length; i++) {
printf("*");
}
}
//画端点
void drawDD(int length)
{
printf("*");
for (int i = 0; i < (length - 2); i++) {
printf(" ");
}
printf("*\n");
}
//画四端点
void drawFP(int length)
{
if (length > 6 ) {
printf("*");
printf(" ");
printf("*");
for (int i = 0; i < length-6; i++) {
printf(" ");
}
printf("*");
printf(" ");
printf("*\n");
} else {
printf("宽应该大于六");
}
}
//有距离的画横线
void drawHWithJL(int j, int c)
{
for (int i = 0; i < j; i++) {
printf(" ");
}
for (int i = 0; i < c; i++) {
printf("*");
}
printf("\n");
}
//画实心矩形
void drawRec(int d, int g)
{
for (int i = 0; i < g; i++) {
drawLine(d);
}
}
//画空心矩形
void drawBlankRec(int d, int g) {
drawLine(d);
for (int i = 0; i < (g - 2); i++) {
drawDD(d);
}
drawLine(d);
}
//画回字
void drawHui(int d, int g) {
if (g > 6) {
//第一行
drawLine(d);
//第二行
drawDD(d);
//第三行
printf("*");
printf(" ");
drawL(d-4);
printf(" ");
printf("*\n");
//中间的行
for (int i = 0; i < (g - 6); i++) {
drawFP(d);
}
//倒数第三行
printf("*");
printf(" ");
drawL(d-4);
printf(" ");
printf("*\n");
//倒数第二行
drawDD(d);
//倒数第一行
drawLine(d);
} else {
printf("高应该大于六");
}
}
//等腰三角形
void drawDY(int d, int g) {
for (int i = 0; i < g; i++)
{
drawHWithJL(d - i, (2*i + 1));
}
}
//倒等腰三角形
void drawDDY(int d, int g) {
for (int i = g; i > 0; i--){
drawHWithJL(d - i + 1, (2*i - 1));
}
}
//画菱形
void drawLX(int z, int g) {
drawDY(z-1,g/2);
drawHWithJL(z- g/2 -1, z + 1);
drawDDY(z-1,g/2);
}
int main()
{
//实心矩形
drawRec(5, 6);
printf("\n");
//空心矩形
drawBlankRec(5, 6);
printf("\n");
//画回字
drawHui(8, 8);
printf("\n");
//画等腰
drawDY(8, 8);
printf("\n");
//画倒三角
drawDDY(8, 8);
printf("\n");
//画菱形
drawLX(8, 8);
return 0;
}