RESTITUZIONE DI PUNTATORE A STRUCT

di il
35 risposte

RESTITUZIONE DI PUNTATORE A STRUCT

Salve a tutti, mentre testavo un programma per calcolare l'intersezione tra due insiemi ho riscontrato il seguente problema:
nella funzione per calcolare l'intersezione creo ins_int, dove inserirò gli elementi in comune tra i due insiemi; se provo a inserire e stampare elementi dell'insieme dentro la funzione intersezione ci riesco, ma dal momento in cui restituisco alla main l'insieme, e provo a stamparlo, a tempo d'esecuzione mi dà un errore di segmentazione, come se non avessi mai inizializzato l'insieme. Penso quindi che il problema sia su come restituisco l'insieme, anche se non ne sono sicuro . Sapete aiutarmi?
Grazie mille in anticipo.
ps: ovviamente negli insiemi ins1 e ins2 sono stati inseriti e validati gli elementi in un altro punto della main.
La funzione appartiene a una libreria quindi ho scritto il codice su diversi fil, per questo vi metto solo le parti interessate.
STRUTTURA PER RAPPRESENTARE L'INSIEME:
typedef struct insieme
{
	double *arr;     /*array che andrà a contenere gli elementi dell'insieme*/
	int dim;    	 /*variabile per il numero di elementi dell'insieme*/
	int ind;    	 /*variabile indice per muoversi all'interno dell'array*/
} insieme_t;
FUNZIONE INTERSEZIONE:
insieme_t * intersezione ( insieme_t ins1,       /*variabile per rappresentare il primo insieme*/
				           insieme_t ins2)      /*variabile per rappresentare il secondo insieme*/
{
	insieme_t *ins_int;     /*variabile per estituire alla main l'insieme intersezione*/
	
	if(ins1 . ind == 0)
		ins_int =(insieme_t*) calloc (1, sizeof(insieme_t)); 	 
		

	if( (ins1 . ind) < (ins1 . dim) )
	{
		for (ins2 . ind = 0; (ins2 . ind) < (ins2 . dim); ins2 . ind ++)
			if((ins1 . arr[ins1 . ind]) == (ins2 . arr[ins2 . ind]))
			{
				if((ins_int -> dim) == 0)
				{
					ins_int -> dim = 1;
					ins_int -> ind = 0;
					ins_int -> arr= (double *) calloc( 1, sizeof(double));
					ins_int -> arr[ins_int -> ind] = ins1 . arr[ins1 . ind];
				} 
				else
				{
                			ins_int -> dim ++;
                			ins_int -> ind ++;
                			ins_int -> arr = (double *) realloc( ins_int -> arr, ins_int -> dim * sizeof(double));
                			ins_int -> arr[ins_int -> ind] = ins1 . arr[ins1 . ind];
                		}	
			}
		ins1 . ind ++;
		ins_int = intersezione (ins1, ins2);
	}
	
	
	ins1 . ind = 0;
	ins2 . ind = 0;
	return(ins_int);
} 
PEZZO DELLA FUNZIONE CHIAMANTE(MAIN):
insieme_t *ins_int;      /*dichiarazione dell'insieme intersezione*/
	ins_int = intersezione(ins1<, ins2);      /*chiamata alla funz. intersezione*/
	printf("L'insieme intersezione ha il seguente numero di elementi:\n"); /*stampa a schermo del numero di elementi*/
	printf("%d", ins_int -> dim);

