根据前面几篇关于C语言的抽象类型及模块化开发的知识,一方面总结知识,另一方面通过实例来增加理解,使其真正转化为自己的能力和思想,使强大而又古老的C语言不再枯燥,挖掘它的高级语言特性。我们简单回顾一下相关知识:

重点有:

1)接口定义,只重行为,不重底层实现,给予实现层充分的自由。

2)模块化划分再加上接口层,实现层和客户层,多种形式,使程序易于开发和维护

 

这里我们主要应用前面几篇博文中提到的关于模块块开发及抽象数据类型的相关知识,结合一个常见的数据结构题目,练习体会一下。题目如下:

显然,此题目中的问题涉及堆栈和队列相关数据类型,为了实现最大程度的代码重用,我们让堆栈和队列抽象类型的底层均基于链表,那我们就可以实现一个链表抽象类型,并以此为基础,来实现堆栈和队列的抽象类型。

此程序共有9个文件,按类型和功能划分为:

1)主模块:parking.c 和它的头文件parking.h

2)链表抽象类型:接口定义list.h,接口实现list_impl.h和list.c

3)堆栈抽象类型: 接口定义 stack.h ,接口实现 stack.c

4)队列抽象类型:接口定义 queue.h 接口实现 queue.c

 

下面看代码:

链表抽象类型的接口:

  1 /* list.h --- 
  2  * 
  3  * Filename: list.h
  4  * Description: 链表抽象接口定义
  5  * Author: magc
  6  * Maintainer: 
  7  * Created: 五  8月 17 10:02:41 2012 (+0800)
  8  * Version: 
  9  * Last-Updated: 六  8月 18 00:41:41 2012 (+0800)
 10  *           By: magc
 11  *     Update #: 82
 12  * URL: 
 13  * Keywords: 
 14  * Compatibility: 
 15  * 
 16  */
 17 
 18 /* Commentary: 
 19  * 
 20  * 
 21  * 
 22  */
 23 
 24 /* Change Log:
 25  * 
 26  * 
 27  */
 28 
 29 /* Code: */
 30 
 31 #ifndef _list_h
 32 #define _list_h
 33 
 34 
 35 
 36 #include "../commonlib/genlib.h"
 37 
 38 /*
 39  * struct :链表抽象类型,
 40  * listCDT:不完全类型,有待实现层去定义
 41  */
 42 typedef struct listCDT *listADT;
 43 
 44 
 45 
 46 /*
 47  * struct :链表单元结构定义
 48  * data:为了提高此属性的适用范围,特将它设为void *类型,在获取具体数据时,需要显式转换该指针类型为目标类型
 49  */
 50 typedef struct listCellT{
 51     void *data;              //此处用通用指针类型,便于存放各种指针类型的数据,只是在取指针类型时,需要强制转换一下指针类型。
 52     struct listCellT *next;  //指向下一个元素
 53 } *listCellP;
 54 
 55 /*************************************************************************
 56 *功能描述:创建新链表
 57 *参数列表:
 58 *返回类型:
 59 **************************************************************************/
 60 listADT NewList(void);
 61 
 62 /*************************************************************************
 63 *功能描述:释放链表
 64 *参数列表:
 65 *返回类型:
 66 **************************************************************************/
 67 void FreeList(listADT list);
 68 
 69 /*************************************************************************
 70 *功能描述:在链表前端添加元素
 71 *参数列表:
 72 *返回类型:
 73 **************************************************************************/
 74 void AddCellAheadList(listADT list,listCellP cell);
 75 
 76 /*************************************************************************
 77 *功能描述:在链表后端添加元素
 78 *参数列表:
 79 *返回类型:
 80 **************************************************************************/
 81 void AddCellRearList(listADT list , listCellP cell);
 82 
 83 /*************************************************************************
 84 *功能描述:在链表前端删除元素
 85 *参数列表:
 86 *返回类型:
 87 **************************************************************************/
 88 listCellP RemoveCellAheadList(listADT list);
 89 
 90 /*************************************************************************
 91 *功能描述:在链表后端删除元素
 92 *参数列表:
 93 *返回类型:
 94 **************************************************************************/
 95 listCellP RemoveCellRearList(listADT list);
 96 
 97 /*************************************************************************
 98 *功能描述:链表长度
 99 *参数列表:
100 *返回类型:
101 **************************************************************************/
102 int LenthList(listADT list);
103 
104 /*************************************************************************
105 *功能描述:链表是否为空
106 *参数列表:
107 *返回类型:
108 **************************************************************************/
109 bool IsEmptyList(listADT list);
110 
111 /*************************************************************************
112 *功能描述:回调函数(映射函数),用来在打印内容时,让客户端个性化信息
113 *参数列表:
114 *返回类型:
115 **************************************************************************/
116 typedef void (*printCell)(void *data);
117 
118 /*************************************************************************
119 *功能描述:打印输出链表元素内容
120 *参数列表:
121 *返回类型:
122 **************************************************************************/
123 void PrintList(printCell printc,listADT list);
124 
125 
126 #endif
127 
128 /* list.h ends here */

链表单元结构定义

 1 /* list_impl.h --- 
 2  * 
 3  * Filename: list_impl.h
 4  * Description: 链表元素类型底层实现
 5  * Author: magc
 6  * Maintainer: 
 7  * Created: 五  8月 17 16:16:42 2012 (+0800)
 8  * Version: 
 9  * Last-Updated: 六  8月 18 00:39:43 2012 (+0800)
10  *           By: magc
11  *     Update #: 6
12  * URL: 
13  * Keywords: 
14  * Compatibility: 
15  * 
16  */
17 
18 /* Commentary: 
19  * 
20  * 
21  * 
22  */
23 
24 /* Change Log:
25  * 
26  * 
27  */
28 
29 /* Code: */
30 
31 #ifndef _list_impl_h
32 #define _list_impl_h
33 
34 /*
35  * struct :链表单元类型结构定义
36  * 为了使这一种底层实现被多个抽象类型重用,特单独放到这个文件中,
37  */
38 struct listCDT{
39     int count;   //元素个数
40     listCellP head;  //头部指针,指向链表的第一个元素
41     listCellP rear;  ///尾部指针,指向链表最后个元素
42 };
43 
44 #endif
45 
46 /* list_impl.h ends here */

注:将此类型定义单独出来,是为了让后面链表、堆栈和队列三个抽象类型都能引用到,都能重用这同一个类型定义。

链表抽象类型的实现:

/* list.c --- 
 * 
 * Filename: list.c
 * Description:链表的实现 
 * Author: magc
 * Maintainer: 
 * Created: 五  8月 17 10:56:58 2012 (+0800)
 * Version: 
 * Last-Updated: 五  8月 17 23:50:32 2012 (+0800)
 *           By: magc
 *     Update #: 164
 * URL: 
 * Keywords: 
 * Compatibility: 
 * 
 */

/* Commentary: 
 * 链表抽象类型的实现
 * 
 * 
 */

/* Change Log:
 * 
 * 
 */

/* Code: */
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include "../commonlib/genlib.h"
#include "../commonlib/strlib.h"
#include "list.h"
#include "list_impl.h"
/*************************************************************************
*功能描述:创建新链表
*参数列表:
*返回类型:
**************************************************************************/
listADT NewList(void){
    listADT list = New(listADT);
    list->count = 0;
    list->head = NULL;
    list->rear = NULL;
    return list;
    
}

/*************************************************************************
*功能描述:释放链表
*参数列表:
*返回类型:
**************************************************************************/
void FreeList(listADT list){
    //遍历各元素,将元素释放
    listCellP cell = list->head;

    //每个指针类型的属性都是看作地雷,一定要处理好。否则后患无穷。
    while(cell != NULL){
        list->head = list->head->next;
        FreeBlock(cell);
        cell = list->head;
    }
    FreeBlock(list);
}

/*************************************************************************
*功能描述:在链表前端添加元素
*参数列表:
*返回类型:
**************************************************************************/
void AddCellAheadList(listADT list,listCellP cell){

    //链接上头部元素
    cell->next = list->head;
    list->head = cell;
    //若空链表,即尾部指针为空时,要处理一下
    if(list->rear == NULL){
        list->rear = cell;
    }
    list->count++;
    //    printf("add--%x\n",list->head);
    
}


/*************************************************************************
*功能描述:在链表后端添加元素
*参数列表:
*返回类型:
**************************************************************************/
void AddCellRearList(listADT list , listCellP cell){

    //若为空链表时即头指针为NULL ,要处理头部指针
    if(list->head == NULL){
        list->head = cell;
    }
    //链接尾部元素
    if(list->rear != NULL){
        list->rear->next = cell;
    }
    list->rear = cell;
    list->count++;
    
}

/*************************************************************************
*功能描述:在链表前端删除元素
*参数列表:
*返回类型:
**************************************************************************/
listCellP RemoveCellAheadList(listADT list){
    if(list->head == NULL) return NULL;
    listCellP cell = list->head;

    list->head = list->head->next;
    cell->next = NULL;  //注意置NULL的次序,再向上一行,就会影响到list->head了。
    //若当前头指针已经为空,说明当前链表已空,需要将rear指针也置NULL
    if(list->head == NULL){
        list->rear = NULL;
    }
    list->count--;
    
    return cell;
    
}


/*************************************************************************
*功能描述:在链表后端删除元素
*参数列表:
*返回类型:
**************************************************************************/
listCellP RemoveCellRearList(listADT list){
    if(list->rear == NULL) Error("链表已为空\n");
    //若从尾部删除元素,则需要找到倒数第二个元素
    listCellP cell = list->head;
    while(cell->next != list->rear){
        cell = cell->next;
    }
    list->rear = cell;
    cell = cell->next;
    list->count--;
    return cell;
}

/*************************************************************************
*功能描述:链表长度
*参数列表:
*返回类型:
**************************************************************************/
int LenthList(listADT list){
    return (list->count);
}


/*************************************************************************
*功能描述:链表是否为空
*参数列表:
*返回类型:
**************************************************************************/
bool IsEmptyList(listADT list){
    return (list->count == 0);
}


/*************************************************************************
*功能描述:打印输出链表元素内容
*参数列表:printc:回调函数名称
*返回类型:
**************************************************************************/
void PrintList(printCell printc,listADT list){

    listCellP cell = list->head;
    if(cell == NULL){
        printf("链表为空。\n");
    }
    while(cell!=NULL){
        printc(cell->data);   //具体打印格式交给回调函数处理,给予客户端个性化机会。
        cell = cell->next;
    }
}



/* list.c ends here */

堆栈接口定义:

  1 /* stack.h --- 
  2  * 
  3  * Filename: stack.h
  4  * Description:抽象数据类型ADT--堆栈 
  5  * Author: magc
  6  * Maintainer: 
  7  * Created: 四  8月  9 08:59:34 2012 (+0800)
  8  * Version: 
  9  * Last-Updated: 六  8月 18 00:44:24 2012 (+0800)
 10  *           By: magc
 11  *     Update #: 88
 12  * URL: 
 13  * Keywords: 
 14  * Compatibility: 
 15  * 
 16  */
 17 
 18 /* Commentary: 
 19  * ADT 接口
 20  * 只定义行为,而不限制底层表示和实现
 21  * 
 22  */
 23 
 24 /* Change Log:
 25  * 2012-8-16 修改cellT结构,将其int属性改为carP类型,以适应栈内存放汽车信息
 26  * 2012-8-17 修改堆栈抽象类型基于链表抽象类型
 27  */
 28 
 29 /* Code: */
 30 #ifndef _stack_h
 31 #define _stack_h
 32 #include "../commonlib/genlib.h"
 33 #include "parking.h"
 34 #include "list.h"
 35 #include "list_impl.h"
 36 
 37 #define MaxStackSize 10
 38 
 39 
 40 
 41 typedef struct stackCDT *stackADT;
 42 
 43 // 堆栈单元类型重用链表抽象类型的单元类型,为了便于使用和理解,给它起了个本土名字。
 44 
 45 typedef listCellP stackElement;
 46 
 47 /** 2012-8-17  改为基于list单元结构的
 48 typedef struct cellT{  
 49     carP car;
 50     struct cellT *next;
 51 } * stackElement;
 52 
 53 
 54 **/
 55 /*************************************************************************
 56 *功能描述:创建新堆栈
 57 *参数列表:
 58 *返回类型:堆栈指针
 59 **************************************************************************/
 60 stackADT NewStack(void);
 61 
 62 /*************************************************************************
 63 *功能描述:释放堆栈内存空间
 64 *参数列表:
 65 *返回类型:
 66 **************************************************************************/
 67 void FreeStack(stackADT stack);
 68 
 69 /*************************************************************************
 70 *功能描述:压栈
 71 *参数列表:
 72 *返回类型:
 73 **************************************************************************/
 74 void Push(stackADT stack ,stackElement element );
 75 
 76 /*************************************************************************
 77 *功能描述:出栈
 78 *参数列表:
 79 *返回类型:弹出的元素
 80 **************************************************************************/
 81 stackElement Pop(stackADT stack);
 82 
 83 /*************************************************************************
 84 *功能描述:判断当前栈是否为空
 85 *参数列表:
 86 *返回类型:TRUE or FALSE
 87 **************************************************************************/
 88 bool StackIsEmpty(stackADT stack );
 89 
 90 /*************************************************************************
 91 *功能描述:判断当前栈是否已满
 92 *参数列表:
 93 *返回类型:
 94 **************************************************************************/
 95 bool StackIsFull(stackADT stack);
 96 
 97 /*************************************************************************
 98 *功能描述:获取当前栈的深度
 99 *参数列表:
100 *返回类型:
101 **************************************************************************/
102 int StackDepth(stackADT stack);
103 
104 /*************************************************************************
105 *功能描述:读取堆栈顶端元素值
106 *参数列表:
107 *返回类型:
108 **************************************************************************/
109 int StackTop(stackADT stack);
110 
111 /*************************************************************************
112 *功能描述:打印堆栈元素的内容
113 *参数列表:
114 *返回类型:
115 **************************************************************************/
116 void StackPrint(stackADT stack);
117 
118 #endif
119 /* stack.h ends here */

