Linux嵌入式学习——数据结构——队列

一、概念

1)定义 

是只允许在一端进行插入操作,而在另一端进行删除操作的线性表
队列 是一种 先进先出(First In First Out) 的线性表
 
线性表有顺序存储和链式存储,栈是线性表,所以有这两种存储方式
同样,队列作为一种特殊的线性表,也同样存在这两种存储方式
(2)队头

允许删除的一端称为对头
(3)队尾

允许插入的一端称为队尾

二、循环队列

当然,以下是对您提供的函数接口的基本介绍,不包括具体的实现代码:

1. SeqQueue *CreateSeqQueue(int len);

功能
此函数用于创建一个新的顺序队列(SeqQueue),并初始化其容量为len。它分配必要的内存来存储队列的元素,并设置队列的初始状态(如头尾指针、容量等)。

参数

  • int len:指定队列的初始容量,即队列可以存储的最大元素数量。

返回值

  • 返回一个指向新创建的顺序队列的指针。如果内存分配失败,则返回NULL。

SeqQueue *CreateSeqQueue(int len)
{
    SeqQueue * sq = malloc(sizeof(SeqQueue));
    if(NULL == sq)
    {
        perror("CreateSeqQueue");
        return NULL;
    }
    sq->array  = malloc(sizeof(DATATYPE)*len);
    if(NULL == sq->array)
    {
        perror("CreateSeqQueue");
        return NULL;
    }
    sq->head = 0;
    sq->tail = 0 ;
    sq->tlen = len;
    return sq;
}

2. int QuitSeqQueue(SeqQueue *queue);

注意:是从队列中移除并返回头部元素的操作(类似于出队)。

功能
从顺序队列的头部移除一个元素,但此函数的返回值通常应该是被移除的元素的值或操作的状态码(成功/失败)。如果直接返回元素值,可能需要额外的参数来传递该值(如使用指针参数)。

参数

  • SeqQueue *queue:指向要操作的顺序队列的指针。

返回值

  • 如果队列为空,则返回某种错误码(如-1)。如果队列不为空,根据实现,可能返回被移除的元素的值(但通常这种实现会需要一个额外的参数来接收值),或者一个表示成功的状态码(如0或1)。
  • int QuitSeqQueue(SeqQueue *queue)
    {
        if(IsEmptySeqQueue(queue))
        {
            fprintf(stderr,"QuitSeqQueue error\n");
            return 1;
        }
        queue->head= (queue->head +1)%queue->tlen;
        return 0;
    }
    

3. int EnterSeqQueue(SeqQueue *queue, DATATYPE *data);

功能
将一个元素添加到顺序队列的尾部。

参数

  • SeqQueue *queue:指向要操作的顺序队列的指针。
  • DATATYPE *data:指向要添加到队列中的元素的指针。但请注意,更常见的做法是直接传递元素的值(即DATATYPE data),而不是指针。

返回值

  • 如果成功添加元素,则返回1或表示成功的状态码。如果队列已满,则返回0或表示失败的状态码
int EnterSeqQueue(SeqQueue *queue, DATATYPE *data)
{
    if(IsFullSeqQueue(queue))
    {
        fprintf(stderr,"EnterSeqQueue error\n");
        return 1;
    }

    memcpy(&queue->array[queue->tail],data,sizeof(DATATYPE));
    queue->tail = (queue->tail+1)%queue->tlen;
    return 0;

}

4. int IsEmptySeqQueue(SeqQueue *queue);

功能
检查顺序队列是否为空。

参数

  • SeqQueue *queue:指向要检查的顺序队列的指针。

返回值

  • 如果队列为空,则返回1(或非0值,具体取决于设计)。如果队列不为空,则返回0。
int IsEmptySeqQueue(SeqQueue *queue)
{
    return queue->head == queue->tail;
}

5. int IsFullSeqQueue(SeqQueue *queue);

功能
检查顺序队列是否已满。

参数

  • SeqQueue *queue:指向要检查的顺序队列的指针。

返回值

  • 如果队列已满,则返回1(或非0值,具体取决于设计)。如果队列未满,则返回0。
  • int IsFullSeqQueue(SeqQueue *queue)
    {
        return queue->head == (queue->tail+1) %queue->tlen;
    }
    

    空队列和满队列按理说条件是一样的,发明者为了区别开,将满队列的条件 判断tail+1与head相同则满。

6. int DestroySeqQueue(SeqQueue *queue);

