一、思想
二、代码
Queue目录下
bin-子目录、include-子目录、obj-子目录、src-子目录、Makefile文件
Makefile
# 定义了一个名为All的目标
All:
# 在./src/目录下执行make命令,构建该目录下的目标
make -C ./src/
# 在./obj/目录下执行make命令,构建该目录下的目标
make -C ./obj/
# 声明一个伪目标,伪目标是一个始终会被执行的目标,即使存在一个同名的文件
.PHONY: CLEAN
# 定义了一个名为CLEAN的目标
CLEAN:
# 删除obj目录下的所有.o文件(通常是编译产生的目标文件)
rm obj/*.o
# 删除bin目录下的所有文件(通常是链接产生的可执行文件)
rm bin/*
解释:
make -C ./src/:这条命令表示在./src/目录下执行make命令。-C选项用于指定make命令应该在哪个目录下执行。
make -C ./obj/:与上面的命令类似,这条命令表示在./obj/目录下执行make命令。
.PHONY: CLEAN:这行代码声明了一个伪目标CLEAN。伪目标是一个不会被文件名冲突的目标。这意味着,即使存在一个名为CLEAN的文件,执行make CLEAN时,make工具仍然会执行CLEAN目标下的命令,而不会误认为CLEAN是一个文件名。
rm obj/*.o:这条命令用于删除obj目录下的所有.o文件。
rm bin/*:这条命令用于删除bin目录下的所有文件。
需要注意的是,这个Makefile依赖于./src/和./obj/目录中存在相应的Makefile或Makefile.in文件,因为这里使用了make -C命令来在子目录中执行make。如果这些子目录中不存在Makefile,那么这个Makefile将不会按预期工作。
bin-子目录
可执行文件App
include-子目录
myhead.h-头文件
#ifndef _MYHEAD_H
#define _MYHEAD_H
//相关的头文件
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 6
//定义数据类型
typedef int data_type;
//定义队列结构体
typedef struct queue{
data_type Data[SIZE];//队列存储数组
int head;//队头指针
int tail;//队尾指针
int tag;//标志位,存储刚刚执行的动作,1 入队,0 出队
}Queue;
//定义返回值枚举类型
typedef enum ret{
/* member*/
QUEUE_NULL = -4, //队列指针为空
POS_ERR, //位置错误
QUEUE_FULL, //队列已满
QUEUE_EMPTY, //队列为空
OK, //操作成功
} ret_e;
//函数声明
Queue *CreatQueue(void); //创建队列
int Menu(); //菜单函数
int InQueue(Queue *pQueue,data_type item); //入队操作
int ShowQueue(Queue *pQueue); //显示队列内容
int OutQueue(Queue *pQueue,data_type *item); //出队操作
#endif
obj-子目录
Makefile-文件
# 定义了一个名为ALL的目标
ALL:
# 使用gcc编译器将当前目录下的所有.o文件链接成一个可执行文件APP
# 并将其放置在上级目录的bin文件夹中
gcc *.o -o ../bin/APP
解释:
ALL::这是一个Makefile的目标标签。当你在命令行中输入make ALL时,Make工具会查找名为ALL的目标并执行其下的命令。
gcc *.o -o ../bin/APP:这是ALL目标下的命令。
gcc:这是GNU编译器集合(GNU Compiler Collectio
src-子目录
main.c
// 引入自定义的头文件,可能包含队列的数据结构定义和函数声明
#include"../include/myhead.h"
int main(int argc, const char *argv[]) {
// 创建一个队列的指针,并初始化为NULL
Queue *pQueue = NULL;
// 定义用于接收用户选择的变量
int opt = 0;
// 定义用于插入队列的位置(但在此代码中并未使用)
int pos = 0;
// 定义用于插入队列的元素
data_type item = 0;
// 定义用于接收函数返回值的变量
int ret = 0;
// 进入一个无限循环,用于显示菜单并接收用户输入
while(1) {
// 调用Menu函数,展示菜单并接收用户选择
opt = Menu();
// 如果用户选择退出(-1),则跳出循环
if(-1 == opt) break;
// 根据用户的选择执行相应的操作
switch(opt) {
case 1:
// 入队操作
printf("请输入要入队的元素:");
scanf("%d",&item);
ret = InQueue(pQueue,item);
break;
case 2:
// 出队操作
ret = OutQueue(pQueue,&item);
printf("出队的是%d元素\n",item);
break;
case 3:
// 显示队列内容
ret = ShowQueue(pQueue);
break;
case 4:
// 创建队列
pQueue = CreatQueue();
printf("pQueue = %p\n",pQueue);
break;
default:
puts("请输入有效选项!");
}
// 根据函数的返回值进行错误处理
switch(ret) {
case POS_ERR:
puts("POS_ERR");
break;
case QUEUE_FULL:
puts("QUEUE_FULL");
break;
case QUEUE_NULL:
puts("QUEUE_NULL");
break;
case QUEUE_EMPTY:
puts("QUEUE_EMPTY");
break;
// 如果返回值不是上述任何一个,则不执行任何操作
}
}
// 程序正常结束,返回0
return 0;
}
menu.c
#include"../include/myhead.h"
int main(int argc, const char *argv[])
{
//创建
Queue *pQueue = NULL;
//定义选项
int opt = 0;
//定义插入位置
int pos = 0;
//定义插入元素
data_type item = 0;
//接返回值
int ret = 0;
//打印目录 Menu()
while(1)
{
opt = Menu();
if(-1 == opt) break;//退出
switch(opt)
{
case 1:
//insert
printf("请输入要入队的元素:");
scanf("%d",&item);
ret = InQueue(pQueue,item);
break;
case 2:
//OutQueue
ret = OutQueue(pQueue,&item);
printf("出队的是%d元素\n",item);
break;
case 3:
//show
ret = ShowQueue(pQueue);
break;
case 4:
//创建队列
pQueue = CreatQueue();
printf("pQueue = %p\n",pQueue);
break;
defaut:
puts("请输入有效选项!");
}
switch(ret)
{
case POS_ERR:
puts("POS_ERR");
break;
case QUEUE_FULL :
puts("DBNode_FULL");
break;
case QUEUE_NULL:
puts("DBNode_NULL");
break;
case QUEUE_EMPTY:
puts("DBNode_EMPTY");
break;
}
}
return 0;
}
create.c
#include"../include/myhead.h"
//函数功能:创建队列
//函数参数:
//函数返回值:
Queue *CreatQueue(void){
//动态分配队列结构体内存
Queue *pQueue = (Queue *)malloc(sizeof(Queue));
//如果内存分配失败,返回NULL
if(!pQueue) return NULL;
//初始化队列结构体为0
memset(pQueue,0,sizeof(Queue));
//返回队列指针
return pQueue;
}
inqueue.c
#include"../include/myhead.h"
//函数功能:入队
//函数参数:
//函数返回值:
int InQueue(Queue *pQueue,data_type item){
//入参判断
//如果队列指针为空,返回QUEUE_NULL
if(!pQueue) return QUEUE_NULL;
//如果队列已满(队头和队尾相同且tag为1),返回QUEUE_FULL
if(pQueue->head == pQueue->tail && pQueue->tag == 1)
return QUEUE_FULL;
//在队尾添加元素
pQueue->Data[pQueue->tail] = item;
//更新对尾指针,使用取模操作实现循环队列
pQueue->tail = (pQueue->tail + 1) % SIZE;
//标记队列非空
pQueue->tag = 1;
//成功入队,返回OK
return OK;
}
outqueue.c
#include"../include/myhead.h"
//函数功能:从队列中移除并返回元素
//函数参数:
// pQueue:指向队列结构体的指针
// item:用于存储出队元素的指针
//函数返回值:
// OK:成功出队
// QUEUE_NULL:没有此队列
// QUEUE_EMPTY:队列为空
int OutQueue(Queue *pQueue,data_type *item){
//入参判断
//如果队列指针为空,返回错误码
if(!pQueue) return QUEUE_NULL;
//如果队列为空(队头和队尾相同且tag为0),返回错误码
if(pQueue->head == pQueue->tail && pQueue->tag == 0)
return QUEUE_EMPTY;
//将出队元素赋值给item指针指向的变量
*item = pQueue->Data[pQueue->head];
//更新队头指针,使用取模操作实现循环队列
pQueue->head = (pQueue->head + 1) % SIZE;
// 如果更新后队头和队尾相同,说明队列为空,设置tag为0
pQueue->tag = (pQueue->head == pQueue->tail) ? 0 : 1;
// 出队成功,返回OK
return OK;
}
show.c
#include"../include/myhead.h"
//函数功能:显示队列内容函数
//函数参数:
//函数返回值:
int ShowQueue(Queue *pQueue){
//如果队列指针为空,返回
if(!pQueue) return QUEUE_NULL;
//如果队列为空,返回
if(pQueue->head == pQueue->tail && pQueue->tag == 0)
return QUEUE_EMPTY;
int i = 0;
// 队列只有一个元素且队列非空的情况
if(pQueue->head == pQueue->tail && pQueue->tag == 1){
//for(i = 0; i < SIZE; i++)
//printf("%d\t",pQueue->Data[pQueue->head + i]%SIZE);// 使用取模操作确保索引在队列数组范围内
printf("%d\t",pQueue->Data[pQueue->head]);
putchar(10);
return OK;
}
// 初始化i为队头位置
i = pQueue->head;
// 遍历队列,直到i等于队尾位置
while(i != pQueue->tail){
printf("%d\t",pQueue->Data[i]);// 打印当前元素
// 更新i为下一个位置,使用取模操作确保索引在队列数组范围内
i = (i + 1) % SIZE;
}
putchar(10);
return OK;
}
Makefile
# 定义了一个名为ALL的伪目标,用于构建整个项目
ALL: ../obj/main.o ../obj/menu.o ../obj/create.o ../obj/inqueue.o ../obj/show.o ../obj/outqueue.o
# 指定如何从main.c源文件构建../obj/main.o目标文件
../obj/main.o: main.c
gcc -c $< -o $@
# 指定如何从menu.c源文件构建../obj/menu.o目标文件
../obj/menu.o: menu.c
gcc -c $< -o $@
# 指定如何从create.c源文件构建../obj/create.o目标文件
../obj/create.o: create.c
gcc -c $< -o $@
# 指定如何从inqueue.c源文件构建../obj/inqueue.o目标文件
../obj/inqueue.o: inqueue.c
gcc -c $< -o $@
# 指定如何从show.c源文件构建../obj/show.o目标文件
../obj/show.o: show.c
gcc -c $< -o $@
# 指定如何从outqueue.c源文件构建../obj/outqueue.o目标文件
../obj/outqueue.o: outqueue.c
gcc -c $< -o $@
解释:
ALL::这是一个伪目标,通常用于组合多个目标文件,这里它指定了需要构建的所有目标文件。注意,ALL本身并没有指定任何命令,通常你可以添加一条命令来链接所有的目标文件以生成最终的可执行文件。
../obj/main.o: main.c 等行:这些行定义了如何从源文件(如main.c)构建目标文件(如../obj/main.o)。冒号:左边是目标文件,右边是依赖的源文件。
gcc -c $< -o $@:这是编译命令。gcc是C语言编译器,-c选项告诉编译器只编译源文件而不链接,$<是一个自动变量,代表依赖项(这里是源文件),$@代表目标(这里是目标文件)。