Linux使用双向链表实现图片、音乐、视频的切换和删除功能
Linux检索目录下的后缀文件(.bmp .avi .mp3),并将文件名存入链表中
一、双向链表的实现
1.创建双向链表
- 创建双向链表 结构体
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
//创建链表结构体
typedef struct bmp_node{
char data[32]; //数据域
struct bmp_node *prev; //指针域
struct bmp_node *next;
}BmpNode;
2.创建链表头结点
//创建双向链表头
BmpNode *D_R_List_Create(void)
{
//申请堆空间
BmpNode *list=(BmpNode *)malloc(sizeof(BmpNode));
if(list == NULL)
{
perror("malloc failed");
return NULL;
}
list->prev=list;
list->next=list;
return list;
}
2.链表节点添加
//双向链表节点添加(尾插法)
bool list_add_node_tail(BmpNode *head,char *data)
{
//申请堆空间
BmpNode *newnode=(BmpNode *)malloc(sizeof(BmpNode));
if(newnode == NULL)
{
perror("malloc failed");
return false;
}
//对新结点赋值
strcpy(newnode->data,data);
newnode->prev=newnode;
newnode->next=newnode;
//处理后继指针
head->prev->next=newnode;
newnode->next=head;
//处理前继指针
newnode->prev=head->prev;
head->prev=newnode;
return true;
}
3.链表删除
//链表节点删除
bool list_node_remove(BmpNode *head,char *data)
{
BmpNode *p=head->next;
while(p != head)
{
if(p->data == data)
{
printf("删除节点成功\n");
p->prev->next=p->next;
p->next->prev=p->prev;
free(p);
return true;
}
p=p->next;
}
printf("删除节点失败:没有这个节点\n");
return false;
}
4.链表数据显示
//链表数据显示
void D_R_List_Show_Data(BmpNode *head)
{
BmpNode *p=head->next;
printf("链表数据为:");
while(p!=head)
{
printf("%s",p->data);
p=p->next;
}
printf("\n");
}
5.链表销毁
//链表销毁
void list_destory(BmpNode *head)
{
int i;
BmpNode *p=head->next;
while(p != head)
{
i++;
p=p->next;
free(p->prev);
}
printf("一共释放%d个节点",i);
free(head);
printf("链表销毁成功\n");
}
二、查找所需要的文件
1.检索目录下.bmp图片文件并保存到双向链表中,成功返回0
int Search_Dir(BmpNode *head,char *dirpath)
{
DIR *dp=opendir(dirpath); //打开目录
if(NULL == dp)
{
perror("opendir false");
return -1;
}
struct dirent *fp;
char bmp_buf[32];
while(fp=readdir(dp))
{
if(strstr(fp->d_name,".bmp")) //检索bmp文件
{
sprintf(bmp_buf,"%s/%s",dirpath,fp->d_name); //字符串打包
list_add_node_tail(head,bmp_buf);//尾插法插入链表
memset(bmp_buf,0,sizeof(bmp_buf)); //清空数组
}
}
D_R_List_Show_Data(head); //显示链表节点数据
closedir(dp); //关闭文件
return 0;
}
2.检索目录下.avi视频文件,并保存到双向链表中,成功返回0
//检索目录里AVI文件并存入链表
int Search_Dir_Avi(BmpNode *head,char *dirpath)
{
DIR *dp=opendir(dirpath); //打开目录
if(NULL == dp)
{
perror("opendir false");
return -1;
}
struct dirent *fp;
char bmp_buf[32];
while(fp=readdir(dp))
{
if(strstr(fp->d_name,".avi")) //检索文件
{
sprintf(bmp_buf,"%s/%s",dirpath,fp->d_name); //字符串打包
list_add_node_tail(head,bmp_buf); //尾插法插入链表
memset(bmp_buf,0,sizeof(bmp_buf)); //清空数组
}
}
D_R_List_Show_Data(head); //显示链表节点数据
closedir(dp); //关闭文件
return 0;
}
2.检索目录下.mp3音乐文件,并保存到双向链表中,成功返回0
//检索目录里MP3文件数据并存入链表
int Search_Dir_Mp3(BmpNode *head,char *dirpath)
{
DIR *dp=opendir(dirpath); //打开目录
if(NULL == dp)
{
perror("opendir false");
return -1;
}
struct dirent *fp;
char bmp_buf[32];
while(fp=readdir(dp))
{
if(strstr(fp->d_name,".mp3")) //检索文件
{
sprintf(bmp_buf,"%s/%s",dirpath,fp->d_name); //字符串打包
list_add_node_tail(head,bmp_buf); //尾插法插入链表
memset(bmp_buf,0,sizeof(bmp_buf)); //清空数组
}
}
D_R_List_Show_Data(head); //显示链表节点数据
closedir(dp); //关闭文件
return 0;
}
三、双向链表实现的功能
1.实现图片的切换和删除功能
(1)切换上一张、下一张图片
BmpNode *list=D_R_List_Create(); //创建链表
Search_Dir(list,"./picture"); //检索目录
if(...)
{
p=p->next;
if(p==list)
{
p=p->next;
}
show_bmp(800,480,0,0,p->data);
}
if(...)
{
p=p->prev;
if(p==list)
{
p=p->prev;
}
show_bmp(800,480,0,0,p->data);
}
(2)删除图片功能
if(...)
{
remove(p->data);
printf("删除图片成功!\n");
list_node_remove(list,p->data);
p=p->next;
if(p==list)
{
p=p->next;
}
Show_Bmp(640,480, 0, 0, p->data);
}
2.视频和音乐的切换和删除功能和图片的一样的操作
四、实现的难点和总结
(1)strcpy()和“=”直接赋值的区别,个人认为strcpy用于对字符串的堆空间进行拷贝,不改变自身的地址,“=”直接赋值是把字符串的首地址赋值给变量,自身的地址会发生改变。
详情可参考:https://blog.csdn.net/qq_40737025/article/details/103951297
(2)注意双向链表的前指针和尾指针,应指针内容较为抽象,建议画图加深理解双向链表
(3)常用的函数和作用
malloc(sizeof(BmpNode)) :
//申请和BmpNode一样大的栈空间
strcpy(newnode->data,data);
//把data的内容拷贝到newnode->data中
free(p);
//释放p节点的栈空间
perror("opendir false");
//打印错误信息
DIR *dp=opendir(dirpath);
//打开dirpath路径下的目录,成功则返回__dirstream 的结构体,失败返回一个空的指针
strstr(fp->d_name,".bmp");
//若".bmp"是fp->d_name的子串,则返回".bmp"在fp->d_name的首次出现的地址;否则,则返回NULL
memset(bmp_buf,0,sizeof(bmp_buf));
//清空bmp_buf数组