功能
销毁顺序队列,释放其占用的所有内存资源。

参数

  • SeqQueue *queue:指向要销毁的顺序队列的指针。

返回值

  • 如果成功销毁队列,则返回1或表示成功的状态码。如果发生错误(尽管在销毁操作中很少出现),则返回0或表示失败的状态码。但在实践中,此函数通常不返回任何值(即返回类型为void)。
  • 
    int DestroySeqQueue(SeqQueue *queue)
    {
        free(queue->array);
        free(queue);
        return 0;
    }

7. DATATYPE* GetHeadSeqQueue(SeqQueue *queue);

功能
获取顺序队列头部的元素,但不从队列中移除它。

参数

  • SeqQueue *queue:指向要操作的顺序队列的指针。

返回值

  • 返回一个指向队列头部元素的指针。如果队列为空,则返回NULL或某种表示空队列的指针(尽管更常见的做法是返回NULL,并让调用者检查是否为空)。
DATATYPE *GetHeadSeqQueue(SeqQueue *queue)
{
    if(IsEmptySeqQueue(queue))
    {
        return NULL;
    }
    return &queue->array[queue->head];
}

 练习:

两个线程。一个分配任务,一个执行任务。
分配任务得线程入队,执行线程,出队执行任务。任务使用队列保存。如果任务内容是over,分配任务线程,等待执行线程一起结束。执行线程执行到over任务,线程结束。

.h

#ifndef SEQQUEUE_H
#define SEQQUEUE_H



//#define error_exit(_errmsg_)	error(EXIT_FAILURE, errno, _errmsg_)
typedef struct
{
    char task_name[50];
    int task_time;
}
DATATYPE;
typedef struct queue {
    DATATYPE *array;
    int tlen;
    int head;
    int tail;
}SeqQueue;
SeqQueue *CreateSeqQueue(int len);
int  QuitSeqQueue(SeqQueue *queue);
int EnterSeqQueue(SeqQueue *queue, DATATYPE *data);
int IsEmptySeqQueue(SeqQueue *queue);
int IsFullSeqQueue(SeqQueue *queue);
int DestroySeqQueue(SeqQueue *queue);
DATATYPE* GetHeadSeqQueue(SeqQueue *queue);
#endif // SEQQUEUE_H

.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <error.h>
#include "seqqueue.h"

SeqQueue *CreateSeqQueue(int len)
{
    SeqQueue * sq = malloc(sizeof(SeqQueue));
    if(NULL == sq)
    {
        perror("CreateSeqQueue");
        return NULL;
    }
    sq->array  = malloc(sizeof(DATATYPE)*len);
    if(NULL == sq->array)
    {
        perror("CreateSeqQueue");
        return NULL;
    }
    sq->head = 0;
    sq->tail = 0 ;
    sq->tlen = len;
    return sq;
}


int EnterSeqQueue(SeqQueue *queue, DATATYPE *data)
{
    if(IsFullSeqQueue(queue))
    {
        fprintf(stderr,"EnterSeqQueue error\n");
        return 1;
    }

    memcpy(&queue->array[queue->tail],data,sizeof(DATATYPE));
    queue->tail = (queue->tail+1)%queue->tlen;
    return 0;

}

int IsEmptySeqQueue(SeqQueue *queue)
{
    return queue->head == queue->tail;
}

int IsFullSeqQueue(SeqQueue *queue)
{
    return queue->head == (queue->tail+1) %queue->tlen;
}

int QuitSeqQueue(SeqQueue *queue)
{
    if(IsEmptySeqQueue(queue))
    {
        fprintf(stderr,"QuitSeqQueue error\n");
        return 1;
    }
    queue->head= (queue->head +1)%queue->tlen;
    return 0;
}

DATATYPE *GetHeadSeqQueue(SeqQueue *queue)
{
    if(IsEmptySeqQueue(queue))
    {
        return NULL;
    }
    return &queue->array[queue->head];
}

int DestroySeqQueue(SeqQueue *queue)
{
    free(queue->array);
    free(queue);
    return 0;
}

main.c

#include <stdio.h>
#include "seqqueue.h"
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

sem_t sem_task;
typedef struct
{
    int id;
    char task_name[50];
    int task_time;
}TASK;

