Lista dwukierunkowa ANSI C

0

Witam.

Mam taki o to problem, ze wyskauje mi sigesev w codebloksie. Nie wiem co tu robie zle.

#include <stdio.h>
#include <stdlib.h>

typedef struct List
{
    char question[300];
    char answerA[200];
    char answerB[200];
    char answerC[200];
    char correct;

}List;

typedef struct Node
{
    List data;
    struct Node * next;
    struct Node * previous;
} Node;



void add_begin(Node **begin,struct List data_temporarily)
{
   Node * new_node;
    new_node=(struct Node*)malloc(sizeof(struct Node));
    if (new_node==NULL)
    {
        printf("BRAK PAMIECI !");
    }

    else printf("pamiec zaalokowana poprawnie! \n");

    new_node->data=data_temporarily;

  (*begin)->previous=new_node;
  new_node->next = *begin;
  new_node->previous=NULL;
   *begin = new_node;

    printf("pamiec zaalokowana poprawnie!\n");
}

int main()
{

 struct Node * list_begin=NULL; //tak jakby pierwszy element


    List przyklad ={"pierwsze 111111 pytanko", "odpa" ,"odpb" ,"odpc" ,'s' }; // za pomoca tego mozna bedzie wczytywac z pliku
    List przyklad1 ={"drugie 222222", "odpowiadamAAAAA" ,"odpBBBBb" ,"odpcCCCCC" ,'h' };
    List przyklad2 ={"trzecie33333333 pytanie xaxaxa", "IIIIIII" ,"LLLLLL" ,"UUUUUU" ,'z' };
    List przyklad3 ={"czwarte 4444444444", "III4444" ,"L4444L" ,"UU4444U" ,'a' };
    List przyklad4 ={"ostatttttniiiii", "_______" ,"yyyyyyy" ,"xxxxxxxxxxxx" ,'a' };

add_begin(&list_begin,przyklad); 
add_begin(&list_begin,przyklad1); 
add_begin(&list_begin,przyklad2); 

    return 0;
}


 
1

Potrafi zdziałać cuda przy SIGSEGV: http://www.unknownroad.com/rtfm/gdbtut/

1

Nie wiem w czym problem. Kod, który dostarczyłeś się poprawnie kompiluje.

Mogę jedynie zgadywać.
Masz takie coś, że w mainie ustawiasz list_begin na NULL. Potem pewnie chcesz dodać coś do listy, wiec wywołujesz add_begin, a tam masz taki kwiatek

(*begin)->previous=new_node;

I masz null pointer dereference. Próbujesz zapisać coś pod wskaźnikiem, który wskazuje na NULLa.

Ale tak jak mówiłem na początku to tylko zgadywanki. Podaj cały kod, który się wysypuje to dopiero coś zdziałamy

0

Kod poprawiony.

(*begin)->previous=new_node; z tym jest cos nie tak ale do konca nie wiem ocb.

To jest caly kod. Zaczelem przerabiac liste jednokierunkowa na dwu. WIekszosc z funkcji jest w ogole nie tknieta.

 
#include <stdio.h>
#include <stdlib.h>

typedef struct List
{
    char question[300];
    char answerA[200];
    char answerB[200];
    char answerC[200];
    char correct;

}List;

typedef struct Node
{
    List data;
    struct Node * next;
    struct Node * previous;
} Node;



void add_begin(Node **begin,struct List data_temporarily)
{
   Node * new_node;
    new_node=(struct Node*)malloc(sizeof(struct Node));
    if (new_node==NULL)
    {
        printf("BRAK PAMIECI !");
    }

    else printf("pamiec zaalokowana poprawnie! \n");

    new_node->data=data_temporarily;


    (*begin)->previous=new_node;
    new_node->next = *begin;
    new_node->previous=NULL;
    *begin = new_node;

    printf("pamiec zaalokowana poprawnie!\n");
}



void wyswietl(Node* wsk)
{
     printf("jestem w funkcji\n");

    while(wsk)
    {
        printf("%s\n", wsk->data.question);
        printf("%s\n", wsk->data.answerA);
        printf("%s\n", wsk->data.answerB);
        printf("%s\n", wsk->data.answerC);
        printf("%c\n", wsk->data.correct);


        printf("czy mam wczytac nastepne pytanie 0-NIE 1-TAK");
        int var;
        scanf("%d", &var);
        if(var)
             wsk=wsk->next;
        else break;

        system("cls");

        if(wsk==0) printf("TO JUZ BYLO OSTANIE PYTANIE");

    }

}
void add_to_pos( Node **begin, int pos, struct List data1)
{
        pos-=1;
        struct Node *wsk=NULL;
        struct Node *S=NULL;
        struct Node *T=*begin;

        //szukanie poprzedniego i nastepnego
        while(T&&(pos>0))
        {
            S=T;
            T=T->next;
            pos--;
        }

       // wyswietl(S); //wyswietli Node ZA ktorym wstawiamy
       // wyswietl(T); // wyswietli ten Node PRZED ktorym wstawiamy

       if(pos!=0) printf("BLAD POZYCJI");
       if(wsk = (struct Node *)malloc(sizeof(struct Node))) printf("Pamiec OK\n");
       else printf("Pamiec zaalokowana poprawnie na wybranej pozycji!\n");


        // wyswietl(wsk);
        wsk->data=data1;
        wsk->next=T;

        if(S==NULL)
            *begin=wsk;
        else
            S->next=wsk;
}

