C, inversione SCL

di il
12 risposte

C, inversione SCL

Il seguente codice "converte" un array di interi in una scl, nel senso che ogni elemento a[j] viene inserito nella lista nello stesso ordine in cui gli elementi compaiono nell'array.

La mossa più conveniente sarebbe di fare un inserimento in coda. Cosa che ho fatto, quindi ok.

Per esercitarmi ho deciso di fare lo stesso es con un inserimento in testa, e poi invertire la lista, in modo tale da avere gli elementi nello stesso ordine dell'array.

Ecco il codice, funzionante:
#include <stdio.h>
#include <stdlib.h>

struct ElemSCL{
    int info;
    struct ElemSCL* next;
};
typedef struct ElemSCL NodoSCL;
typedef NodoSCL* TipoSCL;


void inverti(TipoSCL *scl);

int main()
{	
	int i = 0, a[5] = {1, 2, 3, 4, 5}, n = 5;
	
	TipoSCL *scl, punt = NULL;
	
	while(i < n)
	{
		*scl = (NodoSCL*) malloc (sizeof(NodoSCL));
		(*scl) -> info = a[i];
		(*scl) -> next = punt;
		punt = *scl;
		i++;
	}
	TipoSCL aux = *scl;
	inverti(&aux);
	*scl = aux;
	printf("\n");
	while(*scl != NULL)
	{
		printf("-> %d", (*scl) -> info);
		(*scl) = (*scl) -> next;
	}
}

void inverti(TipoSCL *scl)
{
	TipoSCL prev = NULL, succ;
	while(*scl != NULL)
	{
		succ = *scl;
		*scl = (*scl) -> next;
		succ -> next = prev;
		prev = succ;
	}
	*scl = prev;
}
Il problema è: questo è un esercizio dato dal prof che, una volta compilato, viene avviato un correttore automatico che stampa, in percentuale, la riuscita dell'ersercizio stesso.

In realtà, l'esercizio consiste nell'implementare la funzione data. Quindi non ho nessun main da utilizzare come nel codice che ho postato qui sopra.

Ecco la traccia:

si realizzi la funzione C:
• void converti(TipoSCL* scl, int a[], int n)
che, presi in input un puntatore scl ad una SCL ed un array a di interi con la relativa dimensione n,
crea una nuova struttura collegata contenente gli elementi di a (mantenendone l’ordine) e la restituisce attraverso il parametro per riferimento scl.


ed ecco l'implementazione:
#include <stdio.h>
#include <stdlib.h>
#include "esercizio.h"

void inverti(TipoSCL *scl);

void converti(TipoSCL*scl, int a[], int n)
{
	TipoSCL punt = NULL;
	int i = 0;
	
	while(i < n)
	{
		*scl = (NodoSCL*) malloc (sizeof(NodoSCL));
		(*scl) -> info = a[i];
		(*scl) -> next = punt;
		punt = *scl;
		i++;
	}
	TipoSCL aux = *scl;
	inverti(&aux);
	*scl = aux;
	
}

void inverti(TipoSCL *scl)
{
	TipoSCL prev = NULL, succ;
	while(*scl != NULL)
	{
		succ = *scl;
		*scl = (*scl) -> next;
		succ -> next = prev;
		prev = succ;
	}
	*scl = prev;
}

che è praticamente uguale al primo codice che ho postato, solamente che l'array mi viene passato come parametro. Il correttore mi da Errore di segmentazione (core dump creato).

Se mi dite come fare, potrei postarvi l'intera cartella contenente anche il codice del correttore.

Oppure c'è un errore che non riesco a vedere?

Grazie

