电话号码管理--链表的简单使用

简介: 电话号码管理--链表的简单使用

综述

电话号码管理项目功能包括简易菜单、单链表、包括增删改查等基本操作。链表插入采用尾插法。

链表结构

每个节点中内容:

  • 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


目录
打赏
0
0
0
0
4
分享
相关文章
|
9月前
|
Golang每日一练(leetDay0110) 零钱兑换I\II Coin Change
Golang每日一练(leetDay0110) 零钱兑换I\II Coin Change
112 0
Golang每日一练(leetDay0110) 零钱兑换I\II Coin Change
LeetCode刷题---19. 删除链表的倒数第 N 个结点(双指针-快慢指针)
LeetCode刷题---19. 删除链表的倒数第 N 个结点(双指针-快慢指针)
|
9月前
【移除链表元素】LeetCode第203题讲解
【移除链表元素】LeetCode第203题讲解
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
76 2
|
9月前
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点.
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点
92 1
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表
LeetCode 83题:删除排序链表中的重复元素【面试】
LeetCode 83题:删除排序链表中的重复元素【面试】
LeetCode 题目 82:删除排序链表中的重复元素 II
LeetCode 题目 82:删除排序链表中的重复元素 II
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等