【问题标题】:How to set size of circular queue如何设置循环队列的大小
【发布时间】:2015-11-04 00:39:13
【问题描述】:

我正在尝试在 C 中实现一个通用的循环缓冲区(队列)。到目前为止,这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/queue.h>

CIRCLEQ_HEAD(circleq, entry) head;
struct circleq *headp;              /* Circular queue head. */
struct entry {
  CIRCLEQ_ENTRY(entry) entries;   /* Circular queue. */
  int number;
};

int main() 
{
  CIRCLEQ_INIT(&head); 

  // Add some numbers to the queue
  int i;
  for (i = 0; i < 10; i++) {
    struct entry* n = malloc(sizeof(struct entry));
    n->number = i;
    CIRCLEQ_INSERT_HEAD(&head, n, entries);
    printf("Added %d to the queue\n", n->number);
  }

  // Remove a number from the queue
  struct entry *n;
  n = CIRCLEQ_FIRST(&head);
  CIRCLEQ_REMOVE(&head, head.cqh_first, entries);
  printf("Removed %d from the queue\n", n->number);

  return 0;
}

产生以下输出:

Added 0 to the queue
Added 1 to the queue
Added 2 to the queue
Added 3 to the queue
Added 4 to the queue
Added 5 to the queue
Added 6 to the queue
Added 7 to the queue
Added 8 to the queue
Added 9 to the queue
Removed 9 from the queue

我对 C 语言不是很熟悉,我的问题是:

  1. 如何设置队列限制,例如,只有 5 个数字 一次可以放入缓冲区吗?如果另一个项目试图 在此之后添加,我应该能够检测到它并做一些事情 关于它(忽略它,等待,退出程序等)。

  2. 我的代码似乎从缓冲区中删除了最后一项 - 我该怎么做 让它从尾部删除项目(数字 0 而不是 9,在我的 例如)?

我已通读http://linux.die.net/man/3/queue,但似乎不清楚我如何才能完成上述两件事。

【问题讨论】:

  • 来自 sys/queue.h 的 CIRCLEQ 不提供限制。您需要自己记录物品数量,并在超过该限制时移除物品。

标签: c circular-buffer


【解决方案1】:
  1. 如果您查看 的描述,这种缓冲区的主要优点之一是它使用单个固定分配,而您的基本上只是一个循环链表。创建时使用的固定大小指定了环形缓冲区可以容纳的元素数量的限制。

  2. 如果你有一个正确实现的循环缓冲区,删除一个项目只需要简单地推进尾部指针,如果需要的话会回到前面。

表示循环缓冲区的示例结构可能如下所示:

struct circleq
{
    int* buf;
    int head;
    int tail;
    int size;
};

void init(struct circleq* q, int size)
{
    q->buf = malloc(sizeof(int) * size);
    q->head = 0;
    q->tail = size - 1;
    q->size = size;
}

void insert(struct circleq* q, int val)
{
    if(q->head == q->tail) { } // queue full, error
    else
    {
        q->buf[q->head] = val;
        q->head = (q->head + 1) % q->size;
    }
}

int remove(struct circleq* q)
{
    if((q->tail + 1) % q->size == q->head) { return 0; } // queue empty, error
    else
    {
        int val = q->buf[q->tail];
        q->tail = (q->tail + 1) % q->size;
        return val;
    }
}

void destroy(struct circleq* q)
{
    free(q->buf);
}

【讨论】:

  • 次要建议:在free(q-&gt;buf); zero/NULL out its fields 之后-即使不太可能重复调用destroy()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-02
  • 1970-01-01
  • 2016-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-17
  • 1970-01-01
相关资源
最近更新 更多