该系列文章源于《深入理解C指针》的阅读与理解,由于本人的见识和知识的欠缺可能有误,还望大家批评指教。
由于C语言是面向过程编程语言,但是可以借助不透明指针,通过数据结构和适当的技巧实现对数据的封装和一定程度的多态行为。可以隐藏用户无需知道的数据结构和内部操作的细节函数等,降低接口的使用的复杂度,同时降低代码后期的维护的难度和复杂度。
一、代码说明,复杂数据定义在person.h中,数据结构定义在link.h中
person.h代码:
1 #ifndef person_h 2 #define person_h 3 4 typedef struct _person{ 5 char* firstName; 6 char* lastName; 7 char* title; 8 unsigned int age; 9 } Person; 10 11 void initPerson(Person *personPtr, const char* firstNamePtr, const char* lastNamePtr, const char* titlePtr, unsigned int age); 12 void delePerson(Person *personPtr); 13 void dispPerson(Person *personPtr); 14 15 #endif
link.h代码:
1 #ifndef link_h 2 #define link_h 3 4 typedef void* Data; 5 typedef struct _linkedList LinkedList; 6 LinkedList* getLinkedListInstance(); 7 void removeLinkedListInstance(LinkedList* list); 8 void addNode(LinkedList*, Data); 9 Data removeNode(LinkedList *); 10 void dispList(LinkedList *); 11 12 #endif
person.c代码:
1 #include "person.h" 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 void initPerson(Person *personPtr, const char* firstNamePtr, const char* lastNamePtr, const char* titlePtr, unsigned int age){ 7 personPtr->firstName = (char *)malloc(strlen(firstNamePtr) + 1); 8 strcpy(personPtr->firstName, firstNamePtr); 9 personPtr->lastName = (char *)malloc(strlen(lastNamePtr) + 1); 10 strcpy(personPtr->lastName, lastNamePtr); 11 personPtr->title = (char *)malloc(strlen(titlePtr) + 1); 12 strcpy(personPtr->title, titlePtr); 13 personPtr->age = age; 14 15 return; 16 } 17 18 void delePerson(Person *personPtr){ 19 free(personPtr->firstName); 20 free(personPtr->lastName); 21 free(personPtr->title); 22 23 return; 24 } 25 26 void dispPerson(Person *personPtr){ 27 printf("%s info name: %s %s title: %s age: %d ", personPtr->firstName, personPtr->firstName, personPtr->lastName, personPtr->title, per sonPtr->age); 28 29 return; 30 }
link.c代码:
1 #include "link.h" 2 #include "person.h" 3 #include <stdlib.h> 4 5 typedef struct _node{ 6 Data* data; 7 struct _node* next; 8 } Node; 9 10 struct _linkedList{ 11 Node* head; 12 }; 13 14 LinkedList* getLinkedListInstance(){ 15 LinkedList* list = (LinkedList*)malloc(sizeof(LinkedList)); 16 list->head = NULL; 17 18 return list; 19 } 20 21 void removeLinkedListInstance(LinkedList* list){ 22 Node *tmp = list->head; 23 while(tmp != NULL){ 24 free(tmp->data); 25 Node *current = tmp; 26 tmp = tmp->next; 27 free(current); 28 } 29 free(list); 30 } 31 32 void addNode(LinkedList* list, Data data){ 33 Node *node = (Node *)malloc(sizeof(Node)); 34 node->data = data; 35 if(list->head == NULL){ 36 list->head = node; 37 node->next = NULL; 38 }else{ 39 node->next = list->head; 40 list->head = node; 41 } 42 } 43 44 Data removeNode(LinkedList *list){ 45 if(list->head == NULL){ 46 return NULL; 47 }else{ 48 Node* tmp = list->head; 49 Data* data = tmp->data; 50 list->head = list->head->next; 51 free(tmp); 52 53 return data; 54 } 55 } 56 57 void dispList(LinkedList *list){ 58 Node *node = (Node *)malloc(sizeof(Node)); 59 node = list->head; 60 while(node != NULL){ 61 dispPerson(node->data); 62 node = node->next; 63 } 64 65 return; 66 } ~
testPerson.c代码(测试代码):
1 #include "link.h" 2 #include "person.h" 3 #include <stdlib.h> 4 5 int main(int argc, char **argv) 6 { 7 LinkedList *list = getLinkedListInstance(); 8 Person *person = (Person *)malloc(sizeof(Person)); 9 initPerson(person, "Peter", "underWood", "Manager", 36); 10 addNode(list, person); 11 person = (Person *)malloc(sizeof(Person)); 12 initPerson(person, "John", "steveenSoon", "Develop", 28); 13 addNode(list, person); 14 person = (Person *)malloc(sizeof(Person)); 15 initPerson(person, "Tome", "lastSonJack", "pet", 2); 16 addNode(list, person); 17 printf("removeNode before: "); 18 dispList(list); 19 20 printf("removeNode after: "); 21 removeNode(list); 22 dispList(list); 23 24 return 0; 25 }
由于整个代码非常简单,
1)、在link.c代码中有些操作无需用户知晓的,可以通过在头文件中不出现,只在实现中出现,将来打包后,便于隐藏代码。
2)、在link中,将数据的类型定义为void *类型,这样就可以将自己定义的数据类型person就可以借助指针完成方便的替换
3)、为了降低应用的复杂度,可以进一步将函数的实现隐藏,
4)、由于本文只是为了教学演示,所有力求说明应用方法,对代码没有追求
5)、为了方便编译,附加便于自学的Makefile文件:
Makefile代码:
1 testPerson:testPerson.o link.o person.o 2 gcc testPerson.o link.o person.o -o testPerson 3 testPerson.o:testPerson.c link.h person.h 4 gcc -c testPerson.c -o testPerson.o 5 link.o:link.c 6 gcc -c link.c -o link.o 7 person.o:person.c 8 gcc -c person.c -o person.o 9 10 .phony clean: 11 rm *.o 12 .phony cleanA: 13 rm *.o $@
这样,整个项目可以这样编译:make
可以这样清除中间文件:make clean