Queue in and out according to clients’type

邮差的信 提交于 2019-12-13 03:43:41

问题


Queue in and out according to clients’type Question

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.

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!

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

}

回答1:


You have a few problems here.

1. Global variables

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.

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.

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. Global variables (again)

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.

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. Ignoring the compiler warnings/errors (mixing types)

Node->CardNum is declared as int and you do

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

My compiler says:

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

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

But:

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

  2. 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.

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

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

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

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. Unless 100% necessary, don't use global variables

  2. 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);
    
  3. Use better names for your variables, it's easier to follow code for everybody:

    void Enqueue(Queue *q, const char *cardNumber, const char *customer);
    
  4. 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.

  5. 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.

  6. 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];
    

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

    A possible implementation for clean_stdin:

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


来源:https://stackoverflow.com/questions/48357275/queue-in-and-out-according-to-clients-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!