#include<stdio.h>
#include<stdlib.h>
// 定义链队数据节点
typedef struct qnode
{
int data;
struct qnode *next;
}DataNode;
// 定义链队头结点
typedef struct
{
DataNode *front;
DataNode *rear;
}LinkQuNode;
// 初始化队列
void InitQueue(LinkQuNode *q)
{
q = (LinkQuNode *)malloc(sizeof(LinkQuNode));
q -> front = q -> rear = NULL;
}
// 销毁队列
void DestroyQueue(LinkQuNode *q)
{
DataNode *pre = q -> front, *p; // pre指向队首节点(除了队头节点的第一个节点)
if(pre != NULL)
{
p = pre -> next;
while(p != NULL)
{
free(p);
pre = p; p = p -> next;
}
free(p);
}
free(q);
printf("队列已销毁");
return;
}
// 队列判空
void QueueEmpty(LinkQuNode *q)
{
if(q -> front == NULL)
printf("队列为空\n");
else
printf("队列不为空\n");
}
// 进队列
void enQueue(LinkQuNode *q, int e)
{
DataNode *p;
p = (DataNode *)malloc(sizeof(DataNode));
p -> data = e;
p -> next = NULL;
if(q -> rear == NULL) // 当结点是队列中的第一个结点时
q -> front = q -> rear = p; // 队头结点和队尾结点同时指向p
else
{
q -> rear -> next = p;
q -> rear = p;
}
}
// 出队列, 返回出队列的值e
int deQueue(LinkQuNode *q)
{
DataNode *t;
if(q -> rear == NULL) // 队列为空
{
printf("队列空\n");
return 1;
}
t = q -> front;
if(q -> front == q -> rear) // 队列中只有一个数据结点
q -> front = q -> rear = NULL;
else
{
q -> front = q -> front -> next;
}
printf("被删除的元素是:%d\n", t -> data);
free(t);
return 0;
}
// 入队功能函数
void pushQueue(LinkQuNode *q)
{
int i;
printf("输入要入队的数据:");
scanf("%d", &i);
enQueue(q, i);
printf("入队成功");
}
int main()
{
int menu;
LinkQuNode *q;
InitQueue(q);
printf("1 入队列 2 出队列\n");
printf("3 队列判空 4 销毁队列\n");
printf("5 退出\n");
while(1)
{
printf("请输入菜单号:");
scanf("%d", &menu);
if(menu == 5)
break;
switch(menu)
{
case 1: pushQueue(q); break;
case 2: deQueue(q); break;
case 3: QueueEmpty(q); break;
case 4: DestroyQueue(q); break;
default: printf("1\n");
}
}
return 0;
}
这是代码和调试的结果,实在找不出错误的原因,请求大佬告知。
这个问题的原因不是在在函数中开辟的空间地址离开函数就无效。
用 malloc() 函数申请的内存地址离开函数后还是有效,需要主动用 free() 函数释放才会无效。
这段代码出问题的原因在于,传入到 InitQueue() 函数的参数类型不对。下面这种写法,传入到该函数的 q指针参数是传值的方式,在 InitQueue() 函数内部并不能修改外部 q 指针变量的值。
void InitQueue(LinkQuNode *q)
即,在你的 main() 函数的下面语句中,LinkQuNode *q 这个变量的值并不会因为执行 InitQueue(q); 语句而改变。执行 InitQueue(q); 语句后,q这个变量值还是没有初始化,并没有指向 malloc() 分配出来的内存地址。
LinkQuNode *q;
InitQueue(q);
如果你想要修改外部这个q变量的值,要把 InitQueue函数的参数类型改成 void InitQueue(LinkQuNode **q),然后再该函数里面用 *q 来为它赋值。
把 q = (LinkQuNode *)malloc(sizeof(LinkQuNode));//分配空间 提到主函数有效,就是因为这会真正为 q变量赋值。
你可以用 printf("q: %p", &q); 语句打印 L 指针变量的地址来查看 InitQueue() 函数内外 L 的地址,看是否一样。
对于 InitQueue(LinkQuNode *q) 这种函数来说,可以用 q 指针来修改 q 指向的内存地址的值,但是这个 L 是形参,修改 q 本身的值,并不影响外面实参的值。
可改成
q -> front->next = q -> rear->next = NULL;
q -> front->data = q -> rear->data = 0;
原因:
未初始化的内存
如:p已被分配了10个字节。这10个字节可能包含垃圾数据。
char*p=malloc(10);
垃圾数据
如果在对这个p赋值前,某个代码段尝试访问它,则可能会获得垃圾值,您的程序可能具有不可预测的行为。p可能具有您的程序从未曾预料到的值。
结合使用memset和malloc,或者使用calloc。
char*p=malloc(10);
memset(p,’’,10);
这样就行了,你永远记住,指针你一旦使用就得指向一块地址。
void InitQueue(LinkQuNode *q)
{
q = (LinkQuNode *)malloc(sizeof(LinkQuNode));
q -> front = (DataNode *)malloc(sizeof(DataNode));
q -> rear = (DataNode *)malloc(sizeof(DataNode));
q -> rear->next = (DataNode *)malloc(sizeof(DataNode));
q -> rear->data = 0;
q -> front->next = NULL;
q -> front->data = 0;
}
这个是调试结果:调用函数时都是在这个判断句这里出错