C, inversione SCL

di Anonimizzato14377 il
12 risposte
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

  • 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)
  • No, il compilatore non mi ha dato nessun warning in compialazione (utilizzo gcc).

    Quindi è quello il problema? Come risolvo?
  • 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...
  • 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?
  • 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 ...
  • 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;
    }
    	
    
  • Ora ci siamo ...
  • 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..
  • Semplicemente alla fine della funzione converti scrivi

    inverti(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;
    }
    
  • vbextreme ha scritto:


    scusa ma cosi era troppo semplice?
    Dai per scontato che l'array non sia vuoto ...
  • E che scl non sia null...
Devi accedere o registrarti per scrivere nel forum
12 risposte