TASK task[]={
    {0,"washing",5},
    {1,"cooking",9},
    {2,"working",3},
    {3,"over",0},

};
void* th(void* arg)
{
    SeqQueue* sq = (SeqQueue* )arg;
    DATATYPE * tmp=NULL;
    while(1)
    {
        sem_wait(&sem_task);
        tmp = GetHeadSeqQueue(sq);
        if(0==strcmp("over",tmp->task_name))
        {
            break;
        }

        while(tmp->task_time--)
        {
            printf("i'm %s\n",tmp->task_name);
            sleep(1);
        }
        QuitSeqQueue(sq);

    }
    return NULL;
}
int main()
{

    pthread_t tid;

    sem_init(&sem_task,0,0);
    SeqQueue* sq = CreateSeqQueue(10);
    pthread_create(&tid,NULL,th,sq);
    int i= 0 ;
    for(i = 0 ;i<4;i++)
    {
        printf("id:%d name:%s time:%d\n",task[i].id,task[i].task_name,task[i].task_time);
    }
    DATATYPE data;
    int end_flag = 1;
    while(end_flag)
    {
        bzero(&data,sizeof(data));
        int num = -1 ;
        char buf[5]={0};
        fgets(buf,sizeof(buf),stdin);
        num = atoi(buf);
        switch (num) {
        case 0:
            strcpy(data.task_name,task[0].task_name);
            data.task_time = task[0].task_time;
            EnterSeqQueue(sq,&data);
            break;
        case 1:
            strcpy(data.task_name,task[1].task_name);
            data.task_time = task[1].task_time;
            EnterSeqQueue(sq,&data);
            break;
        case 2:
            strcpy(data.task_name,task[2].task_name);
            data.task_time = task[2].task_time;
            EnterSeqQueue(sq,&data);
            break;
        case 3: //over
            strcpy(data.task_name,task[3].task_name);
            data.task_time = task[3].task_time;
            EnterSeqQueue(sq,&data);
            end_flag=0;
            break;

        default://over
            strcpy(data.task_name,task[3].task_name);
            data.task_time = task[3].task_time;
            EnterSeqQueue(sq,&data);
            end_flag=0;
            break;
        }
       sem_post(&sem_task);
    }

    pthread_join(tid,NULL);
    sem_destroy(&sem_task);
    DestroySeqQueue(sq);
    printf("Hello World!\n");
    return 0;
}

三、链式队列

链表队列(Linked List Queue)是一种使用链表数据结构实现的队列。队列是一种先进先出(FIFO, First In First Out)的数据结构,它允许在队列的一端(通常是队尾)添加元素,在另一端(通常是队首)移除元素。链表队列通过链表节点来存储队列中的元素,每个节点包含数据部分和指向列表中下一个节点的指针(或引用)

1. LinkQueue *CreateLinkQueue();

功能描述:创建一个空的链式队列。

实现思路

  • 分配内存给LinkQueue类型的指针。
  • 初始化队列的头部和尾部指针为NULL,表示队列为空。
  • 初始化队列的其他可能属性(如队列长度等)。
  • 返回指向新创建的队列的指针。
LinkQueue *CreateLinkQueue()
{
    LinkQueue* lq =(LinkQueue*)malloc(sizeof(LinkQueue));
    if(NULL == lq)
    {
        perror("CreateLinkQueue malloc");
        return NULL;
    }
    lq->head =NULL;
    lq->tail =NULL;
    lq->clen = 0 ;
    return lq;

}

2. int EnterLinkQueue(LinkQueue *queue, DATATYPE *data);

功能描述:向链式队列中插入一个新的元素。

实现思路

  • 创建一个新的节点,将data指针所指向的值复制到新节点的数据域中。
  • 如果队列为空(头部和尾部指针均为NULL),则新节点既是头节点也是尾节点。
  • 如果队列不为空,将新节点插入到尾部,并更新尾部指针指向新节点。
  • 更新队列长度(如果维护了队列长度的话)。
  • 返回成功或失败的状态码。
int EnterLinkQueue(LinkQueue *queue, DATATYPE *data)
{
    QueueNode*newnode = (QueueNode*)malloc(sizeof(QueueNode));
    if(NULL == newnode)
    {
        perror("EnterLinkQueue malloc");
        return 1;
    }
    memcpy(&newnode->data,data,sizeof(DATATYPE));
    newnode->next = NULL;

    if(IsEmptyLinkQueue(queue))
    {
        queue->head = newnode;
        queue->tail = newnode;
       }
    else
    {
        queue->tail->next = newnode;
        queue->tail = newnode;
    }
     queue->clen++;
    return 0;

}

