2

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

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

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

有什么办法吗?

谢谢!

4

3 回答 3

3

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

  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索引,以及size选项 1 的值。如果您的队列协议是这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;
于 2013-07-08T17:16:28.403 回答
0

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

源文件:

#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 的帮助和耐心。如果有人需要帮助理解这段代码,很高兴解释。我还在谷歌代码上创建了这个项目,很高兴收到你的想法和批评!

于 2013-07-09T18:47:02.893 回答
0

您可以使用 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

于 2013-07-08T18:10:27.693 回答