vi编辑器makefile的使用以及双向链表
一、makefile
Makefile :用来管理代码的编译和链接
make工具解释
名称:Makefile、makefile(只有两种形式,首字母大写或小写)
Makefile的语法:
gcc main.c fun.c -o a.out -I$(INC) -L$(LIB)
目标文件:a.out
依赖文件:main.c fun.c
(注:$(OBJ) : $(SRC))
-I : 指定头文件所在位置
-L:指定使用到的库所在的位置
语法规则:
目标文件:依赖文件
编译方法
Makefile中的变量(没有确切的数据类型):
1. 自定义变量
定义:
变量名=值
引用:
$(变量名)
OBJ=a.out
$(OBJ) ----->a.out
2. 系统变量
$^: 所有依赖
$<:第一个依赖
$@:生成的目标
时间戳:在编译代码时,只编译修改后的源文件,其他没有修改的,只进行链接即可。
#a.out:main.c link.c
# gcc main.c link.c -o a.out#自定义变量
#需要生成的目标
OBJ=a.out#生成目标依赖的二进制文件
SRC=main.o
SRC+=link.o
#编译器
CC=gcc
#头文件所在位置
INC=../include
#库所在位置
LIB=../lib#生成目标文件的编译规则
$(OBJ):$(SRC)$(CC) $^ -o $@ -I$(INC) -L$(LIB)#生成二进制文件的编译规则
%.o:%.c$(CC) -c $^ -o $@ -I$(INC) -L$(LIB)#main.o:main.c
# $(CC) -c $^ -o $@#link.o:link.c
# $(CC) -c $^ -o $@#伪指令:make clean执行该指令:删除目标文件和一些中间文件
clean:rm $(OBJ) *.o
二、gcc编译的四个步骤
预处理:处理和#相关的指令
gcc -E main.c -o main.i
编译:将源程序转换成汇编指令
gcc -S main.i -o main.s
汇编:将汇编指令生成二进制指令
gcc -c main.s -o main.o
链接:处理多文件及函数的链接关系
gcc main.o -o app
三、双向链表
(1)创建双向链表
①在头文件(.h)中声明
#ifndef __DOULINK_H__
#define __DOULINK_H__
//双向链表存储的数据类型
typedef struct stu
{int id;char name[32];int score;
}Data_type_t;/*双向链表的结点类型*/
typedef struct dounode
{Data_type_t data;struct dounode *ppre; //指向前驱结点的指针struct dounode *pnext; //指向后继结点的指针
}DNode_t;/*双向链表对象类型*/
typedef struct doulink
{DNode_t *phead; //双向链表头结点地址int clen; //双向链表结点个数
}DLink_t;
②在编写文件(.c)中编写创建双向链表函数
DLink_t *create_doulink()
{DLink_t *dplink = malloc(sizeof(DLink_t));if(dplink == NULL){printf("error\n");return NULL; }dplink -> phead = NULL;dplink -> clen = 0;return dplink;
(2)判断链表是否为空
int is_empty_doulink(DLink_t *dplink)
{return NULL == dplink -> phead;
}
(3)遍历双向链表(正向遍历,逆向遍历)
void printfDouLink(DLink_t *dplink, int dir)
{DNode_t *ptmp = NULL;if(dplink->phead == NULL){return ;}ptmp = dplink -> phead;if(dir){while(ptmp != NULL){printf("%d ,%s , %d\n",ptmp -> data.id,ptmp ->data.name,ptmp ->data.score);ptmp = ptmp -> pnext;}puts("");}else{while(ptmp -> pnext != NULL){ptmp = ptmp -> pnext;}while(ptmp != NULL){printf("%d ,%s , %d\n",ptmp -> data.id,ptmp ->data.name,ptmp ->data.score);ptmp = ptmp -> ppre;}}
}
(4)插入数据
①头插
int insert_doulink_head(DLink_t *dplink,Data_type_t data)
{DNode_t *pnode = malloc(sizeof(DNode_t));if(pnode == NULL){printf("error\n");return -1;}pnode -> data = data;pnode -> pnext = NULL;pnode -> ppre = NULL;if(is_empty_doulink(dplink)){dplink -> phead = pnode;}else{pnode -> pnext = dplink -> phead;dplink -> phead -> ppre = pnode;dplink -> phead = pnode;}dplink -> clen++;return 0;
}
②尾插
int insert_doulink_tail(DLink_t *dplink, Data_type_t data)
{DNode_t *ptmp = dplink -> phead;while(ptmp -> pnext != NULL){ptmp = ptmp -> pnext;}DNode_t *pnode = malloc(sizeof(DNode_t));if(pnode == NULL){printf("error\n");return -2;} pnode -> data = data;pnode -> pnext = NULL;pnode -> ppre = NULL;if(is_empty_doulink(dplink)){insert_doulink_head(dplink,data);}ptmp -> pnext = pnode;pnode -> ppre = ptmp;dplink -> clen++;return 0;
}
(5)
①头删
int delate_doulink_head(DLink_t *dplink)
{if(dplink -> phead == NULL){return -1;}DNode_t *ptmp = NULL;if(dplink -> clen == 1){ptmp = dplink -> phead;dplink -> phead = NULL;free(ptmp);ptmp = NULL;}ptmp = dplink -> phead;DNode_t *pnode = ptmp -> pnext; dplink -> phead = pnode;pnode -> ppre = NULL;free(ptmp);ptmp = NULL;dplink -> clen--;return 0;
}
②尾删
int delate_doulink_tail(DLink_t *dplink)
{if(dplink -> phead == NULL){return -1;}if(dplink -> clen == 1){delate_doulink_head(dplink); }DNode_t *ptmp = dplink -> phead;while(ptmp -> pnext != NULL){ptmp = ptmp -> pnext;}ptmp -> ppre -> pnext = NULL;free(ptmp);ptmp = NULL;return 0;
}
(6)销毁链表
void destroy_doulink(DLink_t *dplink)
{if(dplink -> phead == NULL){return ;}DNode_t *ptmp = NULL;ptmp = dplink -> phead;DNode_t *pnode = NULL;while(ptmp != NULL){pnode = ptmp -> pnext;free(ptmp);ptmp = pnode;}free(dplink);ptmp = NULL;
}
(7)
①通过名字找节点,返回其地址
DNode_t *find_doulink_name(DLink_t *dplink,char *name)
{if(dplink == NULL || name == NULL){return NULL;}DNode_t *ptmp = dplink -> phead;while(ptmp != NULL){if(strcmp(ptmp->data.name , name) == 0){return ptmp;}ptmp = ptmp -> pnext; }return NULL;
}
②通过名字修改其分数
int findname_doulink_changeScore(DLink_t *dplink,char *name,int newscore)
{if(dplink -> phead == NULL && name == NULL){return 0;}DNode_t *ret = NULL;ret = find_doulink_name(dplink,name);ret ->data.score = newscore;return newscore;
}
(8)删除某个指定节点
int delnode_doulink_appoint(DLink_t *dplink,int k)
{if(dplink -> phead ==NULL){return 0;}if(dplink -> clen == 1){delate_doulink_head;}DNode_t *ptmp = dplink -> phead;int i;for(i = 1;i <= k - 1;++i){ptmp = ptmp -> pnext;}ptmp->ppre->pnext = ptmp->pnext;ptmp->pnext->ppre = ptmp->ppre;free(ptmp);ptmp = NULL;return 1;
}