[英]C array of pointers to structs realloc() error
I'm trying to make a Huffman code to practice C coding and I keep geting the same error. 我正在尝试制作一个霍夫曼代码来练习C编码,并且我仍然保持同样的错误。
Let me explain the code. 让我解释一下代码。 First it creates the struct below:
首先,它创建下面的结构:
struct sNo {
int valor;
char letra;
struct sNo *esq;
struct sNo *dir;
};
typedef struct sNo sNo;
Then it creates an array of structs ('No'): 然后它创建一个结构数组('否'):
sNo *No;
No = calloc(qtd_no, sizeof(sNo));
It reads a string from the keyboard placing in this array the letter and the ammount of times it appears. 它从键盘中读取一个字符串,在该数组中放置字母和它出现的次数。 Like the representation below with the word 'abracadabra':
就像下面的代表'abracadabra'一样:
No: a/5 b/2 r/2 c/1 d/1
Now, to make a Huffman tree, it's needed that I create another array ('pNo'), with pointers to the original array: 现在,要创建一个Huffman树,我需要创建另一个数组('pNo'),并指向原始数组:
int qtd_pno = qtd_no;
sNo **pNo;
pNo = calloc(qtd_pno, sizeof(sNo*));
for (i = 0; i < qtd_pno; i++){
pNo[i] = &No[i];
}
The two arrays appear like that: 这两个数组看起来像这样:
No: a/5 b/2 r/2 c/1 d/1
pNo: a/5 b/2 r/2 c/1 d/1
After that it can sort the array of pointers like below without changing the original one: 之后,它可以像下面那样对指针数组进行排序而不更改原始指针:
No: a/5 b/2 r/2 c/1 d/1
pNo: c/1 d/1 r/2 b/2 a/5
But when it tries to increase the size of the 'No' array... 但是当它试图增加'No'数组的大小时......
qtd_no++;
No = realloc(No,(sizeof(sNo) * qtd_no));
... this is what happens with the arrays: ...这是数组发生的事情:
No: a/5 b/2 r/2 c/1 d/1 /0
pNo: c/1 d/1 r/2 b/2 /0
or something like that: 或类似的东西:
No: a/5 b/2 r/2 c/1 d/1 /0
pNo: c/1 d/1 r/2 b/2 �/1288268632
Note that I'm not changing anything on the 'pNo' array, but somehow the value pointed is. 请注意,我没有更改'pNo'数组中的任何内容,但不知何故,指向的值是。 I think it could be some specific characteristic of dynamic memory allocation, but I'm not sure.
我认为它可能是动态内存分配的一些特定特性,但我不确定。
EDIT 编辑
The complete code is below: 完整代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//Definicao do tipo struct No
struct sNo {
int valor;
char letra;
struct sNo *esq;
struct sNo *dir;
};
typedef struct sNo sNo;
//Funcoes
void SelectionSort(sNo *A[], int qtd_no);
void ImprimeArvore (sNo *a);
int main(){
//Variaveis auxiliares
int i, j;
//Leitura de texto do teclado
char texto[30];
printf("Digite frase \n");
setbuf(stdin, NULL);
fgets(texto, 30, stdin);
//Criacao dos nos
int qtd_no = 0;
sNo *No;
for(i = 0; i < strlen(texto) && texto[i] != '\0'; i++){
if(texto[i] >= 32){
if(i == 0){
qtd_no++;
No = calloc(qtd_no, sizeof(sNo));
if(No == NULL){
printf("Erro: memoria insuficiente\n");
exit(1);
}
No[i].letra = texto[i];
No[i].valor = 1;
No[i].esq = NULL;
No[i].dir = NULL;
printf("%d\t%c %c\t%d\n", i, texto[i], No[i].letra, No[i].valor);
}else{
for(j = 0; j <= qtd_no - 1; j++){
if(texto[i] == No[j].letra){
No[j].valor++;
printf("%d %d\t%c %c\t%d\n", i, j, texto[i], No[j].letra, No[j].valor);
break;
}
else if(j == qtd_no - 1){
qtd_no++;
No = realloc(No,(sizeof(sNo) * qtd_no));
if(No == NULL){
printf("Erro: memoria insuficiente\n");
exit(1);
}
No[j+1].letra = texto[i];
No[j+1].valor = 1;
No[j+1].esq = NULL;
No[j+1].dir = NULL;
printf("%d %d\t%c %c\t%d\n", i, j, texto[i], No[j+1].letra, No[j+1].valor);
break;
}
}
}
}
}
//Criacao de array com ponteiros para nos
int qtd_pno = qtd_no;
sNo **pNo;
pNo = calloc(qtd_pno, sizeof(sNo*));
if(pNo == NULL){
printf("Erro: memoria insuficiente\n");
exit(1);
}
for (i = 0; i < qtd_pno; i++){
pNo[i] = &No[i];
}
//Organizacao dos nos pelo valor
SelectionSort(pNo, qtd_pno);
//Criacao da arvore binaria
while(qtd_pno > 1){
qtd_no++;
No = realloc(No,(sizeof(sNo) * qtd_no));
if(No == NULL){
printf("Erro: memoria insuficiente\n");
exit(1);
}
No[qtd_no - 1].letra = '\0';
No[qtd_no - 1].valor = (pNo[0]->valor) + (pNo[1]->valor);
No[qtd_no - 1].esq = pNo[0];
No[qtd_no - 1].dir = pNo[1];
if(qtd_pno > 2){
for(i = 0; i <= qtd_pno-2; i++){
pNo[i] = pNo[i+2];
}
}
qtd_pno--;
pNo = realloc(pNo,(sizeof(sNo*) * qtd_pno));
pNo[qtd_pno - 1] = &No[qtd_no - 1];
if(qtd_pno > 1){
SelectionSort(pNo, qtd_pno);
}
}
sNo *raiz;
raiz = pNo[0];
free(pNo);
printf("\n%s\n", texto);
ImprimeArvore(raiz);
printf("\n");
}
//Funcao de organizacao por valor
void SelectionSort(sNo *A[], int qtd_pno){
sNo *temp;
int i, j, Imin;
for(i = 0; i < qtd_pno - 1; i++){
Imin = i;
for(j = i + 1; j < qtd_pno; j++){
if((A[j]->valor) < (A[Imin]->valor)){
Imin = j;
}
}
temp = A[Imin];
A[Imin] = A[i];
A[i] = temp;
}
}
void ImprimeArvore(sNo *a){
if(a->letra) printf ("<%c/%d", (a->letra), (a->valor));
else printf ("<_/%d", (a->valor));
if(a->esq != NULL) ImprimeArvore (a->esq);
if(a->dir != NULL) ImprimeArvore (a->dir);
printf (">");
}
The problem with your approach is that realloc
does not make any guarantees about expanding your array in place. 您的方法的问题是
realloc
无法保证扩展您的阵列。
to make a Huffman tree, it's needed that I create another array ('pNo'), with pointers to the original array
要制作一个霍夫曼树,需要我创建另一个数组('pNo'),用指向原始数组的指针
Since you have pointers to calloc
-ed array inside other struct sNo
objects, calling realloc
on the block that has these structures may invalidate all external pointers to these structures. 由于您在其他
struct sNo
对象中有指向calloc
-ed数组的指针,因此在具有这些结构的块上调用realloc
可能会使这些结构的所有外部指针无效。 That is why your code runs into undefined behavior after a call to realloc
. 这就是为什么你的代码在调用
realloc
后会遇到未定义的行为。
One approach to fixing this problem is to store indexes instead of pointers. 解决此问题的一种方法是存储索引而不是指针。 This works, as long as you keep a single dynamic array to which you add new items, but never remove items from it.
只要您保留一个添加新项目的动态数组,但从不从中删除项目,这就可以。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.