Visualizzazione dei risultati da 1 a 3 su 3
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2011
    Messaggi
    20

    [C] Possibilità di "simulazione" di passaggio di variabili per riferimento

    Salve a tutti

    Sto lavorando sul seguente programma (che è solo un esempio di un progetto universitario più grosso che devo fare), che si occupa di creare un grafo con chiave intera, inserire al suo interno dei valori random, e stamparlo:

    codice:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #define TRUE 1
    #define FALSE 0
    
    /***************************/
    
    typedef struct Tedge
    {
         int key;
         struct Tedge *next;
    }Tedge;
    
    typedef Tedge* Pedge;
    
    typedef struct Tgraph
    {
         int n_adj;
         Tedge **adj;
    }Tgraph;
    
    typedef Tgraph* Pgraph;
    
    typedef int BOOL;
    
    /***************************/
    
    void make_empty_graph (Pgraph*, int);
    
    void print_graph(Pgraph);
    
    BOOL is_empty(Pgraph);
    
    void fill_graph(Pgraph*);
    
    /***************************/
    
    int main()
    {
        srand(time(NULL));
        Pgraph G=NULL;
        make_empty_graph(&G, 5);
        fill_graph(&G);
        print_graph(G);
        return 0;
    }
    
    /***************************/
    
    void make_empty_graph (Pgraph* G, int NV)
    {
         int i;
         (*G)=(Pgraph) malloc (sizeof(Tgraph));
         (*G)->adj=(Pedge*) malloc (NV*sizeof (Pedge));
         for (i=0; i<NV; ++i)
         {
              (*G)->adj[i]->key=NULL;
         }
    }
    
    
    void fill_graph(Pgraph* G)
    {
         int i;
         for (i=0; i<(*G)->n_adj; ++i)
         {
              (*G)->adj[i]->key=rand()%100;
         }
    }
    
    
    BOOL is_empty(Pgraph G)
    {
         return (G==NULL);
    }
    
    
    void print_graph(Pgraph G)
    {
         Pedge e;
         int i, ne=0;
         if(!is_empty(G))
         {
                      printf("Il grafo ha %d vertici\n\n", G->n_adj);
                      for(i=0; i<G->n_adj; ++i)
                      {
                            printf("Nodi adiacenti al nodo %d->", i);
                            e=G->adj[i];
                            while(e!=NULL)
                            {
                                          printf(" %d", e->key);
                                          ne+=1;
                                          e=e->next;
                            }
                            printf ("\n");
                      }
                      printf("\nIl grafo ha %d archi.\n", ne);
         }
         else
         {
             printf("Il grafo e' vuoto\n");
         }
    }
    Durante la compilazione (uso Code:Blocks su Xubuntu, gcc come compilatore), vado incontro ad un errore di "segmentation fault" che ho individuato (mettendo dei printf qui e la per vedere dove effettivamente il programma s'interrompesse) alla settima riga della funzione "make_empty_graph", per intenderci, qui

    codice:
    (*G)->adj[i]->key=NULL;
    Ora, io abituato ad usare il C++, usavo passare le variabili per riferimento dichiarando la funzione "make_empty_graph" in questo modo

    codice:
    void make_empty_graph (Pgraph&, int);
    e richiamandola dal main così

    codice:
    make_empty_graph (G, nv);
    e tutto funzionava alla perfezione. Per questo progetto, mi è imposto usare il C, e, pur avendo seguito più guide online, tipo questa [http://goo.gl/3Eu6F], e quindi, essendo riuscito a compilare, il programma non mi va in nessun modo.
    So bene che potrei risolvere semplicemente riscrivendo le funzioni in modo che mi ritornino ogni volta un grafo, ma ho già scritto un bel po' di roba, non vorrei perdere troppo tempo (visto pure che ne ho poco per la consegna), ed inoltre, in questo modo, si risparmia un bel po' di codice.

    Qualcuno, quindi, saprebbe dirmi come posso ottenere lo stesso risultato che ottengo in C++ con il C, lasciando quindi, tutte le mie funzioni void?

    Grazie in anticipo.

  2. #2
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    1,326

    Re: [C] Possibilità di "simulazione" di passaggio di variabili per riferimento

    Originariamente inviato da be_ar
    So bene che potrei risolvere semplicemente riscrivendo le funzioni in modo che mi ritornino ogni volta un grafo, ma ho già scritto un bel po' di roba, non vorrei perdere troppo tempo (visto pure che ne ho poco per la consegna), ed inoltre, in questo modo, si risparmia un bel po' di codice.

    Qualcuno, quindi, saprebbe dirmi come posso ottenere lo stesso risultato che ottengo in C++ con il C, lasciando quindi, tutte le mie funzioni void?
    Il problema non è del passaggio del grafo alla funzione. G è un puntatore in main() e passandolo per riferimento fai già in modo che la funzione in questione possa modificarne il valore con la malloc(). Il problema è un altro (sempre in make_empty_graph()):

    codice:
         (*G)->adj=(Pedge*) malloc (NV*sizeof (Pedge));
         for (i=0; i<NV; ++i)
         {
           (*G)->adj[i]->key=NULL;
         }
    per il puntatore adj (di tipo Pedge *) allochi spazio per NV puntatori Pedge, correttamente; dopo però vai ad accedere ai campi key dei singoli puntatori allocati senza aver però allocato spazio anche per questi (e quindi per i campi key). Devi fare una doppia allocazione: una per il doppio puntatore e NV per gli NV puntatori singoli. Tra l'altro, NULL è generalmente definito come ((void *) 0), quindi è un puntatore, pertanto non assegnarlo a key che è un intero (assegna la costante intera 0).


    codice:
         (*G)->adj=(Pedge*) malloc (NV*sizeof (Pedge));
         for (i=0; i<NV; ++i)
         {
           (*G)->adj[i] = (Pedge) malloc(sizeof(Tedge));
           (*G)->adj[i]->key=0;
         }
    non sarebbe male anche scrivere dei controlli sui valori di ritorno delle varie malloc().
    every day above ground is a good one

  3. #3
    Utente di HTML.it
    Registrato dal
    Jun 2011
    Messaggi
    20
    Gentilissimo, davvero. Ci sbattevo la testa da tantissimo tempo (è un problema che mi si pose anche in passato, ma non riuscii a risolverlo in nessun modo).
    Grazie infinite!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.