【问题标题】:Multi size queue without malloc没有 malloc 的多大小队列
【发布时间】:2013-07-08 16:41:57
【问题描述】:

我有兴趣构建一个可以接收不同但已定义大小的队列。假设有 8、16 和 32 个元素,我想在不使用 malloc 的情况下做到这一点。 好吧,如果我创建 3 个不同的队列会很容易,但我不想这样做,我想使用相同的函数并只定义三种类型。

我的问题正是这个,我的代码中有三个地方我想使用队列,但这些情况会使用不同大小的队列,我知道它的大小。我不想创建三组函数和结构来创建这个队列,我只想创建三个结构并使用相同的函数。另外,我不能使用 malloc,因为它是一个嵌入式应用程序。

我想了解如何在 C 中创建抽象类型的 C++。它可以解决我的问题。

有什么办法吗?

谢谢!

【问题讨论】:

  • 在 C++ 中,您可能可以为此创建一个模板类。
  • 但我想在 C 中执行此操作。
  • 如果您知道确切的大小,为什么不使用堆栈变量(数组)?
  • 恢复为数组而不是队列,你的问题就解决了!
  • 也许您应该为只有一个大小的元素的队列添加示例代码。这将使问题更容易回答。

标签: c queue


【解决方案1】:

有几种方法可以做到这一点。这里有一对...

  1. 在队列头中包含队列的大小;访问队列的函数使用头部的大小来限制条目的数量

  2. 将队列大小作为参数传递给管理队列的函数

第一个选项不太容易出错,但需要一个额外的标题字段。

结构将被定义为

static struct s_que8
{
   int in;
   int out;
   int size; // for option 1
   int elements[8]; // or whatever size you like
} que8;

在任何情况下,队列都需要初始化 inout 索引,以及选项 1 的 size 值。如果您的队列协议是 in == out 表示队列为空,您只需设置in = out = 0; 来初始化它们。

附录

对于静态字符串的元素,这里有一些特定的结构声明:

static struct s_que8
{
   int in;
   int out;
   int size; // for option 1
   char * elements[8]; // for pointers to static strings
} que8;

static struct s_que8
{
   int in;
   int out;
   int size; // for option 1
   char elements[8][MAX_STRING_SIZE]; // for strings stored in the queue
} que8;

更改 8 以适合您的特定队列大小。

相应的“通用”类型定义为:

typedef struct s_queX
{
   int in;
   int out;
   int size; // for option 1
   char * elements[]; // for pointers to static strings
} Queue;

typedef struct s_queX
{
   int in;
   int out;
   int size; // for option 1
   char elements[][MAX_STRING_SIZE]; // for strings stored in the queue
} Queue;

【讨论】:

  • 好的,但是,像 dequeue(Queue * queue) 这样的函数呢?也就是说,我会将什么作为参数传递给这个函数?
  • 对于选项 2,您将传递 size,如 dequeue(Queue * queue, int size)
  • 在这种情况下队列是什么?指向什么结构的指针,s_que8、16 还是 32?
  • 你可以使用typedef struct s_queX { int in; int out; int size; int elements[]; } Queue;,因为C允许结构的最后一个元素是一个开放大小的数组。
  • 即使我的元素是字符串?
【解决方案2】:

您可以使用 free_elements 创建一个 TAILQ,每次您需要一个元素时,您都可以将其从 free_elements 队列中移除、使用,然后再将其插入到列表中。

对于 malloc 问题,您需要使用静态内存来初始化队列。

例子:

static struct my_element free_elements_array[TOTAL_ELEMENTS];

extern int my_queue_init(void)
{
    int i;
    TAILQ_INIT(my_queue_head);

    for (i=0; i<TOTAL_ELEMENTS;i++)
        TAILQ_INSERT_TAIL(my_queue_head, &free_elements_array[i]);

    return 0;
}

extern struct my_element *get_element(void)
{
    struct my_element *element;
    element = TAILQ_LAST(my_queue_head)
    if (element)
    {
        TAILQ_REMOVE(my_queue_head, element)
    }
    return element.
}

TAILQ 只是一个建议,我的代码中的宏并不完整,仅用作示例。有关他们和其他队列的更多信息,请参阅http://linux.die.net/man/3/queue