堆栈抽象类型的实现:

  1 /* stack1.c --- 
  2  * 
  3  * Filename: stack.c
  4  * Description: 堆栈ADT的实现(链表实现方式)
  5  * Author: magc
  6  * Maintainer: 
  7  * Created: 三  8月 15 08:49:21 2012 (+0800)
  8  * Version: 
  9  * Last-Updated: 六  8月 18 00:47:35 2012 (+0800)
 10  *           By: magc
 11  *     Update #: 297
 12  * URL: 
 13  * Keywords: 
 14  * Compatibility: 
 15  * 
 16  */
 17 
 18 /* Commentary: 
 19  * 底层采用链表的形式实现堆栈
 20  * 同样实现stack.h接口中的行为
 21  * 堆栈的行为,基于链表抽象类型的行为来实现。即重用链表类型
 22  */
 23 
 24 /* Change Log:
 25  * 2012-8-16 修改Push和PoP,压栈和出栈参数为栈单元类型,
 26  * 2012-8-17 修改Pop方法,将弹出的元素next属性适时置NULL
 27  */
 28 
 29 /* Code: */
 30 #include <assert.h>
 31 #include <ctype.h>
 32 #include <errno.h>
 33 #include <limits.h>
 34 #include <string.h>
 35 #include <stdarg.h>
 36 #include <stdlib.h>
 37 #include <stdio.h>
 38 #include "../commonlib/genlib.h"
 39 #include "stack.h"
 40 
 41 // 为了重用链表的类型和行为,使链表作为堆栈类型的一个属性,将它包装起来,所以它的行为都是可以重用链表的。
 42 struct stackCDT {
 43     listADT list;
 44 };
 45     
 46 /*************************************************************************
 47 *功能描述:创建新堆栈实例 
 48 *参数列表:
 49 *返回类型:空堆栈
 50 **************************************************************************/
 51 stackADT NewStack(void){
 52     stackADT stack = New(stackADT);
 53     listADT list = NewList();
 54     stack->list = list;
 55     return stack;
 56 }
 57 
 58 /*************************************************************************
 59 *功能描述:释放堆栈内存空间(每个元素的空间都需要释放)
 60 *参数列表:
 61 *返回类型:
 62 **************************************************************************/
 63 void FreeStack(stackADT stack){
 64     FreeList(stack->list);
 65     FreeBlock(stack);
 66 }
 67 
 68 
 69 /*************************************************************************
 70 *功能描述:压栈 head始终指向栈顶,压栈是从head端添加元素
 71 *参数列表:
 72 *返回类型:
 73 **************************************************************************/
 74 void Push(stackADT stack ,stackElement element){
 75     AddCellAheadList(stack->list,element);
 76 }
 77 
 78 /*************************************************************************
 79 *功能描述:出栈(将栈顶元素弹出)
 80 *参数列表:
 81 *返回类型:弹出的元素
 82 **************************************************************************/
 83 stackElement Pop(stackADT stack){
 84     if(stack == NULL){
 85         Error("堆栈为NULL");
 86     }
 87     //printf("test---%d\n",stack->list->count);
 88     
 89     stackElement temp = RemoveCellAheadList(stack->list);
 90     return temp;
 91 }
 92 
 93 /*************************************************************************
 94 *功能描述:判断当前栈是否为空
 95 *参数列表:
 96 *返回类型:TRUE or FALSE
 97 **************************************************************************/
 98 bool StackIsEmpty(stackADT stack ){
 99     return (stack->list->count == 0);
100     
101 }
102 /*************************************************************************
103 *功能描述:判断当前栈是否已满
104 *参数列表:
105 *返回类型:
106 **************************************************************************/
107 bool StackIsFull(stackADT stack){
108     return (stack->list->count == MaxStackSize);
109 }
110 
111 
112 /*************************************************************************
113 *功能描述:获取当前栈的深度
114 *参数列表:
115 *返回类型:
116 **************************************************************************/
117 int StackDepth(stackADT stack){
118     return stack->list->count;
119 }
120 
121 /*************************************************************************
122 *功能描述:读取堆栈顶端元素值
123 *参数列表:
124 *返回类型:
125 **************************************************************************/
126 int StackTop(stackADT stack){
127     if(stack->list->count == 0)return NULL;
128     return stack->list->head;
129 }
130 /*************************************************************************
131 *功能描述:打印单元信息(作为回调函数)
132 *参数列表:
133 *返回类型:
134 **************************************************************************/
135 
136 
137 static void printCar(void *data){
138     printf("%s,",((carP)data)->number_id);
139     
140  }
141 
142 
143 /*************************************************************************
144 *功能描述:打印堆栈元素的内容
145 *参数列表:
146 *返回类型:
147 **************************************************************************/
148 void StackPrint(stackADT stack){
149     if(stack->list->count == 0) return ;
150     printf("共%d个元素:",StackDepth(stack));
151     PrintList( printCar,stack->list);
152     
153     /***
154     stackElement element = NULL;
155     for(element = stack->list->head;element!=NULL;element = element->next){
156         printf("%s,",((carP)element->data)->number_id);
157     }
158     *****/
159     
160     printf("\n");
161     
162 }
163 
164 
165 /*************************************************************************
166 *功能描述:主函数
167 *参数列表:
168 *返回类型:
169 
170 int main(int argc, char * argv[])
171 {
172     stackADT stack = NewStack();
173     Push(stack,45);
174     Push(stack,55);
175     Push(stack,66);
176     Pop(stack);
177     
178     StackPrint(stack);
179     printf("\n");
180     
181     
182 }
183 **************************************************************************/
184 
185 
186 
187 
188 
189 
190 /* stack1.c ends here */

