链表操作练习

要求

现在有一个双向链表,里面要保存歌曲的名字;例如 蔡琴/渡口.mp3

我们把它定义在一个link.h文件中。

#ifndef LINK_H
#define LINK_H
#include <stdlib.h>
#include <stdio.h>
#include <string.h>typedef struct Node
{//保存歌曲的名字  char music_name[64];struct Node* next;struct Node* prior;
}Node;
#endif

这里的 #ifndef、#define 和 #endif 是 C/C++ 中的预处理指令,用于防止头文件被重复包含。 如果 link.h 被 a.c 和 b.c 同时包含,或者在一个文件中被间接包含两次,没有头文件保护会导致编译错误。 #ifndef LINK_H 检查是否没有定义过 LINK_H 这个宏,如果没有定义过,则执行下面的代码;如果已经定义过,则跳过整个块(直到 #endif)。 #define LINK_H 定义 LINK_H 这个宏。

现在我们要做的,是在这个link.h对应的link.c中实现以下的操作,(为了方便,我先给出各个操作的方法名)

1.初始化链表 init_link() ==》创建一个新节点,并初始化指针前后指针为NULL

2.插入节点 int insert_link(const char *name)

3.遍历链表 void traverse_link()==>使用尾插法

4.根据当前歌曲找到下一首歌 find_next_music(char *cur, char *next)

==》如果歌曲存在,返回0,如果歌曲不存在,返回-1

5.根据当前歌曲找到上一首歌 void find_prior_music(char *cur, char *prior)

6.从链表中提取歌手的名字 void get_singer(char *s)

7.清空列表 void clear_link()

在link.c中我们需要先写下这两个语句,

#include "link.h"
//把main.c中华定义的头指针引进来。
extern Node *head;

接下来开始我们的练习。。。。。。。。。。。。

初始化链表

创建一个新节点,并初始化指针前后指针为NULL。

注意head指针所指头结点没有值;

/*
返回值:创建成功返回0,否则返回-1
*/
int init_link() {head = (Node*)malloc(sizeof(Node));if (head== NULL) {printf("初始化失败");return -1;}head->prior = NULL;head->next = NULL;return 0;
​
}

插入节点

思路:使用指针p遍历链表至最后一个节点,新建一个节点,并对之赋值;最后将之插在链表尾部;

/*
参数:音乐名
返回值:操作成功返回0,否则返回-1
处理:使用尾插法插入节点
*/
int insert_link(const char* name) {Node* p = head;while (p->next) {p = p->next;}//新建一个节点Node* newNode = (Node*)malloc(sizeof(Node));if (newNode== NULL) {printf("创建节点失败");return -1;}strcpy_s(newNode->music_name, sizeof(newNode->music_name), name);newNode->prior = p;newNode->next = NULL;p->next = newNode;return 0;
}
知识点:
  1. strcpy(newNode->music_name, name); 是 C 语言中用于 字符串拷贝 的标准库函数,其作用是将源字符串 name 的内容复制到目标字符数组 newNode->music_name 中。

遍历链表

v
oid traverse_link() {Node* p = head->next;while (p) {printf("%s\n", p->music_name);p = p->next;}
}

根据当前歌曲找到下一首歌

思路:遍历链表,找到music_name为cur的节点,返回其下一个节点中的歌曲名

int find_next_music(char *cur, char *next)
{Node *p = head->next;while (p){if (strstr(p->music_name, cur) != NULL){break;}p = p->next;}if (p->next != NULL){strcpy(next, p->next->music_name);return 0;}else {return -1;}}
}

知识点:

strstr() 是 C 语言标准库中的一个字符串处理函数,用于在一个字符串中查找另一个字符串的首次出现位置。

提取当前链表中的歌手名

void get_singer(char *s)
{if (head->next == NULL)return;
​//    其他/以后的以后.mp3char *begin = head->next->music_name;char *p = begin;while (*p != '/')p++;
​strncpy(s, begin, p - begin);s[p - begin] = '\0';  // 确保字符串终止
}

从链表节点中提取歌手名称并存储到 s 指向的缓冲区中 begin 指针指向音乐文件名字符串的开头;循环结束后,p 指向 '/' 字符的位置 使用 strncpy 从 begin 开始拷贝 p - begin 个字符到 s;p - begin 计算的是从字符串开头到 '/' 的字符数(即歌手名的长度)

清空链表

void clear_link()
{Node *p = head->next;while (p){head->next = p->next;free(p);p = head->next;}
}

测试==》main.h和main.c

