这是两个以简单形式实现队列数据结构的程序
第一个:
定义一个队列,它完美地运作
第二个:
定义多个队列,并在执行时崩溃
函数在两个程序中都是相同的,除了main()
是实现
有点不同。
所以这里的问题是:为什么第二个代码不起作用?
*这里是代码*
代码1:
/*
Single queue -- this work perfectly
*/
#include <stdio.h>
#define Q_MAX_SIZE 255
struct queue {
int* pointer;
int* currentValue;
int max, count, theQueue[Q_MAX_SIZE];
};
//prototyps
void initQueue(struct queue*);
unsigned short pushQueue(struct queue*, int);
int* popQueue(struct queue*);
int main(void) {
int j;
struct queue q;
initQueue(&q);
for (j = 0; j < 6; j++)
pushQueue(&q, j);
int* inputobj = popQueue(&q);
while (inputobj != NULL)
{
printf("%d ", *inputobj);
inputobj = popQueue(&q);
}
printf("\n\ndone..Queue is empty\n");
return 0;
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void initQueue(struct queue *Q)
{
Q->pointer = Q->theQueue;
Q->max = Q_MAX_SIZE;
Q->count = 0;
}
unsigned short pushQueue(struct queue *Q, int input) {
if (Q->count < Q->max)
{
*Q->pointer = input;
Q->pointer++;
Q->count++;
return 1;
}
else
return 0;
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
int* popQueue(struct queue *Q) {
int i;
if (Q->count > 0)
{
*Q->currentValue = *Q->theQueue;
Q->pointer--;
Q->count--;
for (i = 0; i < Q->count; i++)
{
int* currentPtr = Q->theQueue + i;
int* nextPtr = currentPtr + 1;
*currentPtr = *nextPtr;
}
return Q->currentValue;
}
else
NULL;
}
代码2:
/*
Multiple queues -- this not work and crash at execution
*/
#include <stdio.h>
#define Q_MAX_SIZE 255
struct queue {
int* pointer;
int* currentValue;
int max, count, theQueue[Q_MAX_SIZE];
};
//prototyps
void initQueue(struct queue*);
unsigned short pushQueue(struct queue*, int);
int* popQueue(struct queue*);
int main(void) {
int i, j;
struct queue obj[5];
for(i=0; i<5; i++)
{
initQueue(&obj[i]);
for(j = 0; j<3; j++)
{
pushQueue(&obj[i], j);
}
}
for(i=0; i<5; i++)
{
printf("Queue[%d]:\n", i);
int* inputobj;
inputobj = popQueue(&obj[i]);
while(inputobj != NULL)
{
printf("Queue[No.%d] = %d\n", i, *inputobj);
inputobj = popQueue(&obj[i]);
}
putchar('\n');
}
return 0;
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void initQueue(struct queue *Q)
{
Q->pointer = Q->theQueue;
Q->max = Q_MAX_SIZE;
Q->count = 0;
}
unsigned short pushQueue(struct queue *Q, int input) {
if (Q->count < Q->max)
{
*Q->pointer = input;
Q->pointer++;
Q->count++;
return 1;
}
else
return 0;
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
int* popQueue(struct queue *Q) {
int i;
if (Q->count > 0)
{
*Q->currentValue = *Q->theQueue;
Q->pointer--;
Q->count--;
for (i = 0; i < Q->count; i++)
{
int* currentPtr = Q->theQueue + i;
int* nextPtr = currentPtr + 1;
*currentPtr = *nextPtr;
}
return Q->currentValue;
}
else
NULL;
}
更新:问题发生在initQueue()
,并通过分配内存解决了问题
for Q->currentValue
这里是编辑后的函数:
void initQueue(struct queue *Q)
{
Q->currentValue = malloc(sizeof(int));
Q->pointer = Q->theQueue;
Q->max = Q_MAX_SIZE;
Q->count = 0;
}
答案 0 :(得分:3)
正如两个答案已经说明的那样,问题是Q->current_value
从未被赋值给它,因此它指向一个未定义的地址,并且每个解除引用如*Q->currentValue = ..
都是未定义的行为。代码1看似有效的事实并不能证明任何其他因为由于UB的性质而没有保证行为,你的程序可能会或可能不会崩溃(或者你的狗可能会爆炸,龙会飞出你的鼻子......: - ))
当然,有多种解决方案都意味着不同的东西:
如果currentValue
只保留某个值的副本,则可以是int currentValue
而不是int *...
,并且分配将是
Q-&gt; currentValue = * Q-&gt; theQueue;
,return语句为return &Q->currentValue
。在这种情况下,您将返回指向原始值theQueue[0]
如果你想指向theQueue
中的位置,Jim的anser告诉了正确的方法:
Q-&gt; currentValue = Q-&gt; theQueue;
在这种情况下,您将返回指向theQueue[0]
的新值的指针(可能是您不想要的)
您可以将内存分配给Q->currentValue
我的malloc( sizeof (int) );
,然后保留分配原样。在这种情况下,您将返回指向原始值theQueue[0]
的指针,如(1)
答案 1 :(得分:1)
我认为这实际上是非常微妙的问题。问题(我认为)是popqueue()中的这一行:
*Q->currentValue = *Q->theQueue;
我仔细检查了你的初始代码(没有数组)也会出现故障。它不像你说的那样有效。你应该写:
Q->currentValue = Q->theQueue;
C可以通过指针稍微理解并适当地分配东西,但是当你添加另一个级别(数组)时,我认为赋值被强制转换为无效的东西。这是我的看法。我想我会提出赏金,这样你就可以得到更好的答案。
答案 2 :(得分:1)
首先,我不会尝试将这样的代码放在生产中。事情可以做得更简单,更清晰,更高效,更不容易出错。
我通过在尽可能少的地方改变事物来“修复”你的程序。必须清楚的是,这并不能使事情更加优雅。只有重新思考和重写才能让事情变得更加优雅。
您遇到的错误(包括第一个和第二个程序)都是常规popQueue。
在else子句中没有返回任何内容。你应该“返回NULL”。这至少是草率的编程。
例程返回1 2 3 4 5 5和1 2 2作为队列。这是因为Q-&gt; CurrentValue指向theQueue数组中的第一个位置,并且您向上移动所有值。这意味着CurrentValue事实指向下一个值。
解决方案(再次:它不优雅,也不会将其投入生产,但它对原始版本的改动很小)对你的问题是:
更改结构(保存实际的CurrentValue)
struct queue
{
int* pointer;
int currentValue;
int max, count, theQueue[Q_MAX_SIZE];
};
更改例程popQueue
int* popQueue(struct queue *Q) {
int i;
if (Q->count > 0)
{
Q->currentValue = *Q->theQueue;
Q->pointer--;
Q->count--;
for (i = 0; i < Q->count; i++)
{
int* currentPtr = Q->theQueue + i;
int* nextPtr = currentPtr + 1;
*currentPtr = *nextPtr;
}
return &(Q->currentValue);
}
else
return NULL;
}
亲切的问候, PB
答案 3 :(得分:0)
无法访问位置Q-&gt; currentValue,这就是问题所在。它没有分配。
解决方案是在init例程中分配正确的内存部分:
Q = malloc(sizeof(struct queue));
也许还会在此之后初始化所有变量的值。