鏈表操作練習

要求

現在有一個雙向鏈表,里面要保存歌曲的名字;例如 蔡琴/渡口.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.pswp.cn/pingmian/79566.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79566.shtml
英文地址,請注明出處:http://en.pswp.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; 藍橋云課簽約作者、…