Wypisywanie listy struktur - segmentatnion fault

0

Witam, stworzyłem listę struktur którą uzupełniam danymi wczytanymi z pliku a następnie chcę wypisać dane na ekran. Projekt Buduje się bez błędów. Gdy wywołuję funkcję wypisz_listę()w konsoli wyskakuje błąd "Segmentation fault". Wiem, że szperam w niedozwolonych obszarach pamięci ale nie rozumiem dlaczego. Debugger wskazuje na linijkę z wywołaniem printf() w wypisz_listę(). Proszę o pomoc.

 
struct oper //definicja operatora
{
    char nazwa;
    int l_arg;
};

struct zmienna //definicja zmiennej
{
    char nazwa[MAX_NAZWA];
    int wart;

};

typedef struct { //jedno wyrazenie
    struct oper op;
    struct zmienna zm1;
    struct zmienna zm2;
 }wyrazenie;

typedef struct element{  //lista prosta
    struct element *next;
    wyrazenie* val;
 }el_listy;
void dodaj_do_listy (el_listy *lista, wyrazenie* wyr ) //dodaje wyrazenie do listy
 {
   el_listy *wsk, *nowy;
   wsk = lista;
   while (wsk->next != NULL)       
     {
        wsk = wsk->next; /* przesuwamy wsk aż znajdziemy ostatni element */
     }
   nowy = (el_listy*)malloc(sizeof(el_listy));  
   nowy->val = wyr;                
   nowy->next = NULL;                
   wsk->next = nowy;              
 }

void wypisz_liste(el_listy *lista)
{
    el_listy *wsk;
    wsk = lista;
    while( wsk != NULL )
    {
        printf ("%s %s %c\n", wsk->val->zm1.nazwa, wsk->val->zm2.nazwa, wsk->val->op.nazwa ); ///BŁĘDNA LINIJKA !!!!!
        wsk = wsk->next;
     }
}
int main()
{
    FILE* plik;
    char linia[MAX_CH+1];

    wyrazenie* wyr1 = malloc(sizeof(wyrazenie));
    el_listy* lista = malloc(sizeof(el_listy));
    el_listy* start = lista;
    if(( plik = fopen("plik.txt", "r")) == NULL)
    {
        printf("Nie mogę otworzyć pliku plik.txt do odczytu!\n");
        exit(1);
    }

    zeroj_wyrazenie( wyr1 );
    while( (fgets(linia, 20, plik )) != NULL )
    {
        puts(linia);
        if( przetworz_linie(linia, wyr1 ) == 0)
            continue;
        printf("wyr : zm1:%s zm2:%s op:%c\n", wyr1->zm1.nazwa, wyr1->zm2.nazwa, wyr1->op.nazwa );
        dodaj_do_listy( lista, wyr1 );
        zeroj_wyrazenie( wyr1 );
    }

    wypisz_liste(start); //lub parametr "lista", działa tak samo. 
    fclose(plik);
    return 0;
}
0
void f(int a) { a=666; }
int main()
  {
   int x=0;
   f(x);
   printf("%d",x); // CO TU SIĘ WYŚWIETLI ?
   return 0;
  }
0

Zatem, przekazuję do funkcji wskaźnik pod którym nie ma zapisanych żadnych danych?

2

Chodzi o to że funkcja dodaj_do_listy() nie jest w stanie zmienić wartości el_listy* lista który dostaje jako parametr.
Zrobiłeś bezsensowne obejście tego problemu o którym zapomniałeś w funkcji wypisz_liste()

0

Dziękuję za pomoc i wskazówki, jednym z rozwiązań problemu jest przekazywanie do funkcji "dodaj_do_listy( el_listy lista, wyrazenie wyr )" jako drugiego parametru całej struktury w tym wypadku "wyrazenie" zamiast tylko wskaźnika do niej"wyrazenie", w wyniku czego po dodaniu struktury do listy jest ona przechowywana w pamięci pod adresem elementu listy (następuje skopiowanie danych w wyniku przypisania: nowy->val = wyr; ). Dzięki temu modyfikacje wkaźnika (wyrazenie*) w dalszej części programu nie wpływają na dane przechowywane w liscie. (Jeśli popełniłem gdzieś błąd proszę o poprawę).

 
void dodaj_do_listy (el_listy *lista, wyrazenie wyr ) //zamiast wskaźnika do struktury jako drugi parametr przekazuję strukturę 
 {
   el_listy *wsk, *nowy;
   wsk = lista;
   while (wsk->next != NULL)       
     {
        wsk = wsk->next; /* przesuwamy wsk aż znajdziemy ostatni element */
     }
   nowy = (el_listy*)malloc(sizeof(el_listy));  
   nowy->val = wyr;                
   nowy->next = NULL;                
   wsk->next = nowy;              
 }
 
void wypisz_liste(el_listy *lista)
{
    el_listy *wsk;
    wsk = lista;
    while( wsk != NULL )
    {
        printf ("%s %s %c\n", wsk->val.zm1.nazwa, wsk->val.zm2.nazwa, wsk->val.op.nazwa ); ///BŁĘDNA LINIJKA !!!!!
        wsk = wsk->next;
     }
}
int main()
{
    FILE* plik;
    char linia[MAX_CH+1];
    wyrazenie = wyr;
    wyrazenie* wyr1 = &wyr;  /* malloc(sizeof(wyrazenie));*/
    el_listy* lista = malloc(sizeof(el_listy));
    el_listy* start = lista;
    if(( plik = fopen("plik.txt", "r")) == NULL)
    {
        printf("Nie mogę otworzyć pliku plik.txt do odczytu!\n");
        exit(1);
    }
 
    zeroj_wyrazenie( wyr1 );
    while( (fgets(linia, 20, plik )) != NULL )
    {
        if( przetworz_linie(linia, wyr1 ) == 0)
            continue;
        dodaj_do_listy( lista, wyr ); //zmiana wyr1 na wyr
        zeroj_wyrazenie( wyr1 );
    }
 
    wypisz_liste(lista); 
    fclose(plik);
    return 0;
}
0

Nadal działa źle, po wczytaniu ostatniego wyrażenia, wszystkie wyrażenia masz takie same.
Zmień strukturę danych:

typedef struct  //definicja operatora
{
    char nazwa;
    int l_arg;
}oper;
 
typedef struct  //definicja zmiennej
{
    char nazwa[MAX_NAZWA];
    int wart; 
}zmienna;
 
typedef struct { //jedno wyrazenie
    oper op;
    zmienna zm1;
    zmienna zm2;
 }wyrazenie;
 
typedef struct element{  //element listy
    struct element *next;
    wyrazenie val;
 }el_listy;

typedef struct {  //lista prosta
    struct element *head,*tail;
 }lista;

void dodaj_do_listy (lista *lst, wyrazenie val) //zamiast wskaźnika do struktury jako drugi parametr przekazuję strukturę
  {
   el_listy *nowy;
   nowy=(el_listy*)malloc(sizeof(el_listy));  
   nowy->val=val;                
   nowy->next=NULL;                
   if(lst->tail) lst->tail->next=nowy;
   else lst->head=nowy;
   lst->tail=nowy;
  }

int main()
  {
   wyrazenie wyr;
   lista L={NULL,NULL};
   ...
   dodaj_do_listy(&L,wyr);
   ...
0

Tak, masz rację, strukturę też zmieniłem tylko zapomniałem o tym napisać, program wczytuje i później wypisuje po kolei elementy listy, cel osiągnięty. Dzięki za pomoc:)

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