2017-10-13 11 views
3

C 코딩을 연습하기 위해 허프만 코드를 만들려고 노력 중이며 동일한 오류가 계속 발생합니다.구조체에 대한 포인터의 C 배열 realloc() 오류

코드를 설명해 드리겠습니다.

sNo *No; 
No = calloc(qtd_no, sizeof(sNo)); 

그것은이 배열의 키보드 배치에서 문자열을 문자와를 읽 그 다음은 구조체의 배열 ('아니오')를 생성

struct sNo { 
    int valor; 
    char letra; 
    struct sNo *esq; 
    struct sNo *dir; 
}; 
typedef struct sNo sNo; 

: 첫째는 아래의 구조체를 생성 그것이 나타나는 시간. 단어 '아브라카 다 브라'와 아래의 표현처럼 :

int qtd_pno = qtd_no; 
sNo **pNo; 
pNo = calloc(qtd_pno, sizeof(sNo*)); 
for (i = 0; i < qtd_pno; i++){ 
    pNo[i] = &No[i];  
} 
: 나는 다른 배열 ('PNO')를 만드는 것이 이제

No: a/5 b/2 r/2 c/1 d/1 

하는 허프만 트리를 만들기 위해, 그것은 원래의 배열에 대한 포인터로, 필요한

두 어레이는 그렇게 나타 : 그것은 원래의 변경없이 다음과 같은 포인터 배열을 정렬 할 수

No: a/5 b/2 r/2 c/1 d/1 
pNo: a/5 b/2 r/2 c/1 d/1 

그 후 :

,691 363,210
No: a/5 b/2 r/2 c/1 d/1 
pNo: c/1 d/1 r/2 b/2 a/5  

그러나이 '없음'배열의 크기를 증가하려고 할 때 ...

qtd_no++; 
No = realloc(No,(sizeof(sNo) * qtd_no)); 

...이 배열로 일어나는 것이다 :

No: a/5 b/2 r/2 c/1 d/1 /0 
pNo: c/1 d/1 r/2 b/2 /0 

또는 뭔가 이렇게 :

No: a/5 b/2 r/2 c/1 d/1 /0 
pNo: c/1 d/1 r/2 b/2 �/1288268632 

'pNo'배열에서 아무 것도 변경하지 않고 있습니다. 지적이다. 동적 메모리 할당의 특정 특성 일 수 있다고 생각하지만 확실하지 않습니다.

편집
전체 코드는 다음과 같습니다 : 당신의 접근 방식과

#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 (">"); 

} 
+1

'realloc'은 더 많은 메모리를 재 할당하지만 새로 할당 된 메모리는 초기화하지 않습니다. 0 또는 이상한 값은 불확정 값입니다. 베스트 [mcve]를 올립니다. –

+2

... 또한'realloc()'은 전달 된 포인터의 값을 "무효화"하고 "원본"값의 다른 모든 복사본도 "무효화"합니다. – alk

답변

7

문제는 realloc 자리에 배열을 확장에 대한 보증을하지 않습니다.

허프만 트리를 만들기 위해, 당신이 다른 struct sNo 객체 내부 calloc -ed 배열에 대한 포인터를 가지고 있기 때문에 원래 배열

포인터와 다른 배열 ('PNO')를, 만드는 것이 필요한 이러한 구조를 가진 블록에서 realloc을 호출하면 이러한 구조에 대한 모든 외부 포인터가 무효화 될 수 있습니다. 따라서 realloc을 호출 한 후 코드가 정의되지 않은 동작으로 실행되는 것입니다.

이 문제를 해결하기위한 한 가지 방법은 포인터 대신 인덱스를 저장하는 것입니다. 이 작업은 새 항목을 추가하는 단일 동적 배열을 유지하면서 항목을 제거하지 않는 한 작동합니다.