循环队列打印输入内容涉及到的问题
#define MaxSize 6 //循环队列的最大容量
typedef struct CycleQueue{
int* base; //循环队列的内存分配基地址
int front;
int rear;
}CycleQueue; //定义循环队列类CycleQueue
InitiQueue(CycleQueue* q)
{
q->base = (int*)malloc(MaxSize * sizeof(int));
if (!q->base) return; //内存分配失败
q->front = q->rear = 0; //此时为空队列,front和rear均指向0号元素
//注意此时的front和rear不是指针变量
}
EnQueue(CycleQueue* q, int e)
{
if ((q->rear + 1) % MaxSize == q->front) return;
q->base[q->rear] = e;
//q->rear++;是不对的。要记住是模加运算,而不是不同的加减运算。
//这是为了在线性内存空间上模拟出逻辑上循环的队列
q->rear = (q->rear + 1) % MaxSize;
}
Dequeue(CycleQueue* q, int* e)
{
if (q->front == q->rear) return;//队列为空
*e = q->base[q->front];
q->front = (q->front + 1) % MaxSize;
}
int main()
{
int num;
int EnQueuetimes=0;
CycleQueue* cq;
cq = (CycleQueue*)malloc(sizeof(struct CycleQueue));
InitiQueue(cq);
scanf("%d", &num);
EnQueue(cq, num);
while ((EnQueuetimes++) < MaxSize)
{
scanf("%d", &num);
EnQueue(cq, num);
}
while (cq->front % MaxSize != cq->rear)
{
Dequeue(cq, &num);
printf("%d ", num);
}
return 0;
}
上面程序段中,值得注意的点:
1. 数组名与指针之间的等价关系
q->base[q->rear] = e;
这个语句也可以等价于
*(base+q->rear)=e;//这里涉及到指针的加减运算
//这里的base+q->rear,相当于在base基地址的基础上,
//加上q->rear个int类型的个数,而不是单纯的加一个字节
//因为base是指向int类型的指针变量
2. 通过地址传递改变实参的值
在C语言中,实参与形参之间的数据交换为“值传递”。也就是说形参的变化并不能够改变实参的值。所以说需要通过指针变量,进行地址传递,才能够在被调用函数中对实参进行修改。
Dequeue(CycleQueue* q, int* e)
{
if (q->front == q->rear) return;//队列为空
*e = q->base[q->front];
q->front = (q->front + 1) % MaxSize;
}
如下面的出队操作程序块所示,实参将其所在地址传递给被调动函数的指针变量e,此时e存储这实参值所在的地址。在被调用函数中用到了
*e = q->base[q->front];
通过“*”取地址符将e指针所指向空间内所存储的数据取出,然后对该数据进行修改。形象一点说,e就是宝箱所在位置,取地址符为宝箱的钥匙,只有通过它才可以打开宝箱并取出里面的宝物。
回到程序中,此时进行取值操作的空间正是队头元素所在的空间。那么通过将实参的地址传递给形参(指针变量),然后再由形参将地址返回,这样就解决了形参在被调用结束之后就被销毁,而无法将其值传递给实参的问题。实现了修改实参的情况。