在某次需求中,如果书籍A有两个属性——名字与编号,当然了每本书籍还会对应一个作者;同时呢,每个作者还会有自己的属性,即名字与作者电话。(这里只是一个假设,实际中书籍与书籍作者不可能只含有这些属性😅)
这样,那么就会有两种实现方式:
main.c文件
#include "stdio.h"
#include "book.h"
#include "lw_oopc.h"int main(void)
{char temp1[10],temp2[10];author*a[10] ;book*b[10];for(int i=0;i<10;++i){// 作者初始化a[i] = (author*)author_new();sprintf(temp1,"a%d",i);sprintf(temp2,"t%d",i);a[i]->vInit(a[i],temp1,temp2);// 书籍初始化b[i] = (book*)book_new();sprintf(temp1,"bn%d",i);sprintf(temp2,"bt%d",i);b[i]->vSetNumberAndTile(b[i],temp1,temp2);b[i]->vSetAuthor(b[i],a[i]);// 显示b[i]->vDisplay(b[i]);}return 0;
}
book.h文件
#ifndef _BOOK_H
#define _BOOK_H#include "lw_oopc.h"// 作者类
CLASS (author)
{void (*vInit) (void*,char*,char*);char* (*vGetName) (void*);char* (*vGetTelNo) (void*);char _name[14];char _telPhoto[20];
};// 书籍类
CLASS (book)
{void (*vSetNumberAndTile) (void*,char*,char*);void (*vSetAuthor) (void*,author*);void (*vDisplay) (void*);char _bookNo[20];char _bookTitle[20];author *_author;
};
#endif //_BOOK_H
book.c文件
#include "book.h"
#include "string.h"
#include "stdio.h"/************ 作者类 **********/// 初始化
static void aInit(void*pointer,char*name,char*tel)
{author*pthis = (author*)pointer;strcpy(pthis->_name,name);strcpy(pthis->_telPhoto,tel);
}// 获取名字
static char* aGetName(void*pointer)
{author*pthis = (author*)pointer;return pthis->_name;
}// 获取电话
static char*aGetTel(void*pointer)
{author*pthis = (author*)pointer;return pthis->_telPhoto;
}
CTOR(author)FUNCTION_SETTING(vInit,aInit);FUNCTION_SETTING(vGetTelNo,aGetTel);FUNCTION_SETTING(vGetName,aGetName);
END_CTOR/********** 书籍类 *********/// 设置书籍的书籍号与名字
static void bSetNumberAndTile(void*pointer,char*no,char*ti)
{book* pthis = (book*)pointer;strcpy(pthis->_bookNo,no);strcpy(pthis->_bookTitle,ti);
}// 设置作者
static void bSetAuthor(void*pointer,author*myAuthor)
{book*pthis = (book*)pointer;pthis->_author = myAuthor;
}// 打印书籍信息
static void bDisplay(void*poniter)
{book *pthis = (book*)poniter;author*myAuthor = pthis->_author;printf("bookNumber:%s bookTitle:%s ",pthis->_bookNo,pthis->_bookTitle);printf("authorName:%s authorTel:%s\n",myAuthor->_name,myAuthor->_telPhoto);
}CTOR (book)FUNCTION_SETTING(vSetAuthor,bSetAuthor);FUNCTION_SETTING(vSetNumberAndTile,bSetNumberAndTile);FUNCTION_SETTING(vDisplay,bDisplay);
END_CTOR
实验结果
main.c
#include "stdio.h"
#include "book.h"
#include "lw_oopc.h"int main(void)
{// 初始化链表头结点bookList*bookInfo = (bookList*)bookList_new();// 新增节点listBookNode*b1 = (listBookNode*)listBookNode_new();b1->vSet(b1,"C language","123123","zhoujie","19891890");bookInfo->vAdd(bookInfo,b1);listBookNode*b2 = (listBookNode*)listBookNode_new();b2->vSet(b2,"java language","123456","zhoujie","1989190");bookInfo->vAdd(bookInfo,b2);listBookNode*b3 = (listBookNode*)listBookNode_new();b3->vSet(b3,"python language","98765","zhoujie","198990");bookInfo->vAdd(bookInfo,b3);// 判断节点是否为空printf("isempty:%d\n",bookInfo->vIsEmty(bookInfo));// 查找书籍信息listBookNode*res = bookInfo->vGetInfoByBookName(bookInfo,"java language");if(res)printf("result1 of finding: %s\n",res->_bookName);else printf("result1:not finding\n");// 显示书籍信息bookInfo->vDispaly(bookInfo);// 删除对应名字的书籍bookInfo->vDeleteBookInfoByName(bookInfo,"java language");// 再次查找删除对应名字的书籍 res = bookInfo->vGetInfoByBookName(bookInfo,"java language");if(res)printf("result2 of finding: %s\n",res->_bookName);else printf("result2: not finding\n");// 显示链表中存储的书籍bookInfo->vDispaly(bookInfo);return 0;
}
book.h
#ifndef _BOOK_H
#define _BOOK_H#include "lw_oopc.h"// 链表相关
CLASS (listBookNode)
{char _bookName[15];char _bookNumber[20];char _authorName[15];char _authorTel[15];listBookNode*next;void (*vInit) (void*);void (*vSet) (void*,char*,char*,char*,char*);
};CLASS (bookList)
{void (*vInit) (void*);void (*vAdd) (void*,listBookNode*);int (*vIsEmty) (void*);listBookNode* (*vGetInfoByBookName) (void*,char*);void (*vDispaly) (void*);void (*vDeleteBookInfoByName) (void*,char*);int listCount;listBookNode* next;
};
#endif //_BOOK_H
book.c
#include "stdio.h"
#include "book.h"
#include "lw_oopc.h"int main(void)
{bookList*bookInfo = (bookList*)bookList_new();listBookNode*b1 = (listBookNode*)listBookNode_new();b1->vSet(b1,"C language","123123","zhoujie","19891890");bookInfo->vAdd(bookInfo,b1);listBookNode*b2 = (listBookNode*)listBookNode_new();b2->vSet(b2,"java language","123456","zhoujie","1989190");bookInfo->vAdd(bookInfo,b2);listBookNode*b3 = (listBookNode*)listBookNode_new();b3->vSet(b3,"python language","98765","zhoujie","198990");bookInfo->vAdd(bookInfo,b3);printf("%d name:%s\n",bookInfo->listCount,bookInfo->next->_bookName);printf("isempty:%d\n",bookInfo->vIsEmty(bookInfo));listBookNode*res = bookInfo->vGetInfoByBookName(bookInfo,"java language");if(res)printf("result1 of finding: %s\n",res->_bookName);else printf("result1:not finding\n");bookInfo->vDispaly(bookInfo);bookInfo->vDeleteBookInfoByName(bookInfo,"java language");res = bookInfo->vGetInfoByBookName(bookInfo,"java language");if(res)printf("result2 of finding: %s\n",res->_bookName);else printf("result2: not finding\n");bookInfo->vDispaly(bookInfo);return 0;
}
结果
Makefile源文件
# 声明伪目标
.PHONY:clean# 指定make最终生成的文件
TARGET := target
# 指定依赖文件
OBJ = book.o $(TARGET) : $(OBJ)gcc -o $@ main.c $^ # 编译某一个文件 $@表示目标 $^表示依赖
%.o : %.cgcc -c -o $@ $^
上述两种实现方式均可使用这个makefile文件。
使用makefile文件的好处是:在某个项目中,如果只有一个文件受到改动,那么编译时就可不必花多余时间编译没有改动过的文件,直接编译已经改动过的文件与主文件即可。(这个现象在一个大工程中更能直观体现,但是在小项目中可以查看编译过程的命令)
&esmp;&esmp;实现上述的优点主要是使用了依赖,也就是说如果某个目标文件的依赖没有发生更新,那么他自己也是不需要更新的。代码体现在:
# 编译某一个文件 $@表示目标 $^表示依赖
%.o : %.cgcc -c -o $@ $^
符号"%"是一个通配符,也就是能够表达符合这个条件的所有文件,比如:%.o可以表示a.o、b.o、c.o、d.o……
报错描述
小编直接使用vscode+gcc无法运行,会出现报错
undefined reference to `bookList_new’
。这个报错小编最终锁定在bookListbookInfo = (bookList)bookList_new();
** 分析及解决方案**
小编分析,这玩意与编译链接有关(这方面小编不太熟悉)。小编最终是使用 vscode+Makefile+gcc,完成编译操作的,当然了运行也是在终端中完成的。
问题描述
当我们在使用类初始化
bookListbookInfo = (bookList)bookList_new();
时,调用的xxx_new()
函数少括号时,编译器是不会发现的,但是实际运行时程序就会卡死。
分析与解决方案
这里的解决方案比较简单,只需要在
xxx_new()
函数后加上一个括号即可。