main.h如下:#ifndef MAIN_H
#define MAIN_H
#include "link.h"
#include<stdlib.h>
#include <stdio.h>
#endif
​
main.c如下:#include "main.h"
Node* head = NULL;      //链表头指针
int main() {//初始化链表if (init_link() == -1){printf("链表初始化失败\n");}insert_link("蔡琴/渡口.mp3");insert_link("蔡琴/你的眼神.mp3");insert_link("蔡琴/绿岛小夜曲.mp3");insert_link("蔡琴/南屏晚钟.mp3");insert_link("蔡琴/给电影人的情书.mp3");traverse_link();char singerName[64];get_singer(singerName);printf("%s", singerName);clear_link();return 0;
}
 

知识点:

1.在main.c中我定义了Node* head = NULL; 在link.c。player.c等要用到链表的文件中我使用extern Node* head;这样做的用意是什么?

==》

为了实现 全局变量的跨文件共享,同时避免重复定义。

ain.c 中定义:这里是全局变量的 定义(分配内存),整个程序只有这一处定义。 其他文件中声明:告诉编译器:"head 已经在别处定义了,直接使用它"。 如果多个 .c 文件都直接定义 Node* head,链接时会报错(重复定义)。

通过 extern 声明,确保全局变量 只定义一次,但可被多个文件访问。

2.为什么在link.h中我没有引入main.h,extern Node* head;还是有效,即编译器怎么知道main.c中定义了Node* head = NULL;?

1.extern 是声明,不是定义:它不分配内存,只是承诺“这个变量会在别处定义”。

2.类型信息来自 Node 的定义:link.h 中的 typedef struct Node {...} 提供了 Node* 的类型信息。

3.符号匹配由链接器完成:链接器通过变量名(head)匹配定义,与头文件无关。

4.不需要 #include "main.h":main.c 的定义和 link.c 的声明通过链接器关联,无需头文件介入。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/79566.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MATLAB制作散点图:从基础到进阶的三种类型讲解

一、什么是散点图 散点图是一种用来展示两个或多个变量之间关系的图表形式。它可以帮助我们直观地观察变量之间是否存在相关性、趋势或异常值&#xff0c;常用于数据分析的初步探索阶段。 二、三种类型散点图 1. 基本二维散点图&#xff1a;最简单、最常用 基本二维散点图的…

模块方法模式(Module Method Pattern)

&#x1f9e0; 模块方法模式&#xff08;Module Method Pattern&#xff09; 模块方法模式是一种结构型设计模式&#xff0c;它将复杂的操作分解成一系列相对简单、独立且单一职责的模块。每个模块负责完成一种具体的操作&#xff0c;其他模块或系统可以通过调用这些模块的公开…

Python中的JSON库,详细介绍与代码示例

目录 1. 前言 2. json 库基本概念 3. json 的适应场景 4. json 库的基本用法 4.1 导 json入 模块 4.2 将 Python 对象转换为 JSON 字符串 4.3 将 JSON 字符串转换为 Python 对象 4.4 将 Python 对象写入 JSON 文件 4.5 从 JSON 文件读取数据 4.6 json 的其他方法 5.…

网狐旗舰大联盟组件源码私测笔记:结构分层、UI重构与本地实操全流程

作为一套衍生于传统网狐架构的源码版本&#xff0c;大联盟这套源码组件可谓是在经典基础上进行了深度重塑。与老版死板的框架风格不同&#xff0c;它不仅对界面做了大刀阔斧的重构&#xff0c;还在组件层级的组织上做了优化。本文将基于一整套源码进行深度解析&#xff0c;强调…

STM32 PulseSensor心跳传感器驱动代码

STM32CubeMX中准备工作&#xff1a; 1、设置AD 通道 2、设置一个定时器中断&#xff0c;间隔时间2ms&#xff0c;我这里采用的是定时器7 3、代码优化01 PulseSensor.c文件 #include "main.h" #include "PulseSensor/PulseSensor.h"/******************…

C++项目容易犯错的点

1. 矩阵q要先定义大小&#xff0c;再赋值。不可以直接赋值。下面这种方式是错误的Eigen::MatrixXd q&#xff1b;q<<1,2&#xff1b;正确的这样的&#xff1a; Eigen::MatrixXd q(2,1); q<<1.4, 1.5; 2. 不要重复加载variables.h头文件&#xff0c;这样变量会被…

在阿里云 Ubuntu 24.04 上部署 RabbitMQ:一篇实战指南

前言 RabbitMQ 是业界常用的开源消息中间件,支持 AMQP 协议,易于部署、高可用、插件丰富。本文以阿里云 ECS 上运行的 Ubuntu 24.04 LTS 为例,手把手带你完成 RabbitMQ 从仓库配置到运行的全流程,并分享在国内环境下常见的坑与对应解决方案。 环境概况 操作系统:Ubuntu …

