首页 文章

根据客户的类型排队进出

提问于
浏览
0

根据客户类型问题进出队列

根据以前的实现,修改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 回答

  • 0

    你这里有一些问题 .

    1. Global variables

    我不明白你的全局变量的语义 . 什么是 position 什么是 length ?我的意思是,无论队列如何,都会为每个 Enqueue 调用更新这些值 . 你从来没有真正使用 position (忽略 printf ,我认为它是调试代码),所以没有意义 .

    类似于 length . 它的长度是多少?您在 Node->record 中使用了 length ,但是,无论队列如何,每次排队时都会更新 length .

    对我来说,这些值取决于队列,因此它们应该在struct中:

    typedef struct queue
    {
        Node* front;
        Node* rear;
        int position;
        int length;
    } Queue;
    

    这只是一个观察,这不是造成问题的原因 .

    2. Global variables (再次)

    为什么将 q1q2 声明为全局变量?至少在你的例子中,没有理由让它们成为全球性的 . 我把它们放在 main 函数中 .

    我看到的唯一原因是全局变量初始化为0,因此您不必在以后初始化它们,但我认为这是一个坏习惯 . 因为如果您以后必须更改代码并将全局变量放回函数中,您可能会忘记初始化,然后您有未定义的行为 . 声明一个新队列时最好初始化一个新队列 .

    int init_queue(Queue* queue)
    {
        if(queue == NULL)
            return 0;
    
        memset(queue, 0, sizeof *queue);
        return 1;
    }
    

    当你想要一个新队列时:

    Queue q;
    init_queue(&q);
    

    3. Ignoring the compiler warnings/errors (混合类型)

    Node->CardNum 被声明为 int ,你做到了

    strcpy(temp->CardNum, x);
    strcpy(temp->CardNum, y);
    

    我的编译器说:

    a.c:81:12: warning: passing argument 1 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
         strcpy(temp->CardNum,y);
                ^~~~
    

    我认为第二行是你的错字,你可能想做 strcpy(temp->CustomerType, y); 这是正确的 .

    但:

    • 您正在尝试将字符串复制到 int ,这不会混合类型 .

    • 真正发生的事情是 strcpy 开始写入你很可能没有读/写权限的位置,如果幸运的是巧合 temp->CarnNum 的整数值与你可以写的地址相同,那么你就覆盖了内存你不应该 .

    一个简单的修复方法是 temp->CardNum = atoi(y); 或者更好的是你还是读了这个值:

    int cardNum;
    scanf("%d", &cardNum);
    

    并将 cardNum 整数传递给 Enqueue . 您显然需要更改enqueue函数的签名:

    void Enqueue(Queue *q, char *x, int y);
    

    但在这种情况下,我认为最好的策略是阅读字符串 . 当然,您的卡号似乎是整数,但管理层可能会稍后更改,并在卡号上添加字母,或者他们希望填充0 . 因此,将卡号视为字符串似乎是更好的选择 . 您只需要更改结构 . 您还需要更改 List() 中的 printf 行 .

    typedef struct Node
    {
        int record;
        char CardNum[20];
        char CustomerType[20];
        struct Node* next;
    } Node;
    

    通过我在这里解释的小修复,我能够编译你的代码并使用你提供的输入来运行它 . 这就是我所拥有的:

    IN:1 1000001 Ordinary 0
    IN:2 2000003 VIP 1
    IN:3 2000009 VIP 2
    IN:4 1000007 Ordinary 3
    IN:5 2000005 VIP 4
    LIST:
    2 2000003 VIP
    3 2000009 VIP
    5 2000005 VIP
    1 1000001 Ordinary
    4 1000007 Ordinary
    

    我有一些建议:

    • 除非100%必要,否则不要使用全局变量

    • 当声明一个以字符串作为参数的函数时,并且当该函数是 not 将操纵字符串时,最好将它们声明为 const char* . 这样很明显,你的函数不会改变字符串,用户也可以传递一个字符串文字 .

    void Enqueue(Queue *q, const char *x, const char *y);
    
    • 为变量使用更好的名称,为每个人更容易遵循代码:
    void Enqueue(Queue *q, const char *cardNumber, const char *customer);
    
    • 从用户读取时,最好在写入之前检查缓冲区是否有足够的空间 . 例如,如果用户输入一个很长的卡号,它可能会在执行 strcpy 时溢出缓冲区 . 出于这个原因,最好使用strncpy,但请注意,如果缓冲区中没有剩余空间, strncpy 可能不会写入 '\0' -终止字节 .

    • 即使在像你这样的"trivial"程序中,请释放你用 malloc &Co . 分配的内存 . 写一个 free_queue 函数来完成这项工作并在退出程序之前使用它 .

    • 数组在将它们传递给函数或将它们分配给指针时会衰减为指针 .

    int array[] = { 1, 3, 5, 7, 9 };
    
    int *ptr1 = array;
    int *ptr2 = &array[0];
    

    两者都是等价的,你不需要 ptrcardptrclient 变量 . 这样做:

    scanf("%s", card);
    scanf("%s", client);
    
    Enqueue(&q1, card, client);
    
    • 您应该检查 scanf 的返回值 . 它返回匹配的令牌数 . 当用户输入您不期望的内容时,您可以使用它进行控制 . 在这种情况下,您可以清理缓冲区并忽略该行 .
    while(1)
    {
        if(scanf("%s", card) != 1)
        {
            clean_stdin();
            printf("Unexpected entry: repeat command\n");
            continue; //
        }
    
        if(scanf("%s", client) != 1)
        {
            clean_stdin();
            printf("Unexpected entry: repeat command\n");
            continue; //
        }
    
        Enqueue(&q1, card, client);
    }
    

    clean_stdin 的可能实现:

    void clean_stdin()
    {
        int c;
        while( (c = getchar()) != '\n' && c != EOF));
    }
    

相关问题