C - Libreria Grafo

di il
49 risposte

49 Risposte - Pagina 4

  • Re: C - Libreria Grafo

    Sei sicura che compili senza errori ne warning?
  • Re: C - Libreria Grafo

    SVNiko ha scritto:


    Sei sicura che compili senza errori ne warning?
    sisi compila tutto, anche se ho sbagliato ad incollare grafoparser.c che invece è questo
    #include <stdio.h>
    #include <stdlib.h>
    #include <limits.h>
    #include <ctype.h>
    #include "grafolista.h"
    #include "grafomatrice.h"
    #include "grafoparser.h"
    #include <string.h>
    
    // Elaborazione simboli NON TERMINALI
    
    int parseGrafo (FILE *file, GrafoAdj *G, GrafoMatr *M, int tipo)
    { //Traduce il grafo [ritorna il puntatore alla radice]
        int x,n=0,i=0;
        char val;
    
        n=traduciNumeroNodi(file); //leggi il numero di nodi che dovrà contenere il grafo
    
        if(tipo==2)*M=creaGrafoMatr(n);
        else *G=creaGrafoLista(n);
    
        while(i<n)
        {
            x=confronto(file,ID); //verifica che dopo il numero di nodi ci sia un nodo stesso
            if(x)
            {
                val=fgetc(file); //estrai il primo nodo
                ungetc(val,file);
                if(tipo==1)
                {
                    *G=aggiungiVerticeLista(*G,val,0);
                    sposta(file,ID);
                    verticiAdj(*G,0,val,file);
                }
                else
                {
                    *M=aggiungiVerticeMatr(*M,val,0,n);
                    sposta(file,ID);
                    verticiAdj(NULL,*M,val,file); //traduce i vertici adiacenti al nodo
                }
            }
            else printf(":: ERRORE VERTICE! ::\n\n");
    
            i++;
        }
        // else ERRORE NESSUN NODO PRESENTE!!!
        return n;
    }
    
    int traduciNumeroNodi(FILE *file) // DOPO LA FUNZIONE LO STREAM SI TROVA DOPO LA PARENTESI CHIUSA
    {//Esamina i simboli che rappresentano il numero di nodi [se ' (numeroIntero) ' ritorna il numero, altrimenti errore]
        int n=0;
        if(confronto(file,PARSX)) //se il simbolo corrente è una parentesi aperta è verificato il primo simbolo
        {
            sposta(file,PARSX);//ci si sposta al simbolo successivo la parentesi
            if (confronto(file,NUM)) // se il simbolo corrente è del tipo intero è verificato il secondo simbolo
                {
                    n=traduciIntero(file);
                    //sposta(file,NODO); //ci si sposta al simbolo successivo al nodo NON NECESSARIO
                    if(confronto(file,PARDX)) //se il simbolo corrente è una parentesi chiusa è verificato anche il terzo simbolo
                        {
                            sposta(file,PARDX); //si sposta al simbolo successivo all'interno del file
                            return n;}
                    }
        }
        return 0; //ritorna errore
    }
    
    int traduciIntero (FILE *file) // DOPO LA FUNZIONE LO STREAM SI TROVA DOPO L'INTERO
    {//Traduci il simbolo non terminale che rappresenta un intero [ritorna il vertice intero del nodo]
    	int c=0,num=0,l=0;
    	while ((c=fgetc(file)) != EOF && isdigit(c)) {
    		  if (num <= ((INT_MAX - (c-'0'))/10)){
    		      num = num*10 + (c-'0');
    		      l++;
       		  }
    	     // else syntax_error("Integer ID <= 2147483647",file); // Number too big: ERROR
    	}
    	//if (l==0) syntax_error("Integer ID",file); // The ID is not a number
    	if(c != EOF)       // If EndOfFile not yet reached
    		ungetc(c,file);      // push the last character back to the file
    
    	return num;
    }
    
    float traduciPeso (FILE *file)
    {
        float peso; char segno; int pintera, pdecimale; char stringa[10];
    
        segno=fgetc(file);
        pintera=traduciIntero(file);
        if (confronto(file,PUNTO)) //se dopo l'intero c'è un un punto allora è un float
        {
            sposta(file,PUNTO); //sposta allo stream successivo al punto
            pdecimale=traduciIntero(file);
    
        }
        else
        {
            printf("Errore Sintassi Peso! Il numero non è floating point!!\n");
            return 0;
        }
    
    
        sprintf(stringa, "%c", segno);
        sprintf(stringa, "%s%d", stringa,pintera);
        sprintf(stringa, "%s%c",stringa, '.');
        sprintf(stringa, "%s%d", stringa,pdecimale);
    
        peso=atof(stringa);
    
        sposta(file,PARDX);
    
        return peso;
    }
    
    void verticiAdj (GrafoAdj G, GrafoMatr M, char nodo, FILE *file)
    {//Traduci vertici adiacenti
        int res;
        char val;
        float peso;
        res=confronto(file,PUNT);  // Cerca freccia che indica a quali vertici punta il nodo in questione
        while(res!=0)
        {// Se IL SIMBOLO PUNTATORE è stato trovata verificare che segua un peso
            peso=0;
            if (confronto(file,PARSX))
            {sposta(file,PARSX);
            if(confronto(file,PESO))
                peso=traduciPeso(file);
            }
    
            val=fgetc(file);
    
            if(G!=NULL) G=aggiungiArcoLista(G,nodo,val,peso);
            else M=aggiungiArcoMatr(M,nodo,val,peso);
    
            if (confronto(file,VIRG))
                sposta(file,VIRG);
            else
                res=0;
            }
         //non ha altri vertici adiacenti
    
        sposta(file,PUNTOV);
        printf("\n");
    
    }
    
    
    
    
    // Elaborazione simboli TERMINALI
    
    int confronto(FILE *file, type x)
    { //Verifica se il tipo x corrisponde al simbolo nel file [ritorna 1  se vero, 0 altrimenti]
    	char c;
    	type rp;                       // Read symbol type
    	int res=0;
    
    	while(((c = fgetc(file)) == '\t') || (c== '\n') || (c== ' '))
    			;
        switch(c) {               // Determine the read symbol type
            case '(': rp = PARSX; break;
            case ')': rp = PARDX; break;
            case '-':
                rp=MENO;
                if(confronto(file,PUNT)) rp=PUNT;
                else rp=PESO;
                break;
            case '>': rp=PUNT; break;
            case '+': rp=PESO; break;
            case ';': rp = PUNTOV; break;
            case ',': rp = VIRG; break;
            case '.': rp= PUNTO; break;
            default : rp = NUM; break;
        }
    
        if(rp==NUM) //se alla fine dello switch rp è NUM è un intero altrimenti è un ID
           {
               if(!isdigit(c))
                    rp=ID;
           }
    
        ungetc(c,file); // Push the read character back to the file
    
        if(rp==PUNT) //Se il tipo è un puntatore effettuo uno spostamento in avanti in quanto il simbolo corrente potrebbe essere il meno perchè il simbolo del punt è fatto da '-' e '>'
            sposta(file,PUNT);
    
        if (rp==x)        // The expexted type et and the read symbol type rp match
    			res = 1;
    
      return res;
    }
    
    void sposta (FILE *file, type x)
    {//si sposta nel file al simbolo successivo a quello del tipo x
    	int dim = 0;
    
        switch(x) {               // Assign the read symbol type
       	   case PARSX:; case PARDX:; case NUM:; case PUNTO:; case MENO:; case PIU:; case PUNT:; case PUNTOV:; case VIRG:; case ID:; case PESO:dim=1; break;
        } //qualunque sia il simbolo ricevuto dim=1, ci si sposta di un passo
    
    	fseek(file,dim,SEEK_CUR);   // Si muove di dim passi a partire da quello corrente all'interno del file
    }
    
  • Re: C - Libreria Grafo

    Il problema si verifica nella funzione convertToMatrice

    Allochi il vettore v, le matrici m e p, poi dopo aver assegnato i riferimenti di questi con la generaGrafoMatr liberi la memoria con le free, perché? Così perdi i puntatori proprio a quelle aree di memoria che ti servono. Togli quelle tre free e vedrai che funzionerà.

    P.s. La free di un vettore di puntatori non si fa così, perché, non liberi tutta la memoria che hai allocato. La regola è ad ogni malloc corrisponde una free
  • Re: C - Libreria Grafo

    SVNiko ha scritto:


    Il problema si verifica nella funzione convertToMatrice

    Allochi il vettore v, le matrici m e p, poi dopo aver assegnato i riferimenti di questi con la generaGrafoMatr liberi la memoria con le free, perché? Così perdi i puntatori proprio a quelle aree di memoria che ti servono. Togli quelle tre free e vedrai che funzionerà.

    P.s. La free di un vettore di puntatori non si fa così, perché, non liberi tutta la memoria che hai allocato. La regola è ad ogni malloc corrisponde una free
    Giusto! E come mai in convertToLista non mi crea problema?
    Quindi in questo caso quale sarebbe il modo giusto di liberare la memoria, ammesso che occorra in questo caso. Mi ero creata il problema in quanto utilizzo delle variabili temporanee, che mi servono solo per modificare la rappresentazione, o sbaglio il ragionamento?
  • Re: C - Libreria Grafo

    Nella convertToLista non ti servono più quei puntatori perchè non li assegni a nessuno, quindi dopo aver utilizzato i dati che ti interessano, puoi certamente liberare la memoria, anzi devi.

    Una matrice la allochi scrivendo:
    
    int **m=(int**)malloc((n)*sizeof(int*));
    for(i=0; i<n; i++)
        m[i]=(int*)malloc((n)*sizeof(int));
    
    e la liberi scrivendo:
    
    for(i=0; i<n; i++)
       free(m[i]);
    free(m);
    
    Ad ogni malloc deve corrispondere una free utilizzandole in ordine inverso rispetto all'allocazione.
Devi accedere o registrarti per scrivere nel forum
49 risposte