一、概念
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;
}