【论文笔记】SOTR: Segmenting Objects with Transformers

【题目】&#xff1a;SOTR: Segmenting Objects with Transformers 【引用格式】&#xff1a;Guo R, Niu D, Qu L, et al. Sotr: Segmenting objects with transformers[C]//Proceedings of the IEEE/CVF international conference on computer vision. 2021: 7157-7166. 【网…

MinIO实现https访问

Windows下实现MinIO的https访问. 首先需要自己解决证书问题, 这里可以是个人证书 也可以是花钱买的证书. 现在使用个人开发者证书举例子。 将证书数据解压到你知道的目录之下 然后直接使用命令启动MinIO start minio.exe server --certs-dir D:\xxxxx\tools\certs …

基于 jQuery 实现灵活可配置的输入框验证功能

在 Web 表单开发中&#xff0c;输入框验证是保障数据准确性和安全性的关键环节。无论是用户注册、信息提交还是数据录入场景&#xff0c;都需要对用户输入内容进行合法性检查。本文将介绍如何使用 HTML、CSS 和 jQuery 构建一个可灵活配置的输入框验证系统&#xff0c;轻松应对…

Kotlin 04Flow stateIn 和 shareIn的区别

一 Kotlin Flow 中的 stateIn 和 shareIn 一、简单比喻理解 想象一个水龙头&#xff08;数据源&#xff09;和几个水杯&#xff08;数据接收者&#xff09;&#xff1a; 普通 Flow&#xff08;冷流&#xff09;&#xff1a;每个水杯来接水时&#xff0c;都要重新打开水龙头从…

WebRTC 服务器之SRS服务器概述和环境搭建

1.概述 SRS&#xff08;Simple Realtime Server&#xff09;是一款高性能、跨平台的流媒体服务器&#xff0c;支持多种协议&#xff0c;包括 RTMP、WebRTC、HLS、HTTP-FLV、SRT、MPEG-DASH 和 GB28181。本文介绍了 SRS&#xff0c;包括其用途、关键功能、架构和支持协议。SRS 旨…

Dify - Embedding Rerank

注意&#xff1a;v100显卡会出现不适配&#xff0c;不推荐使用 1. 安装 Docker ubuntu 22.04 docker 安装&使用_ubuntu22.04 安装docker-CSDN博客 2. 安装vllm pip install -U xformers torch torchvision torchaudio triton --index-url https://download.pytorch.org/w…

LeetCode:链表的中间结点

1、题目描述 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[3,4,5] 解释&#xff1a;链表只有一个中间结点&#xff…

LabVIEW温控系统热敏电阻滞后问题

在 LabVIEW 构建的温控系统中&#xff0c;热敏电阻因热时间常数大&#xff08;2 秒左右&#xff09;产生的滞后效应&#xff0c;致使控温出现超调与波动。在不更换传感器的前提下&#xff0c;可从算法优化、硬件调整和系统设计等维度着手解决。 ​ 一、算法优化​ 1. 改进 PI…

技术犯规计入个人犯规吗·棒球1号位

在棒球运动中&#xff0c;虽然没有“技术犯规”这一特定术语&#xff0c;但存在多种违规行为或违反规则的情况&#xff0c;通常会导致判罚或处罚。以下是常见的违规行为及相关规则&#xff1a; 1. 投手违规&#xff08;Balk&#xff09; 定义&#xff1a;投手在垒上有跑垒员时…

Python核心技巧 类与实例:面向对象编程的基石

、核心概念图解 &#x1f3af; 类 vs 实例 类&#xff1a;对象的蓝图&#xff08;如"汽车设计图"&#xff09; 实例&#xff1a;类的具体实现&#xff08;如"你的特斯拉Model 3"&#xff09; class MyClass: # 类声明 count 0 # 类…

协程补充---viewModelScope 相关知识点

viewModelScope.launch 默认在 Dispatchers.Default 线程池执行Dispatchers.Default 是一个后台线程池&#xff0c;专门用于 CPU 密集型任务如果需要在主线程执行&#xff0c;必须显式指定 Dispatchers.Main remember 是 Compose 的状态管理函数(queueMenus) 是依赖项&#xff…

linux stm32mp157 GIC-V2 中断处理过程分析

/* ** 中断触发时&#xff0c;调用的 handle_arch_irq 入口地址。 ** 因为此时&#xff0c;挂接的就是 gic_handle_irq 函数&#xff01;gic_handle_irq 是个全局函数指针&#xff0c; ** static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) ** 它是Lin…

动态指令参数:根据组件状态调整指令行为

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…