C语言实现队列review考虑到的知识点

2019-03-15  本文已影响0人  fred290

在stackexchange有一个人提了这么一个问题,自己实现了一个通用队列,然后把代码贴了上来,然后请大家review以下,希望基于以下几方面提一些建议:

在我看来,下面的实现其实已经相当完备了,代码正确性,风格,可读性都相当不错,可是下面还有一人竟然提出了12条改进建议,让我觉得相当惊讶,我看了下这个人的简介,coding since 1976,让我觉得一个有着多年经验的程序员和普通程序员之间的差别
代码如下:

Queue.h
#ifndef QUEUE_H_INCLUDED
#define QUEUE_H_INCLUDED

typedef struct Node
{
  void *data;
  struct Node *next;
}node;

typedef struct QueueList
{
    int sizeOfQueue;
    size_t memSize;
    node *head;
    node *tail;
}Queue;

void queueInit(Queue *q, size_t memSize);
int enqueue(Queue *, const void *);
void dequeue(Queue *, void *);
void queuePeek(Queue *, void *);
void clearQueue(Queue *);
int getQueueSize(Queue *);

#endif /* QUEUE_H_INCLUDED */
Queue.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Queue.h"

void queueInit(Queue *q, size_t memSize)
{
   q->sizeOfQueue = 0;
   q->memSize = memSize;
   q->head = q->tail = NULL;
}

int enqueue(Queue *q, const void *data)
{
    node *newNode = (node *)malloc(sizeof(node));

    if(newNode == NULL)
    {
        return -1;
    }

    newNode->data = malloc(q->memSize);

    if(newNode->data == NULL)
    {
        free(newNode);
        return -1;
    }

    newNode->next = NULL;

    memcpy(newNode->data, data, q->memSize);

    if(q->sizeOfQueue == 0)
    {
        q->head = q->tail = newNode;
    }
    else
    {
        q->tail->next = newNode;
        q->tail = newNode;
    }

    q->sizeOfQueue++;
    return 0;
}

void dequeue(Queue *q, void *data)
{
    if(q->sizeOfQueue > 0)
    {
        node *temp = q->head;
        memcpy(data, temp->data, q->memSize);

        if(q->sizeOfQueue > 1)
        {
            q->head = q->head->next;
        }
        else
        {
            q->head = NULL;
            q->tail = NULL;
        }

        q->sizeOfQueue--;
        free(temp->data);
        free(temp);
    }
}

void queuePeek(Queue *q, void *data)
{
    if(q->sizeOfQueue > 0)
    {
       node *temp = q->head;
       memcpy(data, temp->data, q->memSize);
    }
}

void clearQueue(Queue *q)
{
  node *temp;

  while(q->sizeOfQueue > 0)
  {
      temp = q->head;
      q->head = temp->next;
      free(temp->data);
      free(temp);
      q->sizeOfQueue--;
  }

  q->head = q->tail = NULL;
}

int getQueueSize(Queue *q)
{
    return q->sizeOfQueue;
}
TestQueue.c
#include <stdio.h>
#include <stdlib.h>
#include "Queue.h"

int main()
{
    int val;
    Queue q;

    queueInit(&q, sizeof(int));

    for(val = 0; val < 10; val++)
    {
        enqueue(&q, &val);
        printf("The value %d has been enqueued.\n", val + 1);
    }

    printf("\n");

    queuePeek(&q, &val);

    printf("The value that is at the front of the queue is %d\n\n", val + 1);

    while(getQueueSize(&q) > 0)
    {
        dequeue(&q, &val);
        printf("%d has been dequeued.\n", val + 1);
    }

    return 0;
}

下面让我看看他提的一些建议:

// #endif /* QUEUE_H_INCLUDED */
#endif

关于size_t,int和unsigned int可参考此文https://prateekvjoshi.com/2015/01/03/why-do-we-need-size_t/, size_t,size_t的取值range是目标平台下最大可能的数组尺寸(非负数),一些平台下size_t的范围小于int的正数范围,又或者大于unsigned int。为了移植性和性能考虑,有些情况下表示大小尽可能使用size_t

#include "Queue.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// #include "Queue.h"

关于头文件依赖顺序说明可以参看:https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/headers/
1,foo/bar.h.
2,C 系统文件
3,C++系统文件
4,其他库头文件
5,本项目内头文件,
实际上《C++编程思想》对于2,3,4,5建议的顺序可能是反过来的,两者各有利弊。但有一点本文件相关的头文件必须放在第一位,可以防止在本文件(如上面的bar.h)里面少包含了必须的头文件。

另外还有一个回答建议Node结构体的声明可以在.c文件中定义,如果其不是对外公开的数据结构体。

原文网址:

https://codereview.stackexchange.com/questions/141238/implementing-a-generic-queue-in-c

上一篇 下一篇

猜你喜欢

热点阅读