电话号码管理
文章目录
综述
电话号码管理项目功能包括简易菜单、单链表、包括增删改查等基本操作。链表插入采用尾插法。
链表结构
每个节点中内容:
- id id号码
- name 姓名
- phone_number 电话号码
- home_address 家庭地址
- company_address 公司地址
init
int init(PHONE **head)
{
PHONE *newnode = (PHONE *)malloc(sizeof(PHONE));
if(NULL == newnode)
{
return -1;
}
//newnode->value = 0;
newnode->next = NULL;
*head = newnode;
return 0;
}
这段代码是一个函数,名称为 init,它接收一个指向 PHONE 指针的指针,用于指向一个链表的头节点。
这个函数首先使用 malloc 分配一个新的 PHONE 节点,如果分配失败,则返回 -1。
接着,这个函数初始化新节点的值为 0,将 next 指针设置为 NULL。
最后,将链表头节点指针指向新节点,即将 *head 设置为 newnode。
这个函数返回 0 表示初始化成功。
create
int create(PHONE *head)
{
PHONE *p;
p = head;
PHONE *newstudent = (PHONE *)malloc(sizeof(PHONE));
if(NULL == newstudent)
{
return -1;
}
。。。。
newstudent->next = NULL;
while(head->next != NULL)
{
head = head->next;
}
head->next = newstudent;
。。。。
head = p;
}
这段代码是一个函数,名称为 create,它接收一个指向链表头节点的 PHONE 指针。
这个函数首先将指针 p 指向链表头节点 head,以便在后面将链表头节点指针传递回来。
然后,使用 malloc 分配一个新的 PHONE 节点 newstudent,如果分配失败,则返回 -1。
接着,初始化新节点的值,并将 next 指针设置为 NULL。
接下来的代码是在链表的尾部插入新节点,它使用一个循环将指针 head 移动到链表的末尾,即指向最后一个节点。
最后,将新节点插入链表的末尾,即将 head 指向的节点的 next 指针指向新节点。
最后,将指针 head 指向链表头节点,以便将链表头节点指针传递回来。
注意,该函数返回类型为 int,但是没有返回值。如果在分配新节点时发生错误,则返回 -1,否则函数将正常返回。
delete
int delete(PHONE *head)
{
PHONE *p;
p = head;
char name[20];
。。。。。。
while(head->next != NULL)
{
if(strcmp(head->next->name,name) == 0)
{
count++;
PHONE *ptr = head->next;
head->next = ptr->next;
free(ptr);
}
。。。。。
head = p;
printf("\n");
return 0;
}
这段代码中的循环用于遍历链表,查找匹配输入的姓名的节点。
具体地,使用条件判断语句 while 和表达式 head->next != NULL 循环遍历链表,当 head 指向的节点不为 NULL 时,执行循环体内的代码。
循环体内部的条件判断语句 if 判断链表中下一个节点的姓名是否与输入的 name 相等,如果相等,则执行删除操作。
删除操作首先将指针 ptr 指向需要删除的节点,然后将链表中该节点的前一个节点的 next 指针指向该节点的后一个节点,即删除该节点。
最后,释放节点内存,将 head 指针指向下一个节点,继续循环遍历链表,直到遍历完整个链表。
在循环结束后,将指针 head 指向链表头节点,以便将链表头节点指针传递回来。
函数返回 0 表示删除成功。注意,该函数删除的是第一个匹配的节点,如果有多个节点匹配,则只删除第一个匹配的节点。如果链表中没有匹配的节点,则函数将正常返回。
allfree
PHONE *allfree(PHONE *head)
{
while(head->next != NULL)
{
PHONE *ptr = head;
head = head->next;
free(ptr);
}
free(head);
head = NULL;
return head;
}
这段代码用于释放链表中所有节点占用的内存,同时将链表头节点指针置为 NULL。
具体地,使用条件判断语句 while 和表达式 head->next != NULL 循环遍历链表,当 head 指向的节点不为 NULL 时,执行循环体内的代码。
循环体内部的操作首先将指针 ptr 指向当前节点,然后将 head 指针指向下一个节点,最后释放节点内存。
在循环结束后,需要释放链表头节点占用的内存,然后将链表头节点指针置为 NULL。
最后,函数返回 NULL 指针,以便将链表头节点指针传递回来。
需要注意的是,该函数在释放内存时,必须保证链表中至少有一个节点。如果链表为空,或者链表中只有一个节点,需要特殊处理。如果链表中只有一个节点,释放内存后,需要将链表头节点指针置为 NULL,否则会出现野指针的问题。
ANSI颜色转义
printf("\033[1;33m Hello World. \033[0m \n");
颜色列表如下:
none = "\033[0m"
black = "\033[0;30m"
dark_gray = "\033[1;30m"
blue = "\033[0;34m"
light_blue = "\033[1;34m"
green = "\033[0;32m"
light_green -= "\033[1;32m"
cyan = "\033[0;36m"
light_cyan = "\033[1;36m"
red = "\033[0;31m"
light_red = "\033[1;31m"
purple = "\033[0;35m"
light_purple = "\033[1;35m"
brown = "\033[0;33m"
yellow = "\033[1;33m"
light_gray = "\033[0;37m"
white = "\033[1;37m"
字背景颜色范围:40–49 字颜色: 30–39
40: 黑 30: 黑
41:红 31: 红
42:绿 32: 绿
43:黄 33: 黄
44:蓝 34: 蓝
45:紫 35: 紫
46:深绿 36: 深绿
47:白色 37: 白色
输出特效格式控制:
\033[0m 关闭所有属性
\033[1m 设置高亮度
\03[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[30m -- \033[37m 设置前景色
\033[40m -- \033[47m 设置背景色
光标位置等的格式控制:
\033[nA 光标上移n行
\03[nB 光标下移n行
\033[nC 光标右移n行
\033[nD 光标左移n行
\033[y;xH设置光标位置
\033[2J 清屏
\033[K 清除从光标到行尾的内容
\033[s 保存光标位置
\033[u 恢复光标位置
\033[?25l 隐藏光标
\33[?25h 显示光标
Makefile
顶层Makefile
include scripts/Makefile
#包含
scripts/Makefile 文件。它可能包含其他变量、目标和规则,以及其他可能需要在此Makefile中使用的脚本和功能。
modules_make = $(MAKE) -C $(1);
modules_clean = $(MAKE) clean -C $(1);
#这些是两个变量,用于执行每个模块的make命令和clean命令。这些变量可以通过参数传递需要操作的模块的名称。
.PHONY: all mm mc clean
#这是一个特殊目标,告诉Make,这些目标不是文件名,而是伪目标。它告诉Make无论如何都要执行它们。
all: $(Target)
#这是一个目标,告诉Make要构建$(Target)。它将在mm目标后执行。
mm:
@ $(foreach n,$(Modules),$(call modules_make,$(n)))
#这是一个目标,用于执行每个模块的make命令。它使用foreach循环来迭代所有的模块名称,并通过modules_make变量调用make命令。
mc:
@ $(foreach n,$(Modules),$(call modules_clean,$(n)))
#这是一个目标,用于执行每个模块的clean命令。它使用foreach循环来迭代所有的模块名称,并通过modules_clean变量调用clean命令。
$(Target) : mm
$(CC) $(CFLAGS) -o $(Target) $(AllObjs) $(Libs)
@ echo $(Target) make done!
#这是一个目标,告诉Make要构建$(Target)。它在mm目标完成后执行。它使用$(CC)编译器,$(CFLAGS)编译选项和$(Libs)链接库来编译所有的目标文件,并将它们链接成可执行文件。
clean : mc
rm -rf $(Target)
@ echo clean done!
#这是一个目标,告诉Make清理项目。它在mc目标完成后执行。它使用rm命令来删除$(Target)和其他生成的文件。
#这些是命令,用于输出构建和清理操作完成的消息。前面的@符号告诉Make不要输出命令本身,只输出命令的结果。
scripts Makefile
CC := gcc
CFLAGS := -Wall -O3
Libs = -lpthread
Target := phone
Source := $(wildcard ./*.c)
Objs := $(patsubst %.c,%.o,$(Source))
Modules += allfree create delete display init login menu search main
AllObjs := $(addsuffix /*.o,$(Modules))
Makefile 文件中包含了一些特殊的变量和命令,可以指导 Make 工具根据代码的依赖关系自动化构建程序。
在这段代码中,首先定义了一些变量:
- CC:C 编译器名称;
- CFLAGS:编译器选项,包括 -Wall 和 -O3;
- Libs:需要链接的库文件,这里是线程库;
- Target:目标程序名,这里是 phone;
- Source:所有源文件的路径和名称;
- Objs:所有对象文件的路径和名称,通过把源文件的扩展名 .c 替换为 .o 得到;
- Modules:项目中所有模块的名称,这里是 allfree、create、delete、display、init、login、menu、search 和 main;
- AllObjs:所有模块的对象文件路径和名称,通过在模块名后加上 /* 和 .o 得到。
接下来是一些命令,以及命令的依赖关系和规则:
- .PHONY:声明了一个伪目标,表示这些目标不是实际存在的文件,只是用来作为 make * 的执行目标;
- all:构建目标程序 phone,依赖于所有对象文件 $(Objs) 和链接库 $(Libs);
- $(Target):生成目标程序 phone,依赖于所有对象文件 $(Objs) 和链接库 $(Libs);
- $(Objs):编译所有源文件 $(Source),每个源文件对应一个对象文件;
- $(Modules):每个模块都要编译成一个对象文件,依赖于对应的源文件;
- clean:删除所有对象文件 $(Objs) 和目标程序 $(Target)。
通过执行 make 命令,根据 Makefile 文件中的定义,自动编译源代码,并生成目标程序。
search main init include display delete create allfree 目录下Makefile
include ../scripts/Makefile
all : $(Objs)
clean :
rm -rf $(Objs)
这是一个简单的 Makefile,它包含另一个 Makefile,该 Makefile 位于 scripts 目录中(假定为父目录级别),并定义了两个目标,all 和 clean。
all 目标依赖于目标文件($(Objs)),并仅构建它们。实际的构建命令没有在此 Makefile 片段中显示,但应该在包含的 Makefile(…/scripts/Makefile)中定义。
clean 目标删除目标文件
result