12 Risposte

  • Re: C, inversione SCL

    Il codice non è compilabile (almeno, se non ignori i warning o se il tuo compilatore è abbastanza serio da fornirteli ...).

    Nella linea

    *scl = (NodoSCL*) malloc (sizeof(NodoSCL));

    scl è un puntatore a puntatore e quindi *scl utilizza un puntatore non inizializzato ... ecco il seg fault (ripeto, lo avresti anche con il primo codice che apparentemente funziona)
  • Re: C, inversione SCL

    No, il compilatore non mi ha dato nessun warning in compialazione (utilizzo gcc).

    Quindi è quello il problema? Come risolvo?
  • Re: C, inversione SCL

    Risolvi scrivendo correttamente l'inserimento nella lista. L'avrai fatto mille altre volte ...

    Ti ho detto "cosa controllare", ora dovresti sbatterci un po' la testa se vuoi imparare ...

    P.S. Non ho ancora capito se frequenti un corso universitario o una scuola superiore ... e soprattutto da quanto la segui questa materia...
  • Re: C, inversione SCL

    Ok, ora ci provo.

    Un'ultima cosa: questa è la soluzione del prof con inserimento in coda
    #include <stdio.h>
    #include <stdlib.h>
    #include "esercizio.h"
    
    void converti(TipoSCL* scl, int a[], int n){
        //Nodo generatore
        *scl = (NodoSCL*) malloc(sizeof(NodoSCL));
        
        NodoSCL* aux = *scl;
        
        for(int i = 0; i < n; i++){
            aux -> next = (NodoSCL*) malloc(sizeof(NodoSCL));
            aux = aux -> next;
            aux -> info = a[i];
        }
        aux -> next = NULL;
        
        aux = *scl;
        *scl = aux -> next;
        free(aux);
    }
    
    Anche qui scl è un puntatore a puntatore e quindi *scl utilizza un puntatore non inizializzato?
  • Re: C, inversione SCL

    Qui si utilizza una funzione e il puntatore a puntatore è un argomento della funzione. Giustamente, perché se hai un puntatore da modificare lo devi passare per puntatore alla funzione. L'inizializzazione del puntatore da passare alla funzione avverrà nella funzione chiamante (tipicamente nel main, che non è mostrato in questo caso).

    Ma tu hai scritto codice nel main come se fosse in una funzione (parlo sempre del primo codice, quello che definisci funzionante).

    Se vuoi controllare la funzione che hai scritto (non il codice del main), invia la cartella cont quel "correttore" di cui parli ...
  • Re: C, inversione SCL

    Ah sìsì è vero.

    Nel main andrebbe utilizzato TipoSCL scl essendo typedef NodoSCL* TipoSCL;

    Se fosse stato typedef NodoSCL TipoSCL; sarebbe stato corretto utilizzare TipoSCL *scl nel main, vero?

    Così va bene?
    #include <stdio.h>
    #include <stdlib.h>
    
    struct ElemSCL{
        int info;
        struct ElemSCL* next;
    };
    typedef struct ElemSCL NodoSCL;
    typedef NodoSCL* TipoSCL;
    
    void converti(TipoSCL*scl, int a[], int n);
    
    void inverti(TipoSCL *scl);
    
    int main()
    {
    	int array[5] = {1, 2, 3, 4, 5};
    	
    	TipoSCL lista;
    	
    	converti(&lista, array, 5);
    	
    	TipoSCL stampa = lista;
    	while(stampa != NULL)
    	{
    		printf("-> %d", stampa -> info);
    		stampa = stampa -> next;
    	}
    	
    	printf("\n");
    	
    	inverti(&lista);
    	
    	stampa = lista;
    
    	while(stampa != NULL)
    	{
    		printf("-> %d", stampa -> info);
    		stampa = stampa -> next;
    	}
    	
    	printf("\n");
    	
    }
    
    void converti(TipoSCL*scl, int a[], int n)
    {
    	int i = 0;
    	TipoSCL punt = NULL;
    	
    	while(i < 5)
    	{
    		*scl = (NodoSCL*) malloc (sizeof(NodoSCL));
    		(*scl) -> info = a[i];
    		(*scl) -> next = punt;
    		punt = *scl;
    		
    		i++;
    	}
    	
    	
    }
    
    void inverti(TipoSCL *scl)
    {
    	TipoSCL prec = NULL, suc;
    	
    	while(*scl != NULL)
    	{
    		suc = *scl;
    		*scl = (*scl) -> next;
    		suc -> next = prec;
    		prec = suc;
    	}
    	
    	*scl = prec;
    }
    	
    
  • Re: C, inversione SCL

    Ora ci siamo ...
  • Re: C, inversione SCL

    Ok

    Ora, però, vorrei richiamare inverti non più dal main ma da converti:
    void inverti(TipoSCL *scl);
    
    void converti(TipoSCL*scl, int a[], int n)
    {
    	int i = 0;
    	TipoSCL punt = NULL;
    	
    	while(i < 5)
    	{
    		*scl = (NodoSCL*) malloc (sizeof(NodoSCL));
    		(*scl) -> info = a[i];
    		(*scl) -> next = punt;
    		punt = *scl;
    		
    		i++;
    	}
    
    	TipoSCL aux = *scl;
    	inverti(&aux);
    	*scl = aux;
    }
    
    void inverti(TipoSCL *scl)
    {
    	TipoSCL prec = NULL, suc;
    	
    	while(*scl != NULL)
    	{
    		suc = *scl;
    		*scl = (*scl) -> next;
    		suc -> next = prec;
    		prec = suc;
    	}
    	
    	*scl = prec;
    	
    }
    Ma non va bene..
  • Re: C, inversione SCL

    Semplicemente alla fine della funzione converti scrivi

    inverti(scl);
  • Re: C, inversione SCL

    Scusa ma cosi era troppo semplice?
    
    void converti(TipoSCL* scl, int a[], int n)
    {
        NodoSCL* ele;
    
        *scl = ele = malloc (sizeof(NodoSCL));
        ele->info = a[0];
        ele->next = NULL;
    
        int i;
        for (i = 1; i < n; i++, ele = ele->next)
        {
            ele->next = malloc (sizeof(NodoSCL));
            ele->next->info = a[i];
        }
        ele->next = NULL;
    }
    
  • Re: C, inversione SCL

    vbextreme ha scritto:


    scusa ma cosi era troppo semplice?
    Dai per scontato che l'array non sia vuoto ...
  • Re: C, inversione SCL

    E che scl non sia null...
Devi accedere o registrarti per scrivere nel forum
12 risposte