根据客户类型问题进出队列
根据以前的实现,修改LIST命令,使其先按队列号按升序打印VIP客户端,然后按普通客户端打印 . 与OUT命令相同,VIP将首先排队到普通客户端 .
Input
IN 1000001 Ordinary
IN 2000003 VIP
IN 2000009 VIP
OUT
OUT
OUT
OUT
IN 1000007 Ordinary
IN 2000005 VIP
LIST
OUT
QUIT
Output
IN:1 1000001 Ordinary 0
IN:2 2000003 VIP 0
IN:3 2000009 VIP 1
OUT:2 2000003 VIP
OUT:3 2000009 VIP
OUT:1 1000001 Ordinary
FAILED:
IN:4 1000007 Ordinary 0
IN:5 2000005 VIP 0
LIST:
5 2000005 VIP
4 1000007 Ordinary
OUT:5 2000005 VIP
GOOD BYE!
我试图为VIP制作一个队列一个,普通的一个队列在Enqueue函数中有错误,它显示卡号和客户端类型的奇怪数字,但程序运行..........任何其他解决方案是欢迎以外的两种排队方式 .
#include <stdio.h>
#include <malloc.h>
#include<string.h>
int position=0;
int length=1;
typedef struct Node
{
int record;
int CardNum;
char CustomerType[20];
struct Node* next;
}Node;
typedef struct queue
{
Node* front;
Node* rear;
}Queue;
Queue q1,q2;
void Enqueue(Queue *q, char *x, char *y);
void List(Queue *q);
int main()
{
char command[10];
char card[10],*ptrcard;
char client[10],*ptrclient;
while(1)
{
scanf("%s",command);
if(strcmp(command,"IN") == 0)
{
printf("IN:");
scanf("%s",card);
ptrcard=&card[0];
scanf("%s",client);
ptrclient=&client[0];
if(strcmp(client,"VIP")==0)
{
Enqueue(&q1,card,client);
}
else if(strcmp(client,"Ordinary")==0)
{
Enqueue(&q2,card,client);
}
}
else if(strcmp(command,"LIST") == 0)
{
printf("LIST:\n");
List(&q1);
List(&q2);
}
else if(strcmp(command,"QUIT") ==0)
{
printf("GOOD BYE!\n");
break;
}
}
return 0;
}
void Enqueue(Queue *q, char *x, char *y)
{
Node* temp = (Node*)malloc(sizeof(Node));
strcpy(temp->CardNum,x);
strcpy(temp->CardNum,y);
temp->record=length;
temp->next=NULL;
if(q->front == NULL && q->rear == NULL)
{
q->front=q->rear=temp;
}
else
{
q->rear->next=temp;
q->rear=temp;
}
printf("%d %d %s %d\n",temp->record,temp->CardNum,temp->CustomerType,position);
position++;
length++;
}
void List(Queue *q)
{
Node *temp;
if(q->front != NULL)
{
temp = q->front;
while(temp != NULL)
{
printf("%d %d %s\n",temp->record,temp->CardNum,temp->CustomerType);
temp = temp->next;
}
}
}
1 回答
你这里有一些问题 .
1. Global variables
我不明白你的全局变量的语义 . 什么是
position
什么是length
?我的意思是,无论队列如何,都会为每个Enqueue
调用更新这些值 . 你从来没有真正使用position
(忽略printf
,我认为它是调试代码),所以没有意义 .类似于
length
. 它的长度是多少?您在Node->record
中使用了length
,但是,无论队列如何,每次排队时都会更新length
.对我来说,这些值取决于队列,因此它们应该在struct中:
这只是一个观察,这不是造成问题的原因 .
2. Global variables (再次)
为什么将
q1
和q2
声明为全局变量?至少在你的例子中,没有理由让它们成为全球性的 . 我把它们放在main
函数中 .我看到的唯一原因是全局变量初始化为0,因此您不必在以后初始化它们,但我认为这是一个坏习惯 . 因为如果您以后必须更改代码并将全局变量放回函数中,您可能会忘记初始化,然后您有未定义的行为 . 声明一个新队列时最好初始化一个新队列 .
当你想要一个新队列时:
3. Ignoring the compiler warnings/errors (混合类型)
Node->CardNum
被声明为int
,你做到了我的编译器说:
我认为第二行是你的错字,你可能想做
strcpy(temp->CustomerType, y);
这是正确的 .但:
您正在尝试将字符串复制到
int
,这不会混合类型 .真正发生的事情是
strcpy
开始写入你很可能没有读/写权限的位置,如果幸运的是巧合temp->CarnNum
的整数值与你可以写的地址相同,那么你就覆盖了内存你不应该 .一个简单的修复方法是
temp->CardNum = atoi(y);
或者更好的是你还是读了这个值:并将
cardNum
整数传递给Enqueue
. 您显然需要更改enqueue函数的签名:但在这种情况下,我认为最好的策略是阅读字符串 . 当然,您的卡号似乎是整数,但管理层可能会稍后更改,并在卡号上添加字母,或者他们希望填充0 . 因此,将卡号视为字符串似乎是更好的选择 . 您只需要更改结构 . 您还需要更改
List()
中的printf
行 .通过我在这里解释的小修复,我能够编译你的代码并使用你提供的输入来运行它 . 这就是我所拥有的:
我有一些建议:
除非100%必要,否则不要使用全局变量
当声明一个以字符串作为参数的函数时,并且当该函数是 not 将操纵字符串时,最好将它们声明为
const char*
. 这样很明显,你的函数不会改变字符串,用户也可以传递一个字符串文字 .从用户读取时,最好在写入之前检查缓冲区是否有足够的空间 . 例如,如果用户输入一个很长的卡号,它可能会在执行
strcpy
时溢出缓冲区 . 出于这个原因,最好使用strncpy,但请注意,如果缓冲区中没有剩余空间,strncpy
可能不会写入'\0'
-终止字节 .即使在像你这样的"trivial"程序中,请释放你用
malloc
&Co . 分配的内存 . 写一个free_queue
函数来完成这项工作并在退出程序之前使用它 .数组在将它们传递给函数或将它们分配给指针时会衰减为指针 .
两者都是等价的,你不需要
ptrcard
和ptrclient
变量 . 这样做:scanf
的返回值 . 它返回匹配的令牌数 . 当用户输入您不期望的内容时,您可以使用它进行控制 . 在这种情况下,您可以清理缓冲区并忽略该行 .clean_stdin
的可能实现: