[Risolto] Problema con le liste

Linguaggi di programmazione: php, perl, python, C, bash, ecc.

[Risolto] Problema con le liste

Messaggioda Taurus95 » mercoledì 9 maggio 2018, 17:25

Ciao a tutti, sta volta premetto che non so più dove sbattere la testa e quindi non saprei come risolvere.
Premetto anche che usiamo scanf e printf poiché vengono richiesti questi "formati" durante i nostri esami.

Dunque, arrivo al sodo: sto creando un programma con liste di dimensione variabile e il problema è il seguente ESERCIZIO (se nella sottoposizione trovate un codice che non c'entra nulla, non guardatelo)
Il problema che riscontro è una volta che eseguo, inserisco il primo elemento e va in Segmentation Fault (dunque presumo che l'errore sia nell'inserimento dei dati)
Qui ci sta il codice:
Codice: Seleziona tutto
//INSERISCI/RIMUOVI DA LISTA
#include <stdlib.h>
#include <stdio.h>

struct eldilis
{   int info;
   struct eldilis *next;
};
typedef struct eldilis elem;
typedef elem *list;

list new1=NULL;
list corr=NULL;
list aus=NULL;

void inste(list lis, int z)   //inserimento in testa
{   if(NULL==lis)
   {   new1->info=z;
      new1->next=NULL;
      lis=new1;
   }
   else
   {   new1->info=z;
      new1->next=lis;
      lis=new1;
   }
}

void insco(list lis, int y)   //inserimento in coda
{   new1->info=y;
   new1->next=NULL;
   if (lis==NULL)
      lis=new1;
   else
   {   list corr=lis;
      while (corr->next->next!=NULL)
         corr=corr->next;
      corr->next=new1;
   }
}

void canc(list lis, int w)   //eliminazione elemento=-w
{   if (lis->info==(w*(-1)))
   {   aus=lis;
      if(lis->next!=NULL)
         lis=lis->next;
      free(aus);
   }
   else
      corr=lis;
   while(corr->next!=NULL)
   {   if(corr->info==(w*(-1)))
      {   aus=corr;
         if(corr->next!=NULL)
            corr=corr->next;
         free(aus);
      }
      else
         corr=corr->next;
   }
}

void printlis(list lis) //stampa la lista
{   aus=lis;
   while (aus->next!=NULL)
   {   if(aus->info==0)
         aus=aus->next;
      printf("%d\n", aus->info);
      aus=aus->next;
   }
}
void insel(list lis, int x)
{   if(x>0)
   {   if (x%2==0)
         inste(lis, x);
      else
         insco(lis, x);
   }
   else
         canc(lis, x);
}
int main()
{   list head=malloc(sizeof(elem));
   head=NULL;
   int el;
   scanf("%d", &el);
   while(el!=0)
   {   insel(head, el);
      scanf("%d", &el);
   }
   printlis(head);
   return 0;
}


Ci saranno sicuramente altri errori, dunque se li trovate non vi fate problemi a "bacchettarmi".

ps: se avete suggerimenti da dove apprendere meglio come usare le liste ve ne sono grato!
Ultima modifica di Taurus95 il sabato 16 giugno 2018, 11:22, modificato 1 volta in totale.
Taurus95
Prode Principiante
 
Messaggi: 65
Iscrizione: giugno 2017
Località: Pisa
Desktop: ubuntu-xorg
Distribuzione: Ubuntu 16.04.1 LTS
Sesso: Maschile

Re: Problema con le liste

Messaggioda Taurus95 » mercoledì 9 maggio 2018, 17:44

Implemento nuovo codice con risolvimento credo parziale della cosa..sembra fatto di proposito, ma una volta chiesto aiuto qua mi viene l'ispirazione! :cry: (Mi sento quasi scemo)

Codice: Seleziona tutto
//INSERISCI/RIMUOVI DA LISTA
#include <stdlib.h>
#include <stdio.h>

struct eldilis
{   int info;
   struct eldilis *next;
};
typedef struct eldilis elem;
typedef elem *list;

void inste(list lis, int z)   //inserimento in testa
{   list new1=malloc(sizeof(elem));
   if(lis==NULL)
   {   new1->info=z;
      new1->next=NULL;
      lis=new1;
   }
   else
   {   new1->info=z;
      new1->next=lis;
      lis=new1;
   }
}

void insco(list lis, int y)   //inserimento in coda
{   list new1=malloc(sizeof(elem));
   list corr=NULL;
   new1->info=y;
   new1->next=NULL;
   if (lis==NULL)
      lis=new1;
   else
   {   list corr=lis;
      while (corr->next->next!=NULL)
         corr=corr->next;
      corr->next=new1;
   }
}

void canc(list lis, int w)   //eliminazione elemento=-w
{   list corr=NULL;
   list aus=NULL;
   if (lis->info==(w*(-1)))
   {   aus=lis;
      if(lis->next!=NULL)
         lis=lis->next;
      free(aus);
   }
   else
      corr=lis;
   while(corr->next!=NULL)
   {   if(corr->info==(w*(-1)))
      {   aus=corr;
         if(corr->next!=NULL)
            corr=corr->next;
         free(aus);
      }
      else
         corr=corr->next;
   }
}

void printlis(list lis) //stampa la lista
{   list aus=NULL;
   aus=lis;
   while (aus->next!=NULL)
   {   if(aus->info==0)
         aus=aus->next;
      printf("%d\n", aus->info);
      aus=aus->next;
   }
}
void insel(list lis, int x)
{   if(x>0)
   {   if (x%2==0)
         inste(lis, x);
      else
         insco(lis, x);
   }
   else
         canc(lis, x);
}
int main()
{   list head=malloc(sizeof(elem));
   head=NULL;
   int el;
   scanf("%d", &el);
   while(el!=0)
   {   insel(head, el);
      scanf("%d", &el);
   }
   printlis(head);
   return 0;
}


Adesso il seg. fault lo da quando inserisco l'elemento negativo (e quindi deve rimuovere dalla lista esistente tutti i valori uguali al valore assoluto dell'elemento inserito)
Taurus95
Prode Principiante
 
Messaggi: 65
Iscrizione: giugno 2017
Località: Pisa
Desktop: ubuntu-xorg
Distribuzione: Ubuntu 16.04.1 LTS
Sesso: Maschile

Re: Problema con le liste

Messaggioda jepessen » mercoledì 9 maggio 2018, 18:13

Prima di risolvere ti consiglio di provare con il debugger a vedere se riesci a trovare il problema. Vedere passo passo cosa succede e' di grande aiuto in generale.
Compiz l'ha creato Chuck Norris quando ha colpito un computer con un calcio rotante.
http://www.renderosity.com/mod/gallery/ ... e=Jepessen
http://jepessen.wordpress.com/
Avatar utente
jepessen
Imperturbabile Insigne
Imperturbabile Insigne
 
Messaggi: 3550
Iscrizione: dicembre 2005
Località: Alcamo - Angera
Desktop: Unity
Distribuzione: Ubuntu

Re: Problema con le liste

Messaggioda Taurus95 » mercoledì 9 maggio 2018, 19:42

jepessen Immagine ha scritto:Prima di risolvere ti consiglio di provare con il debugger a vedere se riesci a trovare il problema. Vedere passo passo cosa succede e' di grande aiuto in generale.


Non ero pratico del debugger, mi sono un po' sforzato a capire dopo il "run" che fare e ho provato ad inserire i dati del test case!
Il risultato al primo elemento negativo inserito

Codice: Seleziona tutto
Program received signal SIGSEGV, Segmentation fault.
0x00005555555548e3 in canc (lis=0x0, w=-4) at rimozione.c:48
48      if (lis->info==(w*(-1)))


Non riesco però a capire quale sia il vero problema.

ps: grazie del suggerimento dell'uso del debugger! Mi è di grande aiuto per il futuro!

AGGIORNAMENTO:
Per il precedente errore l'ho superato mettendo in quella riga semplicemente "if (lis!=NULL && lis->info==-w)" (sinceramente non lo so perché, se passo la lista lo dovrebbe fare anche se è vuota, no?)

Ad ogni modo adesso ho risolto i vari seg. fault, ma non stampa nulla quando deve stampare
Codice: Seleziona tutto
//INSERISCI/RIMUOVI DA LISTA
#include <stdlib.h>
#include <stdio.h>

struct eldilis
{   int info;
   struct eldilis *next;
};
typedef struct eldilis elem;
typedef elem *list;

void inste(list lis, int z)   //inserimento in testa
{   list new1=malloc(sizeof(elem));
   if(lis==NULL)
   {   new1->info=z;
      new1->next=NULL;
      lis=new1;
   }
   else
   {   new1->info=z;
      new1->next=lis;
      lis=new1;
   }
}

void insco(list lis, int y)   //inserimento in coda
{   list new1=malloc(sizeof(elem));
   list corr=NULL;
   new1->info=y;
   new1->next=NULL;
   if (lis==NULL)
      lis=new1;
   else
   {   list corr=lis;
      while (corr->next->next!=NULL)
         corr=corr->next;
      corr->next=new1;
   }
}

void canc(list lis, int w)   //eliminazione elemento=-w
{   list corr=malloc(sizeof(elem));
   list aus=malloc(sizeof(elem));
   list prec=malloc(sizeof(elem));
   corr=NULL;
   aus=NULL;
   prec=NULL;
   if (lis!=NULL && lis->info==-w)
   {   aus=lis;
      if(lis->next!=NULL)
      {   lis=lis->next;
         free(aus);
      }
      else
         free(lis);
   }
   else if (lis!=NULL)
   {   corr=lis->next;
      prec=lis;
      while(corr->next!=NULL)
      {   if(corr->info==(w*(-1)))
         {   aus=corr;
            if(corr->next!=NULL)
            {   corr=corr->next;
               free(aus);
               prec->next=corr;
            }
            else
            {   free(corr);
               prec->next=NULL;
            }   
         }
         else
         {   prec=prec->next;
            corr=corr->next;
         }
      }
   }
}

void printlis(list lis) //stampa la lista
{   list corr=NULL;
   corr=lis;
   while (lis!=NULL && corr->next!=NULL)
   {   printf("%d\n", corr->info);
      corr=corr->next;
   }
}
void insel(list lis, int x)
{   if(x>0)
   {   if (x%2==0)
         inste(lis, x);
      else
         insco(lis, x);
   }
   else
         canc(lis, x);
}
int main()
{   list head=malloc(sizeof(elem));
   head=NULL;
   int el;
   scanf("%d", &el);
   while(el!=0)
   {   insel(head, el);
      scanf("%d", &el);
   }
   printlis(head);
   return 0;
}


E qui non so dove mettere mani
Taurus95
Prode Principiante
 
Messaggi: 65
Iscrizione: giugno 2017
Località: Pisa
Desktop: ubuntu-xorg
Distribuzione: Ubuntu 16.04.1 LTS
Sesso: Maschile

Re: Problema con le liste

Messaggioda jepessen » giovedì 10 maggio 2018, 10:29

Io nel main vedo che setti head a NULL, poi fai delle cose senza mai cambiare il valore di head, e quando arrivi alla riga printlis(head); del main gli passi comunque un head pari a NULL. Quindi il controllo su lis != 0 dentro printlis fallisce e non stampa niente.
Compiz l'ha creato Chuck Norris quando ha colpito un computer con un calcio rotante.
http://www.renderosity.com/mod/gallery/ ... e=Jepessen
http://jepessen.wordpress.com/
Avatar utente
jepessen
Imperturbabile Insigne
Imperturbabile Insigne
 
Messaggi: 3550
Iscrizione: dicembre 2005
Località: Alcamo - Angera
Desktop: Unity
Distribuzione: Ubuntu

Re: Problema con le liste

Messaggioda Taurus95 » giovedì 10 maggio 2018, 10:54

Scusa, essendo list di tipo elem *, non è un passaggio tramite puntatori? Almeno un elemento verrà inserito in quanto nelle funzioni lis punta a head
Taurus95
Prode Principiante
 
Messaggi: 65
Iscrizione: giugno 2017
Località: Pisa
Desktop: ubuntu-xorg
Distribuzione: Ubuntu 16.04.1 LTS
Sesso: Maschile

Re: Problema con le liste

Messaggioda jepessen » giovedì 10 maggio 2018, 11:35

head e' pari a NULL, e tu passi il puntatore per copia, quindi il suo valore non cambia (ed il suo valore e' l'indirizzo di memoria). Faccio un esempio:
Codice: Seleziona tutto
void doSomething(int* localP) {
  localP = malloc(sizeof(int));
  *localP = 3;
}


int *p = NULL;
doSomething(p);
printf("%u", p); // Stampa 0 perche' p viene passato per copia ed il suo valore rimane inalterato


Quando stampi il valore di p, ottieni 0.
Vediamo cosa succede:
  • Crei un puntatore, e gli assegni un valore, in questo caso NULL;
  • Passi il puntatore all'interno di una funzione per copia. All'interno della funzione localP sara' una COPIA del puntatore che gli passi. La copia e' riferita al valore del puntatore, non a quello che punta. Quindi puoi assegnare a localP un nuovo valore dentro la funzione, ma alla variable p frega niente.
  • cambi il valore del puntatore dentro la funzione. Questo cambia solamente il valore del puntatore locale, non di quello globale, che rimane NULL;
  • Esci dalla funzione: il riferimento a localP viene perso (e hai un memory leak) e p rimane uguale a null.

Tu non vuoi modificare il valore cui punta il puntatore. Tu vuoi modificare il puntatore stesso. Per questo devi passarlo come riferimento. Il codice diventa il seguente:
Codice: Seleziona tutto
void doSomething(int** localP) {
  *localP = malloc(sizeof(int));
  **localP = 3;
}


int *p = NULL;
doSomething(&p);
printf("%u", p); // Indirizzo del puntatore
printf("%d", *p); // Valore della variabile referenziata dal puntatore


Vedi la differenza? Alla funzione adesso si passa il riferimento al puntatore, quindi adesso e' possibile modificare il suo valore. E la stessa cosa del passaggio per copia di un parametro di tipo int, solo che succede per il puntatore. Hai un livello di dereferenza in piu'.
In sostanza passi il puntatore per copia, quindi se modifichi il valore del puntatore (e non della locazione cui punta), l'argomento della funzione non viene comunque modificato. Devi passare il puntatore stesso per riferimento, utilizzando ad esempio un puntatore a puntatore, o passando proprio l'indirizzo del puntatore tramite l'operatore &.
Ti posto un esempio completo che mostra le differenze. Al solito se utilizzi un debugger puoi vedere il valore delle varie variabili ad ogni step, cosa che ti consiglio di fare (prova il debugger grafico di qt creator che funziona bene).

Codice: Seleziona tutto
#include <stdio.h>

void doSomething(int* localP) {
  localP = malloc(sizeof(int));
  *localP = 3;
}

void doSomethingWithReference(int** localP) {
  *localP = malloc(sizeof(int));
  **localP = 3;
}

int main()
  int* p = NULL:
  doSomething(p);
  printf("indirizzo di P dopo passaggio del puntatore per copia: %u\n", p);
  doSomethingWithReference(&p);
  printf("Indirizzo di P dopo passaggio del puntatore per riferimento: %u\d", p);
  printf("Valore referenziato dal puntatore: %d\n", *p);
  return 0;
}
Compiz l'ha creato Chuck Norris quando ha colpito un computer con un calcio rotante.
http://www.renderosity.com/mod/gallery/ ... e=Jepessen
http://jepessen.wordpress.com/
Avatar utente
jepessen
Imperturbabile Insigne
Imperturbabile Insigne
 
Messaggi: 3550
Iscrizione: dicembre 2005
Località: Alcamo - Angera
Desktop: Unity
Distribuzione: Ubuntu

Re: Problema con le liste

Messaggioda Taurus95 » giovedì 10 maggio 2018, 12:13

Okay, dopo ciò prendo te come prof ahahahah
Ti faccio sapere il prima possibile! Intanto ti ringrazio però per la pazienza e la "fatica" impiegata soprattutto per l'ultimo post :D
Taurus95
Prode Principiante
 
Messaggi: 65
Iscrizione: giugno 2017
Località: Pisa
Desktop: ubuntu-xorg
Distribuzione: Ubuntu 16.04.1 LTS
Sesso: Maschile

Re: Problema con le liste

Messaggioda jepessen » giovedì 10 maggio 2018, 12:33

:maestro:
Compiz l'ha creato Chuck Norris quando ha colpito un computer con un calcio rotante.
http://www.renderosity.com/mod/gallery/ ... e=Jepessen
http://jepessen.wordpress.com/
Avatar utente
jepessen
Imperturbabile Insigne
Imperturbabile Insigne
 
Messaggi: 3550
Iscrizione: dicembre 2005
Località: Alcamo - Angera
Desktop: Unity
Distribuzione: Ubuntu

Re: Problema con le liste

Messaggioda Taurus95 » martedì 15 maggio 2018, 18:20

Modificando i puntatori mi da problemi di tipo se non sbaglio, dicendomi che uso tipo **p da una parte e ***p da un'altra, dandomi poi come errori anche l'uso del '->'..ancora mi sa che non mi è chiaro il concetto di uso dei puntatori nelle liste
Taurus95
Prode Principiante
 
Messaggi: 65
Iscrizione: giugno 2017
Località: Pisa
Desktop: ubuntu-xorg
Distribuzione: Ubuntu 16.04.1 LTS
Sesso: Maschile

Re: Problema con le liste

Messaggioda jepessen » martedì 15 maggio 2018, 20:32

Evita come la peste i puntatori di puntatori di puntatori... Se lo fai c'è qualcosa di profondamente sbagliato...
Compiz l'ha creato Chuck Norris quando ha colpito un computer con un calcio rotante.
http://www.renderosity.com/mod/gallery/ ... e=Jepessen
http://jepessen.wordpress.com/
Avatar utente
jepessen
Imperturbabile Insigne
Imperturbabile Insigne
 
Messaggi: 3550
Iscrizione: dicembre 2005
Località: Alcamo - Angera
Desktop: Unity
Distribuzione: Ubuntu

Re: Problema con le liste

Messaggioda Taurus95 » martedì 15 maggio 2018, 23:03

Va bene!
Taurus95
Prode Principiante
 
Messaggi: 65
Iscrizione: giugno 2017
Località: Pisa
Desktop: ubuntu-xorg
Distribuzione: Ubuntu 16.04.1 LTS
Sesso: Maschile

Re: Problema con le liste

Messaggioda Taurus95 » giovedì 14 giugno 2018, 19:33

Eccomi di nuovo qui, stesso esercizio, ma mezzo risolto! Non riesco a capire cosa non vada..usando un test case mi dovrebbe dare come risposta 2 2 9 e invece mi risponde con 2 0. :cry:

Codice: Seleziona tutto
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

struct Elemento
{   int info;
   struct Elemento *next;
};
typedef struct Elemento elemento;
typedef elemento *eldilista;

void inserisci(eldilista *lista, int x)
{   *lista=(eldilista) malloc (sizeof(elemento));   
   eldilista aus=(eldilista) malloc (sizeof(elemento));
   if (lista==NULL)
   {   aus->info=x;
      aus->next=NULL;
      *lista=aus;
   }
   else
   {   if (x%2==0)
      {   aus->info=x;
         aus->next=*lista;
         *lista=aus;
      }
      else
      {   aus=*lista;
         while(aus->next!=NULL)
            aus=aus->next;
         eldilista elx = (eldilista) malloc (sizeof(elemento));
         elx->info=x;
         elx->next=NULL;
         aus->next=elx;
      }
   }
}

void rimabs(eldilista *lista, int x)
{   *lista = (eldilista) malloc (sizeof(elemento));   
   eldilista aus1, aus2, scorri;
   aus1 = (eldilista) malloc (sizeof(elemento));
   aus2 = (eldilista) malloc (sizeof(elemento));
   scorri=*lista;
   if(scorri->info==x)
   {   aus1=scorri->next;
      free(scorri);
      *lista=aus1;
   }
   else
   {   while (scorri->info != x && scorri->next != NULL)
      {   aus1=scorri;
         scorri=scorri->next;
         aus2=scorri;
      }
      if (scorri->info == x)
      {   free(scorri);
         aus1->next=aus2;
      }
   }
}

void printlis(eldilista lista)
{   while (lista != NULL)
   {   printf("%d\n", lista->info);
      lista=lista->next;
   }
}