3. int QuitLinkQueue(LinkQueue *queue);

功能描述:从链式队列中删除队首元素。

实现思路

  • 如果队列为空,则直接返回失败或错误码。
  • 否则,获取队首节点的指针,并将其从队列中移除(即更新头部指针)。
  • 释放原队首节点的内存。
  • 如果移除后队列为空,更新尾部指针为NULL
  • 更新队列长度(如果维护了队列长度的话)。
  • 返回成功或失败的状态码。
int QuitLinkQueue(LinkQueue *queue)
{
    if(IsEmptyLinkQueue(queue))
    {
        return 1;
    }
    QueueNode* tmp = queue->head;
    queue->head = queue->head->next;
    if(NULL ==queue->head)
    {
        queue->tail = NULL;
    }
    free(tmp);
    queue->clen--;
    return 0;
}

4. int IsEmptyLinkQueue(LinkQueue *queue);

功能描述:检查链式队列是否为空。

实现思路

  • 如果队列的头部指针为NULL,则队列为空,返回真(或特定值表示空)。
  • 否则,队列不为空,返回假(或特定值表示非空)。
int IsEmptyLinkQueue(LinkQueue *queue)
{
    return 0 == queue->clen;
}

5. int DestroyLinkQueue(LinkQueue *queue);

功能描述:销毁链式队列,释放其占用的所有内存。

实现思路

  • 遍历队列,释放每个节点的内存。
  • 将队列的头部和尾部指针置为NULL
  • 如果需要,可以释放LinkQueue结构体本身占用的内存(如果它是动态分配的)。
  • 返回成功或失败的状态码。
int DestroyLinkQueue(LinkQueue *queue)
{
    int i =0 ;
    int len = GetSizeLinkQueue(queue);
    for(i=0;i<len;i++)
    {
        QuitLinkQueue(queue);
    }
    free(queue);
    return 0;

}

6. DATATYPE * GetHeadLinkQueue(LinkQueue *queue);

功能描述:获取链式队列的队首元素(但不删除它)。

实现思路

  • 如果队列为空,则返回NULL或特定值表示队列为空。
  • 否则,返回队首节点的数据指针。
DATATYPE *GetHeadLinkQueue(LinkQueue *queue)
{
    if(IsEmptyLinkQueue(queue))
    {
        return NULL;

    }
    return &queue->head->data;
}

7. int GetSizeLinkQueue(LinkQueue *queue);

功能描述:获取链式队列的元素个数。

实现思路

  • 如果队列结构体中直接维护了队列长度,则直接返回该值。
  • 否则,需要遍历队列来统计元素个数,并返回。

这些函数共同构成了链式队列的基本操作集,是链表实现队列数据结构时常见的功能。

int GetSizeLinkQueue(LinkQueue *queue)
{
    return queue->clen;
}

总体;

.h

#ifndef LINKQUEUE_H
#define LINKQUEUE_H


#ifndef __HEAD_H__
#define __HEAD_H__
typedef int DATATYPE;

typedef struct node {
    DATATYPE data;
    struct node *next;
}QueueNode;

typedef struct queue {
    QueueNode *head;
    int clen;
    QueueNode *tail;
}LinkQueue;
LinkQueue *CreateLinkQueue();
int EnterLinkQueue(LinkQueue *queue, DATATYPE *data);
int QuitLinkQueue(LinkQueue *queue);
int IsEmptyLinkQueue(LinkQueue *queue);
int DestroyLinkQueue(LinkQueue *queue);
DATATYPE * GetHeadLinkQueue(LinkQueue *queue);
int GetSizeLinkQueue(LinkQueue *queue);
#endif
#endif // LINKQUEUE_H

.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include "linkqueue.h"
LinkQueue *CreateLinkQueue()
{
    LinkQueue* lq =(LinkQueue*)malloc(sizeof(LinkQueue));
    if(NULL == lq)
    {
        perror("CreateLinkQueue malloc");
        return NULL;
    }
    lq->head =NULL;
    lq->tail =NULL;
    lq->clen = 0 ;
    return lq;

}

