一、概念
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: //overstrcpy(data.task_name,task[3].task_name);data.task_time = task[3].task_time;EnterSeqQueue(sq,&data);end_flag=0;break;default://overstrcpy(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/linuxif(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;
}