void FreeList(eldilista lista)
{   eldilista tmp;
   while (lista != NULL)
   {   tmp = lista;
      lista = lista->next;
      free(tmp);
   }
   free(lista);
}

int main()
{   int i=1;
   eldilista head =(eldilista) malloc (sizeof(elemento));
   while (i!=0)
   {   scanf("%d", &i);
      if (i>0)
         inserisci(&head, i);
      if (i<0)
         rimabs(&head, (int)fabs(i));
   }
   printlis(head);
        FreeList(head);
   return 0;
}


ps: perche' le liste sono cosi' "rompiscatole"? :muro:

EDIT:
ho provato in un altro modo, ma mi sa che neanche questo va bene (core dumped al primo elemento)
Codice: Seleziona tutto
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

struct Item
{   int info;
   struct Item *next;
};
typedef struct Item item;
typedef item *itemlist;

itemlist insert (int x)
{   itemlist list=(itemlist)malloc(sizeof(item));
   itemlist aus=NULL, pointer=NULL;
   if(list==NULL)
   {   list->info=x;
      list->next=NULL;
   }
   else
   {   if(x%2==0)
      {   aus->info=x;
         aus->next=list;
         list=aus;
      }
      else
      {   pointer=list;
         while(pointer->next!=NULL)
            pointer=pointer->next;
         aus->info=x;
         aus->next=NULL;
         pointer->next=aus;
      }
   }
   return list;
}

itemlist remabs (itemlist list, int x)
{   itemlist prev=NULL, succ=NULL, pointer=NULL;
   pointer=list;
   int trovato=0;
   if (pointer==list && pointer->info==x)
   {   list=list->next;
      trovato=1;
   }
   while(!trovato && pointer->next!=NULL)
   {   if(pointer->info==x)
         trovato=1;
      else
      {   prev=pointer;
         pointer=pointer->next;   
         succ=pointer->next;
      }
   }
   if(trovato)
   {   free(pointer);
      prev->next=succ;
   }
   return list;
}
      
void printlist (itemlist list)
{   while (list != NULL)
   {   printf("%d\n", list->info);
      list=list->next;
   }
}

void freelist(itemlist list)
{   itemlist temp;
   while (list != NULL)
   {   temp = list;
      list = list->next;
      free(temp);
   }
   free(list);
}

int main()
{   int i=1;
   itemlist head=(itemlist) malloc (sizeof(item));
   while (i!=0)
   {   scanf("%d", &i);
      if (i>0)
         head=insert(i);
      if(i<0)
         head=remabs(head,(int)fabs(i));
   }
   printlist(head);
   freelist(head);
   return 0;
}

perche` sempre una che non va? :cry: :cry:
Taurus95
Prode Principiante
 
Messaggi: 65
Iscrizione: giugno 2017
Località: Pisa
Desktop: ubuntu-xorg
Distribuzione: Ubuntu 16.04.1 LTS
Sesso: Maschile

Re: Problema con le liste

Messaggioda Taurus95 » sabato 16 giugno 2018, 11:22

Dopo una serie di sbattimenti, suggerimenti, seg. fault e GDB vari, finalmente pongo come chiuso il post! Quasi non ci credo ahahaha

Grazie ancora a jepessen!
Taurus95
Prode Principiante
 
Messaggi: 65
Iscrizione: giugno 2017
Località: Pisa
Desktop: ubuntu-xorg
Distribuzione: Ubuntu 16.04.1 LTS
Sesso: Maschile

Re: [Risolto] Problema con le liste

Messaggioda jepessen » martedì 19 giugno 2018, 22:43

👌👌👌
Compiz l'ha creato Chuck Norris quando ha colpito un computer con un calcio rotante.
http://www.renderosity.com/mod/gallery/ ... e=Jepessen
http://jepessen.wordpress.com/
Avatar utente
jepessen
Imperturbabile Insigne
Imperturbabile Insigne
 
Messaggi: 3550
Iscrizione: dicembre 2005
Località: Alcamo - Angera
Desktop: Unity
Distribuzione: Ubuntu


Torna a Programmazione

Chi c’è in linea

Visualizzano questa sezione: 0 utenti registrati e 3 ospiti