Drzewo binarne

0

Napisałem program w języku C, kompiluje się uruchamia i w pewnym momencie pojawia się problem (przypuszczam że dotyczy alokacji pamięci ale nie mam pewności ) czy mógłby ktoś sprawdzić mój kod i pomóc znaleźć błąd

#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#define max 20

struct Wezel
       {
       char *slowo ;
       int ilosc;
       struct Wezel *lewo; 
       struct Wezel *prawo;
       };
typedef struct Wezel wezel;


wezel* drzewo(wezel *korzen, char *sslowo)
{
int a;
        if(korzen==NULL)
        {
          korzen= (struct Wezel *) malloc(sizeof (struct Wezel));
          if (korzen==NULL) getch();
          korzen->ilosc= 1;
          korzen->lewo = NULL;
          korzen->prawo = NULL;   
          strcpy (korzen->slowo, sslowo);
          printf("mowy\n");
          getch();
        }
        else
        {
        a = strcmp(sslowo,korzen->slowo);
        if(a ==0)
        korzen->ilosc++;
        else
            {
            if(a<0)
                   {
                   korzen->lewo=drzewo(korzen->lewo,sslowo);
                   printf("lewo\n");
                   }
            else
                   {
                   korzen->prawo=drzewo(korzen->prawo,sslowo);
                   printf("prawo\n");
                   }
            }
        }
return korzen;
}



void WypiszDrzewo(struct Wezel *korzen)
{   
        if (korzen != NULL)
        {
                WypiszDrzewo(korzen->lewo);
                printf("%4d   %s\n",korzen->ilosc,korzen->slowo);
                WypiszDrzewo(korzen->prawo);
        }
}

main()
{
char   sslowo[max];      
FILE* t;
wezel *korzen = NULL;

t = fopen( "test.txt", "r" );
if (t==NULL) return 1;          


        while (!feof(t))
        {
                fgets(sslowo,sizeof(sslowo),t);
                printf("%s",sslowo);   
                korzen = drzewo(korzen,sslowo);
        }
fclose(t);        
        
WypiszDrzewo(korzen); //wypisuje rekurencyjnie drzewo

getch();
return 0;
}

http://rapidshare.com/files/347823823/test.txt.html to link do pliku txt na jakim ma pracować mój program
program ten ma liczyć ile razy wystąpiło dane słowo

0

Dobrze, że wklejasz kod i dajesz przykład, ale nie każdy ma pod ręką kompilator C. Gdybyś dał więcej informacji, to i ci, co nie mogą skorzystać z kompilatorów mogliby Ci sprawnie pomóc.

Nie podałeś nawet komunikatu o błędzie. "W pewnym momencie pojawia się problem". Kiedy i gdzie? Jaki problem? To tak jakby ktoś Ci powiedział, że w "pewnym miejscu musisz wprowadzić do kodu poprawkę".

Takie rzeczy możesz sprawdzić co najmniej na 3 sposoby. Jeden to odpalenie programu w debuggerze i wykonywanie wszystkiego krok po kroku. Drugi to wstawienie tu i ówdzie debugujących printfów. Np. wstawiaj printf("1\n"), a parę linijek printf("2\n"). Gdy pojawi się 1, ale nie 2, to znaczy że błąd jest gdzieś pomiędzy. Przemieszczaj printfy aż będą otaczały pojedynczą instrukcję -- tam będzie błąd. Trzeci sposób to przeglądanie kodu całkowicie z pały, bez jakiegoś narzędzia i szukanie podejrzanych instrukcji.

Tym ostatnim sposobem zauważyłem np. problem w tym miejscu:

korzen= (struct Wezel *) malloc(sizeof (struct Wezel));
          if (korzen==NULL) getch();
          korzen->ilosc= 1;
          korzen->lewo = NULL;
          korzen->prawo = NULL;  
          strcpy (korzen->slowo, sslowo); /* Ups! korzen->slowo nie jest zainicjalizowany */

Co prawda alokujesz pamięć dla całego węzła korzen, również dla wszystkich jego wskaźników, ale nie inicjalizujesz już wskaźnika korzen->slowo. Wskaźnik ten istnieje, ale nie wskazuje na obszar pamięci, w który możesz wstawić znaki. Dlatego strcpy nie może tam poprawnie skopiować słowa ze zmiennej sslowo, bo po prostu nie ma tam miejsca. Musisz tam zrobić jeszcze jeden malloc, specjalnie dla korzen->slowo. Albo może lepiej zmień pole slowo ze wskaźnika na char na tablice konkretnej liczby charów? Masz już #define max 20, możesz go użyć. I potem użyć nie strcpy, tylko strncpy dla bezpieczeństwa.

Nie wiem czy to jedyny problem, ten mi się po prostu rzucił w oczy.

Jeszcze parę uwag.

(Pseudo)stałe zrobione za pomocą #define piszemy wg konwencji wielkimi literami, czyli nie max, tylko MAX. Tak się po prostu przyjęło i warto to wiedzieć. I stosować, chyba że w zespole macie inny standard.

W programie przydzielasz dynamicznie pamięć za pomocą malloc, ale nie zwalniasz jej (za pomocą free). To zła praktyka, prowadząca do wycieków pamięci (memory leaków). Twój kod nie wygląda beznadziejnie, czy głupio, a w paru miejscach stosujesz nawet bardzo dobre praktyki (trochę obsługi błędów, #define dla rozmiaru bufora, rzutowanie malloc itd.), więc troszkę mnie dziwi że olałeś to free. Cóż, może np. prowadzący zajęcia nie zwraca na to uwagi. Spotkałem tu jednak typków, którzy byli po Javie czy innym języku z garbage collectorem i nie wiedzieli, że coś takiego jak free (lub delete w C++) w ogóle istnieje, więc nieśmiało niniejszym o tym wspominam.

Na forum możesz włączyć kolorowanie składni otwierając tag code w ten sposób:

```c

Zamiast c możesz wpisać skróty nazw innych języków, np. cpp (dla C++), java, delphi, php itd.

Zauważ też proszę, że w dziale C/C++ i w innych jest kilka przypiętych tematów, które warto przeczytać. Są tam m.in. instrukcje dotyczące nazewnictwa tematów. "Drzewo binarne" to nie jest taka zła nazwa jak "pomocyyy!", choć może mogłeś dodać np. po myślniku "segfault", jeśli właśnie taki błąd łapiesz. No i koniecznie dodawaj taga [C] lub [C++]. Raz, że niektórzy tu się bardziej specjalizują w jednym z tych języków, a dwa, że temat może zostać przeniesiony np. do działu Newbie (choć ten temat akurat nie jest taki całkiem noobowaty) i wtedy już zupełnie nie będzie wiadomo o jaki język chodzi.

0

dziękuję faktycznie co do np zwolnienia pamięci to powinno się pojawić

a oto komunikat jaki mi się pojawia po chwili wykonywania programu gdy uruchomiłem mój program w C++Builder

Project Project1 raised exception class EaccessViolation with message 'Access Violation at adress
32609C3C. Write of adress FFFFFFFC'. Process stopped. Use Step or Run to continue.

1 użytkowników online, w tym zalogowanych: 0, gości: 1