输出三角形的思考

作者在 2008-05-05 23:34:47 发布以下内容
天气: 热
心情: 平静

我进入大一的时候写过一些输出图形的小程序,现在想想以前写的程序是比较混乱的,就以输出三角形为例.

我以前是这样写的:

int main()
{
        int i, j, n;
        printf("Please enter the number of col(1~20):\n");
        while(1) {
                scanf("%d",&n);
                if(1<=n && n<=20) {
                        break;
                } else {
                        printf("out of range(1~20),please retype:\n");
                }
        }       

        for(i=0; i<n; i++) {
                for(j=i; j<n-1; j++)
                        printf(" ");
                for(j=0; j<2*i+1; j++)
                        printf("*");
                printf("\n");
        }

        return 0;
}
功能上完全没有什么问题,但是如果站在软件工程的角度来看,就可以发现这个程序把图形的逻辑形成与输出都混在一起,完全没有经过设计。

比较好的做法是把图形参数的获取与图形的逻辑形成,图形的输出分别分开,这样比较易于理解。

根据新的设计方案,我重新编写了代码

/******************************************************************************
*   程序思想把三角形的参数获取和图形的逻辑形成,图形的输出分开,   *
*   这样就只需要关心后面两部分,稍加变动就可以输出各种图形               *
*******************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <memory.h>

typedef struct {//无标识名的结构体申明
    int row;
    int col;
    int *p;
} canvas; //画布结构

int prepare_canvas(canvas *p_cns, /* in/out */
                    int row,  /* in */
                    int col); /* in */
void get_option(int *row, /* out */
                int *col); /* out */
void draw(canvas *p_cns); /*in/out */
void show(const canvas *p_cns);
void release_canvas(canvas *p_cns);  /*in/out*/

/* 提供一个宏,方便访问画布上的像素点 */
#define CANVAS_PIXEL(p_cns, i, j) \
     *((p_cns)->p + (i) * (p_cns)->col + (j))

int main(int argc,  char *argv[]) {
    int     rt, row, col;
    canvas   cns;
   
    get_option(&row, &col);
   
    rt = prepare_canvas(&cns, row, col);
    if (rt != 0) {
        printf("fail to prepare_canvas!\n");
        return NULL;
    }
   
    draw(&cns); //描点逻辑
    show(&cns); //输出逻辑

    release_canvas(&cns);//释放结构体空间
    return 0;
}

//确定画布的大小
void get_option(int *row, int *col) {
    int n;
    do {
        printf("enter the number of lines:\n");
        scanf("%d", &n);
        if (n < 1 || n > 20) {
            printf("out of range(3~20), please re-enter.\n");
        } else {
            *row = n;
            *col = 2 * n -1;
            break;
        }
     } while (1);
}

//准备画图
int prepare_canvas(canvas *p_cns, int row, int col) {

    p_cns->row = row;
    p_cns->col = col;
    p_cns->p = (int*)malloc(row * col * sizeof(int));//为画布分配空间
    if (p_cns->p == NULL) {
        printf("fail to malloc the canvas!\n");
        return -1;
    }
   
    memset(p_cns->p, ' ', row * col * sizeof(int));//将画布上的'像素点'都置为空白
    return 0;
}

void draw(canvas *p_cns) { //生成图形逻辑,我们的focus点
        int row, col;
        for (row = 0; row < p_cns->row; row++) {
                for(col =p_cns->row-1-row ; col <= p_cns->row-1+row; col++) {
                         CANVAS_PIXEL(p_cns, row, col) = '*';
                }
        }
}

void show(const canvas *p_cns) { //图形的通用输出逻辑,此后无须关注
    int row, col;
    for (row = 0; row < p_cns->row; row++) {
                for (col = 0; col < p_cns->col; col++) {
                        printf("%c", CANVAS_PIXEL(p_cns, row, col));
                }
                printf("\n");
        }
}

void release_canvas(canvas *p_cns) {
    if (p_cns->p != NULL) {
        free(p_cns->p);
    }
}
这样即使要输出菱形,也只需要改变get_option() 和draw()函数,方便了很多

默认分类 | 阅读 2932 次
文章评论,共1条
狂人老大
2008-05-06 21:36
1
很强大   学习下
游客请输入验证码
浏览7194次
文章分类