【讨论】:

    【解决方案3】:

    我已经发现了如何做到这一点。也许我表达错了,但我已经达到的这个解决方案解决了我的问题:

    源文件:

    #include "Fila.h"
    #include <string.h>
    #include <stdio.h>
    
    void Fila_Init(Fila_t * fila, const uint32_t qtdLinhas, const uint32_t qtdColunas, char ** buffer)
    {
        fila->qtdLinhas = qtdLinhas;
        fila->qtdColunas = qtdColunas;
        fila->head = 0;
        fila->tail = 0;
        fila->tamanho = 0;
        fila->linhas = buffer;
        uint32_t i;
        for(i = 0; i < fila->qtdLinhas; i++)
            memset(fila->linhas[i], FILA_CARACTERE, FILA_COLUNAS);
    }
    
    void Fila_Enfileira(Fila_t * fila, int tamDado, const char * dado)
    {
        if(tamDado > FILA_COLUNAS)
            tamDado = FILA_COLUNAS;
    
        if (FILA_TAIL == FILA_HEAD && (fila->tamanho + 1) > fila->qtdLinhas)
                fila->head++;
    
        memset(fila->linhas[FILA_TAIL], FILA_CARACTERE, FILA_COLUNAS);
        fila->linhas[FILA_TAIL][tamDado] = '\0';
    
        memcpy(fila->linhas[FILA_TAIL_INC], dado, tamDado);
    
        if(fila->tamanho < fila->qtdLinhas)
            fila->tamanho++;
    }
    
    char * Fila_Desenfileira(Fila_t * fila)
    {
        if(Fila_TemProximo(fila))
            fila->tamanho--;
    
        return fila->linhas[FILA_HEAD_INC];
    }
    
    inline char * Fila_Primeiro(Fila_t * fila)
    {
        return fila->linhas[FILA_HEAD];
    }
    
    inline bool Fila_TemProximo(Fila_t * fila)
    {
        return (fila->tamanho > 0);
    }
    
    void Fila_Imprime(Fila_t * fila)
    {
      int tamanho = fila->tamanho;
      int cabeca = fila->head;
      while(tamanho > 0)
      {
        printf("%s\n", fila->linhas[(cabeca++ % fila->qtdLinhas)]);
        tamanho--;
      }
    }
    

    头文件:

    /*
     * Fila.h
     *
     *  Created on: 18/06/2013
     *      Author: Leandro
     */
    
    #ifndef FILA_H_
    #define FILA_H_
    
    #include "types.h"
    #include <stdint.h>
    
    #define FILA_COLUNAS (fila->qtdColunas)
    #define FILA_CARACTERE 0xff
    #define FILA_TAIL (fila->tail % fila->qtdLinhas)
    #define FILA_HEAD (fila->head % fila->qtdLinhas)
    #define FILA_TAIL_INC (fila->tail++ % fila->qtdLinhas)
    #define FILA_HEAD_INC (fila->head++ % fila->qtdLinhas)
    
    typedef struct {
        uint32_t qtdLinhas;
        uint32_t qtdColunas;
        uint32_t head;
        uint32_t tail;
        uint32_t tamanho;
        char ** linhas;
    } Fila_t;
    
    void Fila_Init(Fila_t * fila, const uint32_t qtdLinhas, const uint32_t qtdColunas, char ** buffer);
    void Fila_Enfileira(Fila_t * fila, int tamDado, const char * dado);
    char * Fila_Desenfileira(Fila_t * fila);
    bool Fila_TemProximo(Fila_t * fila);
    char * Fila_Primeiro(Fila_t * fila);
    void Fila_Imprime(Fila_t * fila);
    
    #endif /* FILA_H_ */
    

    还有,测试文件:

    #include "Fila.h"
    #include <stdio.h>
    #include <string.h>
    
    Fila_t testeStatic()
    {
        static char ele[8][512];
        const int c = sizeof(ele[0])/sizeof(ele[0][0]);
        const int l = sizeof(ele)/c;
    
        printf("Tamanho da matriz: %d bytes.\n", c*l*sizeof(char));
        char* ele2[c];
        int i = 0;
        for (i = 0; i < l; i++)
            ele2[i] = ele[i];
    
        Fila_t fila;
        Fila_Init(&fila, l, c, ele2);
    
        printf("Tamanho da matriz de ponteiros na fila: %d bytes.\n", sizeof(fila) - 5*sizeof(uint32_t));
        printf("Tamanho da fila: %d bytes.\n", sizeof(fila));
        printf("Tamanho final de uma fila [8][512]: %d\n", c*l*sizeof(char)+sizeof(fila));
        printf("Overhead de apenas 24 bytes ou %f por cento.\n", (float)((sizeof(fila) * 100))/(c*l*sizeof(char)));
        return fila;
    }
    void testaFila(Fila_t * fila)
    {
        char texto[20];
        int i;
        for (i = 0; i < 50; i++)
            Fila_Enfileira(fila, sprintf(texto, "Entrada [%d]", i), texto);
    
        while (Fila_TemProximo(fila))
            printf("%s\n", Fila_Desenfileira(fila));
    }
    
    int main()
    {
        Fila_t fila = testeStatic();
        testaFila(&fila);
    
        return 0;
    }
    

    抱歉,它是葡萄牙语,但我相信即使是我的语言,它也会有所帮助。 特别感谢@Doug Currie 的帮助和耐心。如果有人需要帮助理解这段代码,很高兴解释。我还在谷歌代码上创建了这个project,很高兴收到你的想法和批评!

    【讨论】:

      猜你喜欢
      • 2023-03-10
      • 1970-01-01
      • 2012-06-18
      • 2012-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-05
      相关资源
      最近更新 更多