int EnterLinkQueue(LinkQueue *queue, DATATYPE *data)
{
    QueueNode*newnode = (QueueNode*)malloc(sizeof(QueueNode));
    if(NULL == newnode)
    {
        perror("EnterLinkQueue malloc");
        return 1;
    }
    memcpy(&newnode->data,data,sizeof(DATATYPE));
    newnode->next = NULL;

    if(IsEmptyLinkQueue(queue))
    {
        queue->head = newnode;
        queue->tail = newnode;
       }
    else
    {
        queue->tail->next = newnode;
        queue->tail = newnode;
    }
     queue->clen++;
    return 0;

}

int IsEmptyLinkQueue(LinkQueue *queue)
{
    return 0 == queue->clen;
}

int QuitLinkQueue(LinkQueue *queue)
{
    if(IsEmptyLinkQueue(queue))
    {
        return 1;
    }
    QueueNode* tmp = queue->head;
    queue->head = queue->head->next;
    if(NULL ==queue->head)
    {
        queue->tail = NULL;
    }
    free(tmp);
    queue->clen--;
    return 0;
}

DATATYPE *GetHeadLinkQueue(LinkQueue *queue)
{
    if(IsEmptyLinkQueue(queue))
    {
        return NULL;

    }
    return &queue->head->data;
}

int GetSizeLinkQueue(LinkQueue *queue)
{
    return queue->clen;
}

int DestroyLinkQueue(LinkQueue *queue)
{
    int i =0 ;
    int len = GetSizeLinkQueue(queue);
    for(i=0;i<len;i++)
    {
        QuitLinkQueue(queue);
    }
    free(queue);
    return 0;

}

main.c

#include <stdio.h>
#include "linkqueue.h"
int main()
{
    LinkQueue* lq = CreateLinkQueue();

    int i = 0 ;
    for(i=0;i<10;i++)
    {
        EnterLinkQueue(lq,&i);
    }

    int size = GetSizeLinkQueue(lq);

    for(i=0;i<size;i++)
    {
        DATATYPE* tmp = GetHeadLinkQueue(lq);
        printf("%d\n",*tmp);
        QuitLinkQueue(lq);
    }


    DestroyLinkQueue(lq);

    return 0;
}

练习:

找出目录中的.h 文件里的#define

把某个指定目录下面所有 .h
#define
1.主线程
目录 ,入队
文件 .h
找#define
写文件 log
#define 。。。。。 24 xxxx.h
2.工作线程
阻塞,出队,递归目录
目录 ,递归
文件 .h
写文件 log
#define 。。。。。 24 xxxx.h

准备工作:

#include <stdio.h>  
#include <dirent.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <string.h>  
  
// 处理单个文件,搜索#define行并写入日志  
int do_handle_file(char *newpath, FILE *dst) {  
    FILE *fp = fopen(newpath, "r"); // 打开文件以读取  
    if (NULL == fp) {  
        perror("do_handle_file fopen"); // 如果打开文件失败,打印错误信息  
        fprintf(stderr, "filename %s\n", newpath); // 打印出错的文件名  
        return 1; // 返回错误码  
    }  
    int num = 1; // 行号计数器,从1开始  
    while (1) {  
        char buf[1024] = {0}; // 读取缓冲区  
        if (NULL == fgets(buf, sizeof(buf), fp)) {  
            break; // 如果到达文件末尾或读取错误,跳出循环  
        }  
        if (strstr(buf, "#define")) { // 如果行中包含#define  
            buf[strlen(buf) - 1] = '\0'; // 去除行尾的换行符  
            fprintf(dst, "%s %d %s\n", buf, num, newpath); // 将处理后的行写入目标文件,包括行号和文件名  
            fflush(dst); // 刷新输出缓冲区,确保数据立即写入文件  
        }  
        num++; // 行号递增  
    }  
    fclose(fp); // 关闭文件  
    // 注意:这里缺少了返回语句,但按照函数逻辑,应该返回0表示成功  
    return 0; // 假设补充的返回语句  
}  
  