队列抽象类型的接口定义:

  1 /* queue.h --- 
  2  * 
  3  * Filename: queue.h
  4  * Description:队列抽象类型 接口 
  5  * Author: magc
  6  * Maintainer: 
  7  * Created: 三  8月 15 15:48:10 2012 (+0800)
  8  * Version: 
  9  * Last-Updated: 六  8月 18 00:48:43 2012 (+0800)
 10  *           By: magc
 11  *     Update #: 69
 12  * URL: 
 13  * Keywords: 
 14  * Compatibility: 
 15  * 
 16  */
 17 
 18 /* Commentary: 
 19  * 以一个整数队列为例
 20  * 定义队列的行为:创建/销毁/入队/出队等,遵守先进先出,队首出,队尾入规则。
 21  * 
 22  */
 23 
 24 /* Change Log:
 25  * 2012-8-17 修改队列抽象类型基于链表抽象类型
 26  * 
 27  */
 28 
 29 /* Code: */
 30 #ifndef _queue_h
 31 #define _queue_h
 32 
 33 #include "../commonlib/genlib.h"
 34 #include "list.h"
 35 #include "parking.h"
 36 #include "list_impl.h"
 37 
 38 #define MaxQueueLenth 100
 39 
 40     
 41 /*
 42  * struct :队列抽象类型结构定义
 43  * 
 44  */
 45 typedef struct queueCDT *queueADT;
 46 
 47 //队列的单元重用链表的,为了便于使用,给它起了一个本土名字。
 48 
 49 typedef listCellP qcellP ;
 50 
 51 /* 2012-8-17 注释,此结构定义改为重用链表list.h中的单元结构
 52  * struct :队列单元结构定义
 53  * 
 54 
 55 typedef struct qcellT{
 56     carP car;
 57     struct qcellT *next;
 58     
 59 } *qcellP;
 60  */
 61 /*************************************************************************
 62 *功能描述:创建一个新队列
 63 *参数列表:
 64 *返回类型:
 65 **************************************************************************/
 66 queueADT NewQueue(void);
 67 
 68 /*************************************************************************
 69 *功能描述:销毁一个队列
 70 *参数列表:
 71 *返回类型:
 72 **************************************************************************/
 73 void FreeQueue(queueADT queue);
 74 
 75 /*************************************************************************
 76 *功能描述:进入队列(自队尾进入)
 77 *参数列表:queue:队列实例,num:要进入队列的一个整数
 78 *返回类型:
 79 **************************************************************************/
 80 void EnQueue(queueADT queue , qcellP cell);
 81 
 82 /*************************************************************************
 83 *功能描述:出队列(自队首出)
 84 *参数列表:
 85 *返回类型:队列单元
 86 **************************************************************************/
 87 qcellP DeQueue(queueADT queue);
 88 
 89 /*************************************************************************
 90 *功能描述:判断队列是否已满
 91 *参数列表:
 92 *返回类型:
 93 **************************************************************************/
 94 bool QueueIsFull(queueADT queue);
 95 
 96 /*************************************************************************
 97 *功能描述: 判断是否为空队列
 98 *参数列表:
 99 *返回类型:
100 **************************************************************************/
101 bool QueueIsEmpty(queueADT queue);
102 
103 /*************************************************************************
104 *功能描述:打印输出队列内容(由队首到队尾排列)
105 *参数列表:
106 *返回类型:
107 **************************************************************************/
108 void PrintQueue(queueADT queue);
109 
110 #endif
111 /* queue.h ends here */

队列抽象类型的实现 :

  1 /* queue.c --- 
  2  * 
  3  * Filename: queue.c
  4  * Description:队列模型的实现 
  5  * Author: magc
  6  * Maintainer: 
  7  * Created: 三  8月 15 16:26:17 2012 (+0800)
  8  * Version: 
  9  * Last-Updated: 六  8月 18 00:51:18 2012 (+0800)
 10  *           By: magc
 11  *     Update #: 167
 12  * URL: 
 13  * Keywords: 
 14  * Compatibility: 
 15  * 
 16  */
 17 
 18 /* Commentary: 
 19  * 
 20  * 
 21  * 
 22  */
 23 
 24 /* Change Log:
 25  * 2012-8-17 修改代码,基于并重用链表抽象类型的。
 26  * 
 27  */
 28 
 29 /* Code: */
 30 #include <assert.h>
 31 #include <ctype.h>
 32 #include <errno.h>
 33 #include <limits.h>
 34 #include <string.h>
 35 #include <stdarg.h>
 36 #include <stdlib.h>
 37 #include <stdio.h>
 38 #include "../commonlib/genlib.h"
 39 #include "queue.h"
 40     //为了统一队列与链表抽象类型,将链表类型作为它的一个属性,它的行为也就可以重用链表的了。
 41 struct queueCDT{
 42     listADT list;
 43 };
 44 
 45 
 46 /*
 47  * struct :定义队列类型的具体结构,跟实现方式相关
 48  * 
 49 
 50 struct queueCDT{
 51     qcellP head;              //队首
 52     qcellP end;               //队尾
 53     int lenth;               //队列成员个数
 54 };
 55 
 56 *****/
 57 /*************************************************************************
 58 *功能描述:创建新队列 
 59 *参数列表:
 60 *返回类型:
 61 **************************************************************************/
 62 queueADT NewQueue(void){
 63     queueADT queue = New(queueADT);
 64     listADT list = NewList();
 65     queue->list = list;
 66     return queue;
 67 }
 68 /*************************************************************************
 69 *功能描述:销毁队列
 70 *参数列表:
 71 *返回类型:
 72 **************************************************************************/
 73 void FreeQueue(queueADT queue){
 74     //销毁每个成员 
 75 }
 76 
 77 /*************************************************************************
 78 *功能描述:进入队列(自队尾进入)
 79 *参数列表:queue:队列实例,cell:要进入队列的一个整数
 80 *返回类型:
 81 **************************************************************************/
 82 void EnQueue(queueADT queue , qcellP cell){
 83     //    qcellP cell = New(qcellP);
 84     //    cell->data = num;
 85     //    cell->next = NULL;
 86     AddCellRearList(queue->list,cell);
 87 
 88 }
 89 
 90 /*************************************************************************
 91 *功能描述:出队列(自队首出)
 92 *参数列表:
 93 *返回类型:队列的成员类型
 94 **************************************************************************/
 95 qcellP DeQueue(queueADT queue){
 96     if(QueueIsEmpty(queue))return NULL;
 97     qcellP temp = RemoveCellAheadList(queue->list);
 98     return temp;
 99 }
100 
101 /*************************************************************************
102 *功能描述:判断队列是否已满
103 *参数列表:
104 *返回类型:
105 **************************************************************************/
106 bool QueueIsFull(queueADT queue){
107     return (queue->list->count == MaxQueueLenth);
108 }
109 
110 
111 /*************************************************************************
112 *功能描述: 判断是否为空队列
113 *参数列表:
114 *返回类型:
115 **************************************************************************/
116 bool QueueIsEmpty(queueADT queue){
117     return (queue->list->count == 0);
118 }
119 /*************************************************************************
120 *功能描述:打印单元信息(作为回调函数)
121 *参数列表:
122 *返回类型:
123 **************************************************************************/
124 
125 static void printCar(void *data){
126     printf("%s,",((carP)data)->number_id);
127     
128  }
129 
130 /*************************************************************************
131 *功能描述:打印输出队列内容(由队首到队尾排列)
132 *参数列表:
133 *返回类型:
134 **************************************************************************/
135 void PrintQueue(queueADT queue){
136     printf("当前队列共%d个成员:",queue->list->count);
137     PrintList(printCar,queue->list);
138     /****
139     while(cursor != NULL){
140         printf("%s,",((carP)cursor->data)->number_id);
141         cursor = cursor->next;
142     }
143     ****/
144     printf("\n");
145 }
146 
147 
148 /**
149 int main(int argc, char * argv[])
150 {
151     queueADT queue = New(queueADT);
152     EnQueue(queue,100);
153     EnQueue(queue,200);
154     EnQueue(queue,300);
155     EnQueue(queue,400);
156     DeQueue(queue);
157     
158     PrintQueue(queue);
159 
160     FreeQueue(queue);
161     
162     
163 }
164 **/
165 
166 /* queue.c ends here */

停车场管理主模块:

头文件:

 1 /* parking.h --- 
 2  * 
 3  * Filename: parking.h
 4  * Description: 停车场头文件
 5  * Author: magc
 6  * Maintainer: 
 7  * Created: 四  8月 16 11:41:41 2012 (+0800)
 8  * Version: 
 9  * Last-Updated: 四  8月 16 16:37:40 2012 (+0800)
10  *           By: magc
11  *     Update #: 15
12  * URL: 
13  * Keywords: 
14  * Compatibility: 
15  * 
16  */
17 
18 /* Commentary: 
19  * 
20  * 
21  * 
22  */
23 
24 /* Change Log:
25  * 
26  * 
27  */
28 
29 /* Code: */
30 
31 #ifndef _parking_h
32 #define _parking_h
33 
34 
35 
36 /*
37  * struct :汽车结构类型定义
38  * 
39  */
40 typedef struct carT{
41     string start_time;           //进停车场时间
42     string end_time;             //出停车场时间
43     string number_id;            //车牌
44     
45 } *carP;
46 
47 
48 #endif
49 
50 /* parking.h ends here */
  1 /* parking.c --- 
  2  * 
  3  * Filename: parking.c
  4  * Description: 停车场管理仿真
  5  * Author: magc
  6  * Maintainer: 
  7  * Created: 四  8月 16 09:41:13 2012 (+0800)
  8  * Version: 
  9  * Last-Updated: 六  8月 18 01:14:52 2012 (+0800)
 10  *           By: magc
 11  *     Update #: 475
 12  * URL: 
 13  * Keywords: 
 14  * Compatibility: 
 15  * 
 16  */
 17 
 18 /* Commentary: 
 19  * 
 20  * 
 21  * 
 22  */
 23 
 24 /* Change Log:
 25  * 
 26  * 
 27  */
 28 
 29 /* Code: */
 30 #include <assert.h>
 31 #include <ctype.h>
 32 #include <errno.h>
 33 #include <limits.h>
 34 #include <time.h>
 35 #include <string.h>
 36 #include <stdarg.h>
 37 #include <stdlib.h>
 38 #include <stdio.h>
 39 #include "../commonlib/genlib.h"
 40 #include "../commonlib/random.h"
 41 #include "../commonlib/strlib.h"
 42 #include "stack.h"
 43 #include "queue.h"
 44 #include "parking.h"
 45 #define MaxParkNumber 10         //停车场内车位总数
 46 #define UnitPrice 10             //每小时收费10
 47 
 48 
 49 /*
 50  * struct :停车场结构定义
 51  * 
 52  */
 53 typedef struct parkT{
 54     int car_total;               //当前停车场内车量总数
 55     int income_total;            //当前停车场的收入总数
 56     stackADT car_stack;          //停车场内车位
 57     queueADT car_queue;          //停车场外便道
 58 } * parkP;
 59 
 60 
 61 static string GenCarNumber(void);
 62 static parkP NewPark(void);
 63 static carP NewCar();
 64 static void EnPartingStack(parkP park,carP car);
 65 static void EnParking(parkP park,carP car);
 66 static void EnParkingQueue(parkP park , carP car);
 67 static bool IsFullParking(parkP park);
 68 static bool IsEmptyParking(parkP park);
 69 static void DeParking(parkP park,carP car);
 70 static void ChargeParking(carP car);
 71 static void PrintParking(parkP park);
 72 /*************************************************************************
 73 *功能描述: 主函数
 74 *参数列表:
 75 *返回类型:
 76 **************************************************************************/
 77 int main(int argc, char * argv[])
 78 {
 79     
 80     parkP park = NewPark();
 81     int i;
 82     for (i = 0; i < 15; i++) {
 83         carP car = NewCar();
 84         EnParking(park,car);
 85     }
 86     PrintParking(park);
 87     //以下为模拟数据
 88     carP car_out = NewCar();
 89     car_out->number_id = "TJ48812";
 90     DeParking(park,car_out);
 91 
 92     car_out->number_id = "TJ87694";
 93     DeParking(park,car_out);
 94 
 95     car_out->number_id = "TJ93196";
 96     DeParking(park,car_out);
 97 
 98     car_out->number_id = "TJ59759";
 99     DeParking(park,car_out);
100     
101     car_out->number_id = "TJ44388";
102     DeParking(park,car_out);
103 
104     car_out->number_id = "TJ82153";
105     DeParking(park,car_out);
106 
107     //PrintList(printCar,park->car_stack);
108     PrintParking(park);
109     
110     return 0;
111 }
112 /*************************************************************************
113 *功能描述:打印输出当前停车场的车辆信息
114 *参数列表:
115 *返回类型:
116 **************************************************************************/
117 static void PrintParking(parkP park){
118     printf("停车场内");
119     
120     printf("\n");
121     StackPrint(park->car_stack);
122     printf("停车场便道");
123     
124     printf("\n");
125     PrintQueue(park->car_queue);
126     
127 }
128 /*************************************************************************
129 *功能描述:新进汽车
130 *参数列表:
131 *返回类型:
132 **************************************************************************/
133 static carP NewCar(){
134     carP car = New(carP);
135     car->number_id = GenCarNumber();
136     return car;
137 }
138 /*************************************************************************
139 *功能描述:生成随机车牌号
140 *参数列表:
141 *返回类型:
142 **************************************************************************/
143 static string GenCarNumber(void){
144     int num = RandomInteger(23000,99999);
145     string number = IntegerToString(num);
146     string prex = "TJ";
147     string cn = Concat(prex,number);
148     return cn;
149 }
150 /*************************************************************************
151 *功能描述:创建停车场 
152 *参数列表:
153 *返回类型:
154 **************************************************************************/
155 static parkP NewPark(void){
156     parkP park = New(parkP);
157     park->car_total = 0;
158     park->income_total = 0;
159     park->car_queue = NewQueue();
160     park->car_stack = NewStack();
161     return park;
162 }
163 /*************************************************************************
164 *功能描述:进入停车场
165 *参数列表:
166 *返回类型:
167 **************************************************************************/
168 static void EnParking(parkP park,carP car){
169     if(IsFullParking(park)){
170         //场内满时
171         EnParkingQueue(park , car);
172     }
173     else{
174         //场内有空位时
175         EnPartingStack(park,car);
176     }
177     
178 }
179 /*************************************************************************
180 *功能描述:判断停车场内是否占满
181 *参数列表:
182 *返回类型:
183 **************************************************************************/
184 static bool IsFullParking(parkP park){
185     return (park->car_total >= MaxParkNumber);
186 }
187 /*************************************************************************
188 *功能描述:判断停车场内是否为空
189 *参数列表:
190 *返回类型:
191 **************************************************************************/
192 static bool IsEmptyParking(parkP park){
193      return (park->car_total == 0);
194  }
195 /*************************************************************************
196 *功能描述:进入停车场内部
197 *参数列表:
198 *返回类型:
199 **************************************************************************/
200 static void EnPartingStack(parkP park,carP car){
201     car->start_time = "234";//为了简化问题,这里随便设置一个时间
202     stackElement element = New(stackElement);
203     
204     element->data = car;
205     element->next = NULL;
206     park->car_total ++;
207     
208     Push(park->car_stack,element);
209     printf("车辆:%s进入停车场内\n",car->number_id);
210 }
211 /*************************************************************************
212 *功能描述:进入便道队列
213 *参数列表:
214 *返回类型:
215 **************************************************************************/
216 static void EnParkingQueue(parkP park , carP car){
217     qcellP cell = New(qcellP);
218     cell->data = car;
219     cell->next = NULL;
220     EnQueue(park->car_queue,cell);
221     printf("车辆:%s进入便道队列\n",car->number_id);
222 }
223 /*************************************************************************
224 *功能描述:出场
225 *参数列表:
226 *返回类型:
227 **************************************************************************/
228 static void DeParking(parkP park,carP car){
229     printf("%s出场\n",car->number_id);
230     
231     stackADT stack_temp = NewStack();   ///创建一个临时栈,用来为车让道时暂存。
232     stackElement elem_temp = NULL;  
233     elem_temp = Pop(park->car_stack);
234     //比较当前临时弹出的车辆号码
235     while(elem_temp->data!=NULL){
236         if (StringEqual(((carP)elem_temp->data)->number_id,car->number_id)){
237             break;// 当找到要走的车辆时,终止循环
238         }
239         Push(stack_temp,elem_temp);//将让道的车辆放入临时栈中
240         
241         elem_temp = Pop(park->car_stack);  //继续弹出
242 
243     }
244     if(elem_temp == NULL){
245         printf("在停车场内未找到%s\n",car->number_id);
246     }
247     ((carP)elem_temp->data)->end_time = "2343";//为了简化问题,这里随便设置一个时间
248     ChargeParking((carP)(elem_temp->data));
249     //将临时栈中车辆依次放回停车场内
250     elem_temp = Pop(stack_temp);
251     while(elem_temp!=NULL){
252         ///    elem_temp->next = NULL;
253         Push(park->car_stack,elem_temp);
254         elem_temp = Pop(stack_temp);
255 
256     }
257     //要從便道上隊首的車開進停車場內
258     elem_temp = DeQueue(park->car_queue);  //是否可以统一单元类型
259     if(elem_temp!=NULL){
260         //        elem_temp->next = NULL;  //置NULL的过程应该由queue.c来完成
261         Push(park->car_stack,elem_temp);
262         
263     }
264     
265     
266 }
267 /*************************************************************************
268 *功能描述:出场,收费
269 *参数列表:
270 *返回类型:
271 **************************************************************************/
272 static void ChargeParking(carP car){
273     printf("车辆:%s 出场时间:%s,入场时间:%s\n",car->number_id,car->end_time,car->start_time);
274     
275 }
276 /* parking.c ends here */

注:

1)时间仓促,此程序虽然经过两三天工作之余的精雕细琢,注重模块化和抽象化及代码重用,仍然有很多地方需要修改和细化。

2)模拟数据有些简单,大概验证了一下程序的运行效果。

在gcc下运行结果如下:

 

小结:

1)分析一个问题,一般经过“逐步求精”策略,将大问题划分为多个小问题,然后将各环节,进一步分解为相对独立的方法函数来实现,在数据类型上,可以抽象出相对独立的ADT,如这里我们抽象出多个,如链表,堆栈及队列,而其中链表又作为堆栈和队列的基础类型(重用链表,采用了将链表作为一个结构的属性,相应行为的底层实现就可以利用链表的了)。

2)注意体会模块化开发带来的好处,例如,模块化之后,将程序分解为不同的层次,不同的功能,使程序结构清晰,便于分工合作和集成,开发效率提高,好处多多。

3)注意体会这种一个类型重用另一个类型的方式,如这里链表、堆栈和队列采用相同的单元结构,为了不破坏每个接口定义,将这个公共的结构listCDT都单独放到一个文件里,使相应文件便于引用,不知是否还有其它方式,有待考究。

 

附件:源代码