35 Risposte

  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    C'è un altro thread ... e 4.

    Comunque NON avete bisogno di nessuna allocazione per l'insieme intersezione: riordinate sti due benedetti insiemi, contate il numero di elementi in comune e il puntatore a uno dei due è già il puntatore che vi serve per l'intersezione
  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    Grazie mille ma per la consegna che mi è stata data devo per forza creare una nuova variabile di tipo puntatore a insieme_t e restituire quella, come posso fare?
  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    Perché scrivi così

    ins_int = intersezione(ins1<, ins2);

    ??

    Perché la calloc la fai solo se quella if viene soddisfatta

    if (ins1.ind == 0)
    ins_int = (insieme_t*)calloc(1, sizeof(insieme_t));

    ??

    E dove sono ins1 e ins nel main2?
  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    Ins1 e ins2 sono stati dichiarati e riempiti in un altro punto della main.
    Il minore dopo ins1 l'ho aggiunto per sbaglio solo qua sul forum.
    ins_int non è lo stesso insieme della funzione intersezione ma è una variabil edello stesso tipo e con lo stesso nome dichiarata nella main.
  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    DAGGERS ha scritto:


    Grazie mille ma per la consegna che mi è stata data devo per forza creare una nuova variabile di tipo puntatore a insieme_t e restituire quella, come posso fare?
    E che ci vuole? basta modificare leggermente la soluzione senza allocazione
    
    #include <stdio.h>
    
    struct insieme
    {
      double *  a;
      int       l;
    };
    
    insieme * intersezione(insieme i1, insieme i2, unsigned int step)
    {
        int k, j;
        double temp;
        insieme * ret = NULL;
    
        for(k = step; k < i1.l; k++)
            for(j = step; j < i2.l; j++)
                if(i1.a[k] == i2.a[j])
                {
                    temp = i1.a[step];
                    i1.a[step] = i1.a[k];
                    i1.a[k] = temp;
                    temp = i2.a[step];
                    i2.a[step] = i2.a[j];
                    i2.a[j] = temp;
                    return intersezione(i1, i2, step + 1);
                }
    
        ret = (insieme *)malloc(sizeof(insieme));
        if(ret == NULL)
            return NULL;   
        ret->l = step;
        if(step){
            ret->a = (double *)malloc(step*sizeof(double));  
            if(ret->a == NULL)
                return NULL;  
            while(step--)
                ret->a[step] = i1.a[step];       
        }
        else
            ret->a = NULL;
        
        return ret;    
    }
    
    int main(void)
    {
        int n1, n2;
        insieme insieme1, insieme2; 
        insieme * intersez;
        
        printf ("Inserisci il numero di elementi del primo insieme: ");
        scanf (" %d", &n1);
        if(n1 < 0){
            printf ("Valore immesso non valido\n");
            getchar();
            return -1;
        }
        else if(n1 > 0){
            insieme1.a = (double *)malloc(n1*sizeof(double));
            if(insieme1.a == NULL){
                printf ("Memoria insufficiente\n");
                getchar();
                return -1;          
            }
        }   
        insieme1.l = n1;
        while(n1--){
            printf ("Inserisci elemento: ");    
            scanf(" %lf", &insieme1.a[n1]);
        }
        
        printf ("Inserisci il numero di elementi del secondo insieme: ");
        scanf (" %d", &n2);
        if(n2 < 0){
            printf ("Valore immesso non valido\n");
            getchar();
            return -1;
        }
        else if(n2 > 0){
            insieme2.a = (double *)malloc(n2*sizeof(double));
            if(insieme2.a == NULL){
                printf ("Memoria insufficiente\n");
                getchar();
                return -1;          
            }
        }   
        insieme2.l = n2;
        while(n2--){
            printf ("Inserisci elemento: ");    
            scanf(" %lf", &insieme2.a[n2]);
        }
        
        intersez = intersezione(insieme1, insieme2, 0);
        if(intersez == NULL){
            printf ("Memoria insufficiente\n");
            getchar();
            return -1;          
        }    
        if(intersez->l > 0){
    	printf("L'intersezione dei due insiemi ha dimensione %d ", intersez->l);
            printf("ed e' composta dagli elementi:\n");
            for(n1 = intersez->l - 1; n1 >= 0; n1--)
                printf("%lf\n", intersez->a[n1]);
        }
        else
    	printf("L'intersezione dei due insiemi e' vuota\n");
    
        getchar();
        return 0;
    }
    
    Volendo potresti anche levare step dal prototipo
  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    DAGGERS ha scritto:


    Ins1 e ins2 sono stati dichiarati e riempiti in un altro punto della main.
    Ci mostri come hai fatto ? Così proviamo tutto ... che ne dici?
    Il minore dopo ins1 l'ho aggiunto per sbaglio solo qua sul forum.
    Ok
    ins_int non è lo stesso insieme della funzione intersezione ma è una variabil edello stesso tipo e con lo stesso nome dichiarata nella main.
    No ... questa non l'ho capita. Io ti parlo di quella locale dichiarata nella funzione. E la mia domanda era sul perché la calloc è sotto la if. Non mi hai risposto.
  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    La calloc è sotto l'if perchè alloco la memoria solo la prima volta in cui viene eseguita la funzione intersezione altrimenti poi ogni volta che la funzione richiama se stessa mi sovrascrive i dati che devo mantenere. il resto della main è:

    void stampa_ins (insieme_t);

    int main (void)
    {
    insieme_t ins1, /*variabile per rappresentare il primo insieme */
    ins2, /*variabile per rappresentare il secondo insieme */
    *ins_int, /*variabile per l'insieme intersezione*/
    int i, /*variabile per un ciclo for*/
    ris, /*variabile per esito prima funzione*/
    esito_lettura, /*variabile per la validazione stretta*/
    j;


    do /*validazione stertta e acquisizione del */
    { /*numero di elementi del primo insieme */
    printf("Digitare il numero di elementi del primo insieme (>0) e premere invio:");
    esito_lettura = scanf("%d",
    &ins1. dim);
    if ((ins1 . dim < 0) || (esito_lettura != 1))
    {
    printf("Input non accettabile!\n");
    while(getchar() != '\n');
    }

    }
    while ((ins1 . dim < 0) || (esito_lettura != 1));

    ins1 . arr = (double *) calloc( ins1 . dim, sizeof(double)); /* allocazione di memoria in base al n° di elementi*/

    for (ins1 . ind = 0; ( ins1 . ind) < (ins1 . dim); ins1 . ind ++) /* ciclo for per inserire gli elementi */
    { /* del primo insieme nell'array */
    do
    {
    printf("Digitare l'elemento n°%d del primo insieme:",
    ins1 . ind );
    esito_lettura = scanf ("%lf",
    &ins1 . arr[ins1 . ind]);
    j = 0;
    for( i = 0; i < ins1 . ind; i++)
    {
    if((ins1 . arr[ins1 . ind] == ins1 . arr) || (esito_lettura != 1))
    {
    printf("Input non accettabile perche' uguale a un elemento già presente\n");
    j = 1;
    while(getchar() != '\n');
    }
    }
    }
    while((j == 1) || (esito_lettura != 1));
    }



    do /*validazione stertta e acquisizione del */
    { /*numero di elementi del secondo insieme */
    printf("Digitare il numero di elementi del secondo insieme (>0) e premere invio:");
    esito_lettura = scanf("%d",
    &ins2 . dim);
    if ((ins2 . dim < 0) || (esito_lettura != 1))
    {
    printf("Input non accettabile!\n");
    while (getchar() != '\n');
    }
    }
    while ((ins2 . dim < 0) || (esito_lettura != 1));

    ins2 . arr = (double *) calloc( ins2 . dim, sizeof(double)); /* allocazione di memoria in base al n° di elementi*/

    for (ins2 . ind = 0; ( ins2 . ind) < (ins2 . dim); ins2 . ind ++) /* ciclo for per inserire gli elementi */
    { /* del secondo insieme nell'array */
    do
    {
    printf("Digitare l'elemento n°%d del secondo insieme:",
    ins2 . ind );
    esito_lettura = scanf ("%lf",
    &ins2 . arr[ins2 . ind]);
    j = 0;
    for( i = 0; i < ins2 . ind; i++)
    if((ins2 . arr[ins2 . ind] == ins2 . arr) || (esito_lettura != 1))
    {
    printf("Input non accettabile perche' uguale a un elemento gia' presente\n");
    j = 1;
    while(getchar() != '\n');

    }
    }
    while ( j == 1);
    }

    ins1 . ind = 0;
    ris = confronto(ins1, ins2);
    if(ris == 0)
    printf("I due insiemi sono diversi.\n");
    else
    printf("I due insiemim sono uguali.");


    /*ins_int = (insieme_t*) calloc(1, sizeof(insieme_t));*/
    ins_int = intersezione(ins1, ins2);
    printf("L'insieme intersezione ha i seguenti elementi:\n");
    stampa_ins(ins_int);
    return(0);
    }

    void stampa_ins (insieme_t *ins)
    {
    printf("\nSTAMPA\n");
    for(ins -> ind = 0; ins -> ind < ins -> dim; ins -> ind ++)
    {
    printf("%lf \t", ins -> arr[ins -> ind]);
    if(ins -> ind == ins -> dim --)
    printf("\n");
    }

    ins -> ind = 0;
    }

    Ho provato anche a stampare a schermo l'insieme senza la funzione stampa_ins, ossia tramite lo steso ciclo for all'interno della main ma comunque non funziona.
  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    Usa i tag CODE altrimenti il codice diventa illeggibile. E dacci un'idea sui dati in input utilizzati per il tuo test.

    Comunque, se chiami la funzione "ricorsivamente" il puntatore ind_int sarà sempre diverso da chiamata in chiamata. Se lo devi passare tra le chiamate devi farlo negli argomenti.
  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    Ho fatto diversi test ma non so neanche l'esito dato che mi dà errore di segmentazione prima
    #include<stdio.h>
    #include<stdlib.h>
    #include"ins.h"
    
    void stampa_ins (insieme_t *);
    
    int main (void)
    {
    	insieme_t ins1, 		  	/*variabile per rappresentare il primo insieme */
    		      ins2,           	/*variabile per rappresentare il secondo insieme */
    		      *ins_int,        	/*variabile per l'insieme intersezione*/
    	int i,                    	/*variabile per un ciclo for*/
    		ris,                 	/*variabile per esito prima funzione*/
    	    esito_lettura,              /*variabile per la validazione stretta*/
    	    j;
    	
    
    	do                                                                                       /*validazione stertta e acquisizione del */                              
    	{                                                                                        /*numero di elementi del primo insieme   */                            
    	 	printf("Digitare il numero di elementi del primo insieme (>0) e premere invio:");
    		esito_lettura = scanf("%d", 
    			  	      &ins1. dim);
    		if ((ins1 . dim < 0) || (esito_lettura != 1))
    		{	
    			printf("Input non accettabile!\n");
    	     		while(getchar() != '\n');
    		}
    	
    	}
    	while ((ins1 . dim < 0) || (esito_lettura != 1));
    
    	ins1 . arr = (double *) calloc( ins1 . dim, sizeof(double));              /* allocazione di memoria in base al n° di elementi*/
    
    	for (ins1 . ind = 0; ( ins1 . ind) < (ins1 . dim); ins1 . ind ++)            /* ciclo for per inserire gli elementi  */
    	{                                                                                /* del primo insieme nell'array        */
    		do
    		{
    			printf("Digitare l'elemento n°%d del primo insieme:", 
    				   ins1 . ind );
    			esito_lettura = scanf ("%lf", 
    				   	       &ins1 . arr[ins1 . ind]);
    			j = 0;
    			for( i = 0; i < ins1 . ind; i++)
    			{
    				if((ins1 . arr[ins1 . ind] == ins1 . arr[i]) || (esito_lettura != 1))
    				{	
    					printf("Input non accettabile perche' uguale a un elemento già presente\n");
    					j = 1;
    					while(getchar() != '\n');
    				}
    			}
    		}
            	while((j == 1) || (esito_lettura != 1));
    	}	
    
    
    
    	do                                                                                       /*validazione stertta e acquisizione del */                              
    	{                                                                                        /*numero di elementi del secondo insieme */                            
    	 	printf("Digitare il numero di elementi del secondo insieme (>0) e premere invio:");
    		esito_lettura = scanf("%d", 
    			  	      &ins2 . dim);
    		if ((ins2 . dim < 0) || (esito_lettura != 1))
    		{	
    			printf("Input non accettabile!\n");
    		    	while (getchar() != '\n');
    		}    
    	}
    	while ((ins2 . dim < 0) || (esito_lettura != 1));
    
    	ins2 . arr = (double *) calloc( ins2 . dim, sizeof(double));              /* allocazione di memoria in base al n° di elementi*/
    
    	for (ins2 . ind = 0; ( ins2 . ind) < (ins2 . dim); ins2 . ind ++)            /* ciclo for per inserire gli elementi  */
    	{                                                                                /* del secondo insieme nell'array       */
    		do
    		{
    			printf("Digitare l'elemento n°%d del secondo insieme:", 
    				   ins2 . ind );
    			esito_lettura = scanf ("%lf", 
    				   &ins2 . arr[ins2 . ind]);
    			j = 0;
    			for( i = 0; i < ins2 . ind; i++)
    			if((ins2 . arr[ins2 . ind] == ins2 . arr[i]) || (esito_lettura != 1))
    				{	
    					printf("Input non accettabile perche' uguale a un elemento gia' presente\n");
    		            		j = 1;
    					while(getchar() != '\n');
    
    		        	}
    		}
            	while ( j == 1);
    	}
    	
    	ins1 . ind = 0;
    	ris = confronto(ins1, ins2);
    	if(ris == 0)
    		printf("I due insiemi sono diversi.\n");
    	else 
    		printf("I due insiemim sono uguali.");
    
    	
    	/*ins_int = (insieme_t*) calloc(1, sizeof(insieme_t));*/
    	ins_int = intersezione(ins1, ins2);
    	printf("L'insieme intersezione ha il seguenti elementi:\n");
    	stampa_ins(ins_int);
    	
    	return(0);
    }	
    
    void stampa_ins (insieme_t *ins)
    {
    	for(ins -> ind = 0; ins -> ind < ins -> dim; ins -> ind ++)
    	{	
    		printf("%lf \t", ins -> arr[ins -> ind]);
    		if(ins -> ind == ins -> dim --)
    			printf("\n");
    	}
    	
    	ins -> ind = 0;
    
    }
  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    Rileggiti TUTTI i commenti relativi agli altri 3 o 4 thread su questo stesso argomento, li trovi in questo sub-forum.

    L'allocazione DEVE essere fatta FUORI dalla funzione ricorsiva.
  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    DAGGERS ha scritto:


    Ho fatto diversi test ma non so neanche l'esito dato che mi dà errore di segmentazione prima
    Questo perché il tuo ins_int è già sbagliato alla seconda iterazione, quindi quando tenti di stampare il primo elemento del suo array fai una chiamata ad un'area di memoria totalmente sballata.

    Rileggi gli altri topic e/o la soluzione postata qui, gli errori che fate tutti sono sempre gli stessi
  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    Weierstrass ha scritto:


    DAGGERS ha scritto:


    Ho fatto diversi test ma non so neanche l'esito dato che mi dà errore di segmentazione prima
    Questo perché il tuo ins_int è già sbagliato alla seconda iterazione, quindi quando tenti di stampare il primo elemento del suo array fai una chiamata ad un'area di memoria totalmente sballata.

    Rileggi gli altri topic e/o la soluzione postata qui, gli errori che fate tutti sono sempre gli stessi
    Quale sarebbe la seconda iterazione?
    Poi la soluzione sconvolge un po troppo il codice, e vorremmo far funzionare l'idea che abbiamo
  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    Zack909 ha scritto:


    Weierstrass ha scritto:


    DAGGERS ha scritto:


    Ho fatto diversi test ma non so neanche l'esito dato che mi dà errore di segmentazione prima
    Questo perché il tuo ins_int è già sbagliato alla seconda iterazione, quindi quando tenti di stampare il primo elemento del suo array fai una chiamata ad un'area di memoria totalmente sballata.

    Rileggi gli altri topic e/o la soluzione postata qui, gli errori che fate tutti sono sempre gli stessi
    Quale sarebbe la seconda iterazione?
    Poi la soluzione sconvolge un po troppo il codice, e vorremmo far funzionare l'idea che abbiamo
    Quando intersezione() chiama se stessa, è come se chiamasse un'altra funzione: tutte le informazioni che non vengono passate tramite parametri o tramite variabili globali sono perse.

    Nel vostro caso: che fine ha fatto il valore del puntatore insieme_int che avete impostato con la calloc nella prima chiamata di intersezione ()? La seconda chiamata di intersezione () non ne sa nulla! Ricomincia con un altro puntatore.

    O passate le informazioni tramite i parametri del prototipo, come ho suggerito io, o li passate dall'esterno, come vi ha suggerito Nicola.

    Attenzione a utilizzare gli operatori ++ e --, perché possono riferirsi alle variabili della funzione precedente chiamate per valore e non per riferimento. Nel dubbio usate + 1 e - 1 che non muore nessuno. Ma tutto questo è già stato fatto notare (non mi ricordo da chi).

    P.s.: tutto ciò è estremamente più facile da capire se eseguite il codice in modalità debug.
  • Re: RESTITUZIONE DI PUNTATORE A STRUCT

    Weierstrass ha scritto:


    Attenzione a utilizzare gli operatori ++ e --, perché possono riferirsi alle variabili della funzione precedente chiamate per valore e non per riferimento. Nel dubbio usate + 1 e - 1 che non muore nessuno. Ma tutto questo è già stato fatto notare (non mi ricordo da chi).
    Questa me la spiegheresti?
    Dissento
Devi accedere o registrarti per scrivere nel forum
35 risposte