// 递归遍历目录,处理所有.h文件  
void do_ls(char *pathname, FILE *fp) {  
    DIR *dir = opendir(pathname); // 打开目录  
    if (NULL == dir) {  
        perror("opendir"); // 如果打开目录失败,打印错误信息  
        fprintf(stderr, "pathname %s\n", pathname); // 打印出错的目录名  
        return; // 提前返回  
    }  
  
    struct dirent *info; // 读取目录项的结构体指针  
    char newpath[512] = {0}; // 构造新路径的缓冲区  
  
    while ((info = readdir(dir)) != NULL) { // 遍历目录项  
        sprintf(newpath, "%s/%s", pathname, info->d_name); // 构造完整路径  
        printf("processing %s\n", newpath); // 打印正在处理的文件或目录  
  
        // 注意:这里应该使用stat函数来检查文件类型,因为d_type可能不是所有系统都支持  
        // 但是为了保持代码的一致性,我们假设d_type是可用的  
        if (DT_DIR == info->d_type) { // 如果是目录  
            if (strcmp(info->d_name, ".") == 0 || strcmp(info->d_name, "..") == 0) {  
                continue; // 跳过当前目录和上级目录  
            }  
            do_ls(newpath, fp); // 递归处理子目录  
        } else { // 假设不是目录,则检查是否为.h文件  
            if (strlen(info->d_name) < 3) {  
                continue; // 文件名长度不足,不可能是.h文件  
            }  
  
            // 注意:字符串比较的方式有误,应该是从末尾开始比较".h"  
            if (strcmp(".h", &info->d_name[strlen(info->d_name) - 2]) == 0) {  
                do_handle_file(newpath, fp); // 处理该文件  
            }  
            // else { continue; } // 这一行是多余的,因为已经在if-else之外了  
        }  
    }  
  
    closedir(dir); // 关闭目录  
}  
  
