编程珠玑3-5

chapter 3 数据结构程序

"可用小程序的话就不要编写大程序" 

"问题越一般化,解决起来可能也就越容易" ---Polya <How to Solve It>

直接解决一个23种情况的问题,要比编写一个处理n中情况的通用程序,然后将该程序应用到n=23时的情况更加困难。

程序员在对空间缺乏无能为力时,往往会脱离代码的纠缠,回头过去凝神考虑他的数据,这样会找到更好的方法,表示法是编程的精华。

几个原则:

将重复性的代码改写到数组中。使用最简单的数据结构-数组,来表示一段冗长的相类似的代码往往能达到最佳的效果。

封装复杂的结构。当你需要一个复杂的数据结构时,使用抽象的术语对它进行定义,并将那些操作表示成一个类。

尽可能的使用高级工具。超文本、名称-键值对、电子表格、数据库、语言以及类似的工具在其专门的问题领域内都属于功能强大的工具。

让数据去构造程序。使用适当的数据结构去替换复杂的代码。在编写代码之前,好的程序员会通篇理解构建程序时所围绕的输入数据结构、输出数据结构以及中间数据结构。

chapter 5

main.c 实现一个简单的二分查找例子

#include <stdio.h>

#include <stdlib.h>

#include <assert.h>

 

#define MAXN 15

 

typedef int DataType;

 

DataType x[MAXN];

 

int binarysearch(DataType t, int len)

/* pre condition: x[0]<=x[1]<=...<=x[n-1]

 * post condition: 

 * result == -1  => t not present in x

 * 0 <= result < n => x[result] == t 

 */

{

    int l, h, m;

    l = 0;

    h = len-1;

    while(l<=h)

    {

        m = (l+h)/2;

        printf(" %d %d %d \n", l, m, h);

        if(x[m]<t) l = m + 1 ;

        else if(x[m]==t)

        {

             //使用断言

             assert(0<= m && m <len &&x[m]==t);

             return m;

        }

        else h = m-1;

    }

    //当len为0时,h初始化为-1,此时会越界

    assert((h<0 || x[h]<t) && (h+1>=len || x[h+1]>t));

    return -1;

}

 

 

 

int main()

{

    int i, n, t;

    printf("input size of the arrary and key\n");

    //用一个测试脚手架

    while(scanf("%d %d",&n,&t)!=EOF)

{

        for(i = 0; i<n; i++)

        {    

            x[i]=10*i;

            printf("%d\n",x[i]);

        }

        printf("%d\n",binarysearch(t,n));

    }

    

return 0;

}

makefile:

OBJS = main.o

 

all: $(OBJS)

gcc -o all $(OBJS)

main.o: main.c

# tab键不能随便乱加,如果在一个依赖下(如该句下面)只是有一个tab,程序会出错。

#$@ 目标 $< 第一个依赖文件 $* 没有扩展名的目标名字

#“.PHONY”表示,clean是个伪目标文件。

#在rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事

.PHONY: clean   

clean:

-rm all $(OBJS)

 

脚手架 最好的脚手架就是那种最容易构建的脚手架。最简单的脚手架由一个图形用户界面组成,当然命令行简洁移植性更好。

编码 先使用便利的高级伪码为函数描述骨架,然后再转换为实现语言。

测试 在脚手架中测试组件要比在一个大系统中简单和全面的多。使用断言确保程序的正确性,同时符合逻辑和指定要求。输入、程序变量和输出之间的关系描述了程序的状态:断言可以精确的说明这些关系。例如用断言判断函数的前置条件和后置条件。

计时 确保预期的性能。

"work once twice":系统在第一次处理事务时都是正确的,但在后续的事务中都会出错。查找某个变量,这个变量在后续的事务中,是否被正确的初始化了。

无论在什么情况下,恰当的提问都会引导程序员找出bug:你站着和坐着的时候做了不同的事情吗?我可以看看你每次的登录方式吗?准确的说,推出程序之前你输入了什么?程序在开始失败之前正常工作过吗?有多少次?


本文使用Blog_Backup未注册版本导出,请到soft.pt42.com注册。

posted @ 2011-06-22 05:53  莫忆往西  阅读(160)  评论(0编辑  收藏  举报