打印 FIFO 数组时出现问题

Trouble when printing an FIFO array

我正在尝试创建一个先进先出数组,但出于某种原因,我的数组中的某些值正在打印 0 而不是实际值。 到目前为止,我尝试打印代码中的每个值,寻找该问题的原因,但我几乎是 C 语言的初学者,我不知道如何才能更好地解决代码中的错误。

这是编译器正在打印的内容,第一列是我的数组的开头,第二列是结尾。 qtde 是数组中有多少个值,tam 是数组的大小。 |x| 中的数字'i' 来自 imprimir_fila 'for':

--------Teste--------
0, 0
0, 1
0, 2
1, 3
2, 4
2, 5
2, 6

qtde: 5
tam: 6
[30 |3|,0 |4|,0 |5|,60 |6|, 70|7|]

到目前为止,这是我的代码:

    typedef enum boolean{false=0, true=1} Boolean;
    typedef int TipoElemento;
    
    typedef struct {
    TipoElemento* vetor; //Array
    int tam;             //Size of the array
    int inicio;          //Start of the array
    int fim;             //End of my array
    int qtde;            //How many values there is in my array
}Fila;
    
    Fila* fila_criar();
    Boolean fila_inserir(Fila* f, TipoElemento elemento);
    Boolean fila_remover(Fila* f, TipoElemento* saida);
    void verifica_aumenta(Fila* f);
    void fila_imprimir(Fila* f);
    
//Creates the array.
    Fila* fila_criar(){
      Fila* f = (Fila*)malloc (sizeof(Fila));
      f->tam = 3;
      f->qtde = 0;
      f->vetor = (TipoElemento*) malloc(f->tam * sizeof(TipoElemento));
      f->inicio = 0;
      f->fim = -1;
    
      return f;
    }
    
//Add a value into the array
    Boolean fila_inserir(Fila* f, TipoElemento elemento){
      if(f == NULL) return false;
      verifica_aumenta(f);
            
      f->fim++;
      f->vetor[f->fim] = elemento;
      f->qtde++;
      
      return true;
    }
    
//Removes a value
    Boolean fila_remover(Fila* f, TipoElemento* saida){
      if(f == NULL) return false;
    
      *saida = f->vetor[f->inicio];
      if(f->inicio == f->tam) f->inicio = 0;
            
      f->inicio = f->inicio+1;
      f->qtde--;
    
      return true;
    }
    
//Doubles the size of the array if it hits the limit
    void verifica_aumenta(Fila* f){
      if(f->qtde < f->tam) return;
      TipoElemento* clone = (TipoElemento*) calloc(f->tam*2, sizeof(TipoElemento));
    
      for(int i=0; i < f->tam; i++){
        clone[i] = f->vetor[i];
      }
    
      free(f->vetor);
      f->tam *= 2;
      f->vetor = clone;
    }
    
//Printf
    void fila_imprimir(Fila* f){
      if(f == NULL) return;
    
      printf("[");
      int j, i = f->inicio;
      for(j = 0; j < f->qtde; j++){
    
        printf("%d", f->vetor[i++]);
    
        if(j < f->qtde-1) printf(", ");
        if(i > f->tam) i = 0;
      }
      printf("]");
      printf("\n");
    }

这就是我正在做的测试:

    void teste(){
      Fila* f = fila_criar();
      TipoElemento saida;
    
      fila_inserir(f, 10);
      fila_inserir(f, 20);
      fila_inserir(f, 30);
      fila_remover(f, &saida);
      fila_inserir(f, 40);
      fila_remover(f, &saida);
      fila_inserir(f, 50);
      fila_inserir(f, 60);
      fila_inserir(f, 70);
      
    
      fila_imprimir(f);
    }

抱歉我的英语不好,这是我在 Stack Overflow 中的第一个问题,我会很感激能帮助我更好地解释我的问题的提示。感谢关注!

插入三个元素后,你有f->fim == 2fim->qtde == 3,这很好。当您删除一个元素时,您会递减 fim->qtde,因此它现在的值为 2,大概是因为您只保留“活动”元素的数量。所以 verifica_aumenta 中的测试注意到 fim->qtde 小于等于 3 的 f->tam,因此它不会扩大缓冲区。但是 fila_inserir 确实 f->fim++,所以现在 f->fim == 3,并且在下一行写入 f->vetor[f->fim] 会溢出缓冲区。在那之后你有未定义的行为,任何事情都可能发生。

在我看来 verifica_aumenta 中的测试应该是 if (f->fim < f->tam - 1) return;,否则您可能想以其他方式重新设计您的逻辑。 (您还可以通过使用 realloc() 来简化该函数,而不是本质上手动重新发明它。)

我使用 valgrind 找到了这个。如果您要使用 malloc 在 C 中编程,您 必须 学习如何使用这个或类似的 malloc 检查器。