int main(int argc, char *argv[]) {  
    FILE *fp = fopen("log", "w"); // 打开日志文件以写入  
    if (NULL == fp) {  
        perror("fopen"); // 如果打开文件失败,打印错误信息  
        return 1; // 返回错误码  
    }  
    do_ls("/home/linux", fp); // 遍历/home/linux目录及其子目录  
    fclose

.h

#ifndef LINKQUEUE_H
#define LINKQUEUE_H


#ifndef __HEAD_H__
#define __HEAD_H__
typedef struct
{
    char path[512];
 }DATATYPE;

typedef struct node {
    DATATYPE data;
    struct node *next;
}QueueNode;

typedef struct queue {
    QueueNode *head;
    int clen;
    QueueNode *tail;
}LinkQueue;
LinkQueue *CreateLinkQueue();
int EnterLinkQueue(LinkQueue *queue, DATATYPE *data);
int QuitLinkQueue(LinkQueue *queue);
int IsEmptyLinkQueue(LinkQueue *queue);
int DestroyLinkQueue(LinkQueue *queue);
DATATYPE * GetHeadLinkQueue(LinkQueue *queue);
int GetSizeLinkQueue(LinkQueue *queue);
#endif
#endif // LINKQUEUE_H

.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#include "linkqueue.h"
LinkQueue *CreateLinkQueue()
{
    LinkQueue* lq =(LinkQueue*)malloc(sizeof(LinkQueue));
    if(NULL == lq)
    {
        perror("CreateLinkQueue malloc");
        return NULL;
    }
    lq->head =NULL;
    lq->tail =NULL;
    lq->clen = 0 ;
    return lq;

}

int EnterLinkQueue(LinkQueue *queue, DATATYPE *data)
{
    QueueNode*newnode = (QueueNode*)malloc(sizeof(QueueNode));
    if(NULL == newnode)
    {
        perror("EnterLinkQueue malloc");
        return 1;
    }
    memcpy(&newnode->data,data,sizeof(DATATYPE));
    newnode->next = NULL;

    if(IsEmptyLinkQueue(queue))
    {
        queue->head = newnode;
        queue->tail = newnode;
       }
    else
    {
        queue->tail->next = newnode;
        queue->tail = newnode;
    }
     queue->clen++;
    return 0;

}

int IsEmptyLinkQueue(LinkQueue *queue)
{
    return 0 == queue->clen;
}

int QuitLinkQueue(LinkQueue *queue)
{
    if(IsEmptyLinkQueue(queue))
    {
        return 1;
    }
    QueueNode* tmp = queue->head;
    queue->head = queue->head->next;
    if(NULL ==queue->head)
    {
        queue->tail = NULL;
    }
    free(tmp);
    queue->clen--;
    return 0;
}

DATATYPE *GetHeadLinkQueue(LinkQueue *queue)
{
    if(IsEmptyLinkQueue(queue))
    {
        return NULL;

    }
    return &queue->head->data;
}

int GetSizeLinkQueue(LinkQueue *queue)
{
    return queue->clen;
}

int DestroyLinkQueue(LinkQueue *queue)
{
    int i =0 ;
    int len = GetSizeLinkQueue(queue);
    for(i=0;i<len;i++)
    {
        QuitLinkQueue(queue);
    }
    free(queue);
    return 0;

}

main.c

#include <stdio.h>
#include "linkqueue.h"
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <dirent.h>
sem_t sem_task;
pthread_mutex_t mutex;
pthread_t main_th;
int  do_handle_file(char * newpath,FILE* dst)
{
    FILE*fp  =fopen(newpath,"r");
    if(NULL == fp)
    {
        perror(" do_handle_file  fopen");
        fprintf(stderr,"filename %s\n",newpath);
        return 1;
    }
    int num =1;
    while(1)
    {
        char buf[1024]={0};
        if(NULL == fgets(buf,sizeof(buf),fp))
        {
            break;
        }
        if(strstr(buf,"#define"))
        {
            buf[strlen(buf)-1]='\0';
            fprintf(dst,"%s %d %s\n",buf,num,newpath);
            fflush(dst);
        }
        num++;
    }

    fclose(fp);
    return 0;
}

void do_ls(char *pathname,FILE* fp,LinkQueue* lq)
{

    DIR* dir = opendir(pathname);// home/linux
    if(NULL == dir)
    {
        perror("opendir");
        fprintf(stderr,"pathname %s\n",pathname);
        return ;
    }
    DATATYPE data;
    while(1)
    {

        bzero(&data,sizeof(data));
        struct dirent * info = readdir(dir);
        if(NULL == info)
        {
            break;
        }
        char newpath[512]={0};
        sprintf(newpath,"%s/%s",pathname,info->d_name);
        printf("processing %s\n",newpath);
        if(DT_DIR == info->d_type)
        {
            if(0 == strcmp(info->d_name,".")
                    || 0 == strcmp(info->d_name,".."))
            {
                continue;
            }
            if(pthread_self() == main_th)// this th is main_th
            {
                strcpy(data.path,newpath);
                pthread_mutex_lock(&mutex);
                EnterLinkQueue(lq,&data);
                pthread_mutex_unlock(&mutex);
                sem_post(&sem_task);
            }
            else
            {
                do_ls(newpath,fp,lq);// 1   /home/linux/1
            }

        }
        else
        {
            if(strlen(info->d_name)<3)
            {
                continue;
            }

            if(0==strcmp(".h",&info->d_name[strlen(info->d_name)-2]))
            {
                do_handle_file(newpath,fp);
            }
            else
            {
                continue;
            }
        }

    }
    closedir(dir);
}
typedef struct
{
    FILE* fp ;
    LinkQueue* lq;
}TH_ARG;
void * th(void* arg)
{
    TH_ARG* th_arg = (TH_ARG*)arg;
    FILE*fp = th_arg->fp;
    LinkQueue* lq = th_arg->lq;
    DATATYPE data;
    while(1)
    {
        bzero(&data,sizeof(data));
        sem_wait(&sem_task);
        pthread_mutex_lock(&mutex);
        DATATYPE*tmp = GetHeadLinkQueue(lq);
        memcpy(data.path,tmp->path,sizeof(data.path));
        QuitLinkQueue(lq);
        pthread_mutex_unlock(&mutex);
        if(0==strcmp(data.path,"over"))
        {
            break;
        }
        do_ls(data.path,fp,lq);

    }
    return NULL;
}
int main()
{

    main_th= pthread_self();
    pthread_t tid[3]={0};
    LinkQueue* lq = CreateLinkQueue();
    FILE* fp = fopen("log","w");
    if(NULL==fp)
    {
        perror("fopen");
        return 1;
    }
    TH_ARG arg={0};
    arg.fp = fp;
    arg.lq = lq;
    sem_init(&sem_task,0,0);
    pthread_mutex_init(&mutex,NULL);
    int i = 0 ;
    for(i=0;i<3;i++)
    {
        pthread_create(&tid[i],NULL,th,&arg);
    }

    do_ls("/home/linux",fp,lq);

    DATATYPE data;
    for(i=0;i<3;i++)
    {
        bzero(&data,sizeof(data));
        strcpy(data.path,"over");
        EnterLinkQueue(lq,&data);
        sem_post(&sem_task);
    }

    for(i=0;i<3;i++)
    {
        pthread_join(tid[i],NULL);
    }


    pthread_mutex_destroy(&mutex);
    sem_destroy(&sem_task);
    DestroyLinkQueue(lq);
    fclose(fp);

    printf("aaaaaaaaaaaa\n");
    return 0;
}

  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值