void remove_node(Node **begin, int pos) //ta funkcja usuwa Node o podataj pozycji
{
    Node *S=NULL, *T=*begin;

    pos-=1;
    while(T&&(pos>0))
    {
        S=T;
        T=T->next;
        pos--;
    }

    if((pos!=0)||(T==NULL)) printf("BLAD POZYCJI\n");

    else{
            /*
            przestawianie wskaznikow S to jest poprzedni a T obecny a pozniej zostaja one przestawione
            jesli chcemy usunac pierwszy element do BEGIN czyli nasza glowa musi byc przestawiona na drugi
            w innym wypadku S (czyli poprzedni)powinien byc przestawiony nie na ten co usuwamy lecz na jeszcze
            next.
            */
            if(S==NULL) *begin=T->next;
            else  S->next=T->next;
            free(T); //usuwamy obecny!
    }

}
void clean(Node **begin)
{
    Node *wsk;
    while(*begin)
    {
        wsk=*begin;
        *begin=(*begin)->next;

        free(wsk);
    }
}

void add_end(struct Node **begin, struct List data1)
{
    Node *wsk, *S=NULL, *T=*begin;

    while(T!=0)
    {
       S=T;
       T=T->next;
    }

    if(wsk=(struct Node*)malloc(sizeof(struct Node))) printf("dodano Node na koniec\n");
    else printf("BRAK PAMIECI\n");

    wsk->data=data1;
    wsk->next=T;
    if(S==NULL) *begin=wsk;
    else    S->next=wsk;



}

void load_file(Node **begin)
{
    List single_q;
    FILE* file=fopen("questions.bin", "rb");
    while(fread(&single_q,sizeof(struct List), 1, file))
    {
        add_end(&*begin, single_q);
    }

    fclose(file);
}

void save_file(struct Node **begin)
{
    FILE* file=fopen("questions.bin", "wb");

    Node *wsk=*begin;

    while(wsk)
    {
        fwrite(&wsk->data, sizeof(struct List), 1, file);
        wsk=wsk->next;
    }

    fclose(file);

    printf("ZAPISANO!\n");

}

int main()
{

 struct Node * list_begin=NULL; //tak jakby pierwszy element

    List przyklad ={"pierwsze 111111 pytanko", "odpa" ,"odpb" ,"odpc" ,'s' }; // za pomoca tego mozna bedzie wczytywac z pliku
    List przyklad1 ={"drugie 222222", "odpowiadamAAAAA" ,"odpBBBBb" ,"odpcCCCCC" ,'h' };
    List przyklad2 ={"trzecie33333333 pytanie xaxaxa", "IIIIIII" ,"LLLLLL" ,"UUUUUU" ,'z' };
    List przyklad3 ={"czwarte 4444444444", "III4444" ,"L4444L" ,"UU4444U" ,'a' };
    List przyklad4 ={"ostatttttniiiii", "_______" ,"yyyyyyy" ,"xxxxxxxxxxxx" ,'a' };

add_begin(&list_begin,przyklad);
add_begin(&list_begin,przyklad1);
add_begin(&list_begin,przyklad2);

   // wyswietl(list_begin);



    return 0;
}

1

No to przecież to co mówiłem. W mainie masz list_begin inicjalizowanego NULLem. Przekazujesz na to wskaźnik do add_begin.
Więc w add_begin zmienna begin jest wskaźnikiem, na wskaźnik, który wskazuje na NULLa. Potem chcesz pod tego NULLa coś zapisać

(*begin)->previous=new_node;

i masz sigsegv bo pod NULLa pisać nie można.

0

Jak mogę się pozbyć tego problemu ? Chce po prostu przestawic wskaznik następnego węzła(czyli previous) na ten, który przed chwilą powstał. (*begin) prawdopodobnie w ogóle jest mylnym kierunkiem.

1

Potrzebny będzie warunek sprawdzający czy begin nie jest NULLem i dopiero jak nie jest to zapisujesz coś to jego prev czy tam next. Ogólnie przysiądź do tego i powoli to przeanalizuj. To nie jest trudne jak tylko się nad tym trochę pomyśli (:

0

Ok, dziękuje bardzo za pomoc. Już jakoś powoli leci :)

Czasami bywa i tak:
http://i.imgur.com/xVyoSl.jpg

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