根据客户类型排队进出 [英] Queue in and out according to clients’type

查看:57
本文介绍了根据客户类型排队进出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Queue in and out according to clients’type Question

根据先前的实现,修改LIST命令,以便它将首先打印VIP客户端然后普通客户按队列号升序排列.与OUT命令相同,VIP将排队首先是普通客户.

Based on previous implementation, modify the LIST command, so that it will print VIP clients first then ordinary clients in ascending order by queue number. Same as OUT command, VIP will be queued out first then ordinary clients.

输入

IN 1000001 Ordinary

IN 2000003 VIP

IN 2000009 VIP

OUT

OUT

OUT

OUT

IN 1000007 Ordinary

IN 2000005 VIP

LIST

OUT

QUIT

输出

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队列和一个普通队列,但是在入队功能中有错误,该队列显示卡号和客户端类型的怪异数字,但是程序运行..... any除了两个队列方法之外,其他解决方案也受到欢迎.

I have tried to make two queues one for VIP and one for Ordinary it has error in the Enqueue function it shows weird figures for the card number and client type but the program runs ..........any other solution is welcomed other than the two queue approach.

#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;
       }
   }

}

推荐答案

您在这里遇到了一些问题.

You have a few problems here.

1.全局变量

我不了解您的全局变量的语义.什么是 position 和什么是 length ?我的意思是,您为每个入队调用更新这些值不管队列.您根本不会真正使用 position (忽略 printf ,我将其视为调试代码),因此没有任何意义.

I don't understand the semantics of your global variables. What is position and what is length? I mean, you update these values for every Enqueue call regardless of the queue. You never really use position at all (ignoring the printf, which I see as debugging code), so there is no point to that.

类似于 length .它的长度是多少?您在 length 中使用 Node-> record ,但同样,每次进入队列时, length 都会更新不管队列如何.

Similar for length. It is the length of what? You use length in Node->record, but again, length gets updated every time you enqueue something regardless of the queue.

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

For me these values are dependent on the queues, so they should be in struct:

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

这只是一个观察,这不是导致问题的原因.

This is just an observation, this is not what is causing the problems.

2.全局变量(再次 )

为什么要声明 q1 q2 作为全局变量?至少在你的例子中他们没有理由走向全球.我将它们放在 main 函数中.

Why do you declare q1 and q2 as global variables? At least in your example there is no reason for them to be global. I'd put them in the main function.

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

The only reason I see for that would be that global variables are initialized with 0 hence you don't have to initialize them later on, but I consider that a bad habit. Because if you later have to change your code an put the global variables back into a function, you may forget about the initialization and then your have undefined behaviour. It's better to initialize a new queue when you declare one.

int init_queue(Queue* queue)
{
    if(queue == NULL)
        return 0;

    memset(queue, 0, sizeof *queue);
    return 1;
}

当您想要一个新队列时:

And when you want a new queue:

Queue q;
init_queue(&q);

3.忽略编译器警告/错误(混合类型)

Node-> CardNum 被声明为 int ,而您这样做

Node->CardNum is declared as int and you do

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); 是正确的.

I think the second line is a typo of yours, you may have wanted to do strcpy(temp->CustomerType, y); which is correct.

但是:

  1. 您正在尝试将字符串复制到 int 中,这是行不通的.不要混类型.

  1. You are trying to copy a string into an int, that doesn't work. Don't mix types.

真正发生的是 strcpy 开始在您所在的位置书写如果很幸运,很可能没有读/写权限 temp-> CarnNum 的整数值与您可以在其中输入的地址相同写,那么您正在覆盖不应该使用的内存.

What really happens is that strcpy begins writing in location where you most probably don't have read/write permission, if by some lucky coincidence the integer value of temp->CarnNum is the same as an address where you can write, then you are overwriting memory that you shouldn't.

一个简单的解决方法是 temp-> CardNum = atoi(y); 或更好的方法是阅读值:

A simple fix would be temp->CardNum = atoi(y); or better still you read the value:

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

并将该 cardNum 整数传递给 Enqueue .您显然需要进行更改入队功能的签名:

and pass that cardNum integer to Enqueue. You would obviously need to change the signature of the enqueue function:

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

但是在这种情况下,我认为最好的策略是读取字符串.好的,你的卡数字似乎是整数,但管理层可能会在以后更改并在其中添加字母卡号,否则他们希望使用填充0.由于这个原因卡号作为字符串似乎是一个更好的选择.您只需要改变结构.您还需要更改 List()中的 printf 行.

But in this case I think the best strategy is to read strings. Sure, your card numbers seem to be integers, but management may change that later and add letters to the card numbers or they would want to have padding 0s. For this reason treating the card number as a string seems to be a better option. You would only need to change the structure. You would also need to change the printf line in List().

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

进行了一些小小的修订,我得以编译您的代码并运行它与您提供的输入.那就是我所拥有的:

Making the small fixes I explained here, I was able to compile your code and run it with the input you've provided. That's what I've got:

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


我有一些建议:


I have a few suggestions:

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

  1. Unless 100% necessary, don't use global variables

在声明将字符串作为参数的函数时以及函数将要操作字符串,最好声明它们为 const char * .这样就可以很清楚地知道您的功能是不会更改字符串,用户也可以传递字符串文字.

When declaring a function that takes strings as arguments, and when this function is not going to manipulate the strings, it's best to declare them as const char*. This way it is clear right away that your function is not going to alter the strings, the user may also pass a string literal.

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

  • 为变量使用更好的名称,遵循以下代码更容易大家:

  • Use better names for your variables, it's easier to follow code for everybody:

    void Enqueue(Queue *q, const char *cardNumber, const char *customer);
    

  • 从用户那里读取信息时,最好检查一下缓冲区是否具有在写它们之前要有足够的空间.例如,如果用户输入了很长的时间卡号,执行 strcpy 时可能会使缓冲区溢出.为此原因最好使用 strncpy ,但请注意strncpy 可能不会如果缓冲区中没有剩余空间,则写入'\ 0'终止字节.

  • When reading from the user, it's always better to check that you buffers have enough space before writing them. For example if the user enters a very long card number, it may overflow the buffer when doing strcpy. For this reason it's better to use strncpy, but be aware that strncpy might not write the '\0'-terminating byte if there is no space left in the buffer.

    即使在像您这样的琐碎"程序中,也请释放您已经拥有的内存分配了 malloc &Co.编写一个执行此操作的 free_queue 函数工作并在退出程序之前使用它.

    Even in a "trivial" program like yours, please free the memory you've allocated with malloc & Co. Write a free_queue function that does this job and use it before exiting the program.

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

    Arrays decay into pointers when passing them to functions or assigning them to pointers.

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

    两者都是等效的,您不需要 ptrcard ptrclient 变量.可以做到:

    Both are equivalent, you don't need the ptrcard and ptrclient variables. This will do:

    scanf("%s", card);
    scanf("%s", client);
    
    Enqueue(&q1, card, client);
    

  • 您应该检查 scanf 的返回值.它返回令牌的数量匹配.当用户输入您不输入的内容时,您可以使用它进行控制预计.在这种情况下,您可以清理缓冲区并忽略该行.

  • You should check the return value of scanf. It returns the number of tokens matched. You can control with it when a user inputs something you don't expect. In this case you could clean the buffer and ignore the line.

    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));
    }
    

  • 这篇关于根据客户类型排队进出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