Dubbio puntatori

di il
14 risposte

Dubbio puntatori

Salve, ho fatto questo programma banale per chiarirmi meglio il concetto dei puntatori
#include <stdio.h>
#include <stdlib.h>
#define DIM 2

void Funzione(int **ptr);
void AllocareMemoriaVar(int **ptr);
void ScrivereVettore(int *p_var);
void StampareVettore(int *p_var);

int main(void){
	int *var = NULL;

	Funzione(&var);
	ScrivereVettore(var);
	StampareVettore(var);

	system("pause");
	return 0;
}

void Funzione(int **ptr){
	AllocareMemoriaVar(ptr);

	return;
}

void AllocareMemoriaVar(int **ptr){
	*ptr = malloc(DIM * sizeof(int));

	return;
}

void ScrivereVettore(int *p_var){
	*(p_var + 0) = 1;
	*(p_var + 1) = 2;

	return;
}

void StampareVettore(int *p_var){
	printf("%d  %d\n",*(p_var + 0),*(p_var + 1));

	return;
}
Se in C è concesso fare una cosa del genere

int a;
int *p = &a;
e anche questo:

int a;
int *p;
p = &a;
perchè invece nella funzione

void AllocareMemoriaVar(int **ptr){
	*ptr = malloc(DIM * sizeof(int));
	?
	return;
}
se tolgo l'asterisco da ptr il compilatore mi segnala un warning? Grazie.

14 Risposte

  • Re: Dubbio puntatori

    Perché il puntatore a int è *ptr
    Se usi solo ptr allora stai usando un puntatore a puntatore a int e non va bene
  • Re: Dubbio puntatori

    Quindi se il puntatore è *ptr
    dovrei scrivere:
    
    void Funzione(int **ptr){
    	AllocareMemoriaVar(*ptr);
    
    	return;
    }
    
    ?
  • Re: Dubbio puntatori

    No.
    Perché alla funzione devi passare il puntatore al puntatore in modo che la malloc possa modificare il puntatore
  • Re: Dubbio puntatori

    Se hai dichiarato
    
    int **ptr;
    
    Allora:
    ptr è un puntatore a puntatore a int.
    *ptr restituisce un puntatore a int (ci puoi memorizzate il risultato della malloc).
    **ptr dereferenzia *ptr e quindi restituisce l'int.
  • Re: Dubbio puntatori

    In riferimento a questo, ho fatto questo programma dove le funzioni hanno una logica corretta (ho svolto l'esercizio prima senza allocazione dinamica e funzionava) e adesso avrò fatto qualche pasticcio con i puntatori.
    L'errore sta nella funzione GenerareStringaOutput dove credo di aver sbagliato a utilizzare il doppio puntatore per scrivere gli elementi del vettore p_mstringa.
    La cosa che non capisco è come fare a scrivere gli elementi del puntatore char *mstringa attraverso la funzione GenerareStringaOutput che ha in input il doppio puntatore char **p_mstringa ,necessario per dare in input alla sottofunzione AllocareMemoriaP_Mstringa il puntatore a puntatore.
    
    /*Si consideri la sequenza “a, b, (a, c, g), b, e, (p,q ), a, (x, x), f”.
    La sequenza di output sarà allora la seguente: a, b, (*), b, e, (*), a, (*), f.
    */
    #include <stdio.h>
    #include <stdlib.h>
    #define DIM 50
    #define PA '('
    #define PC ')'
    
    int VerificareCorrettezzaStringa(char *stringa);
    void GenerareStringaOutput(char **p_mstringa, char *stringa);
    void AllocareMemoriaP_Mstringa(int i, char **p_mstringa);
    void StampaStringa(char *p_mstringa);
    
    int main(void){
    	int i;
    	char *stringa = "a, b, (a, c, g), b, e, (p,q ), a, (x, x), f";
    	char *mstringa = NULL;
    
    	i = VerificareCorrettezzaStringa(stringa);
    	printf("i: %d\n",i);
    
    	if (i == 1){
    		GenerareStringaOutput(&mstringa, stringa);
    	}
    	StampaStringa(mstringa);
    
    	system("pause");
    	return 0;
    }
    
    int VerificareCorrettezzaStringa(char *stringa){
    	int j = 0;
    	int trovato = 1;
    
    	while(stringa[j] != '\0' && trovato == 1){
    			if (stringa[j] == PC){
    				trovato = -1;
    			}
    			if (stringa[j] == PA){
    				while(stringa[j] != PC && trovato == 1){
    					if (stringa[j + 1] == PA){
    						trovato = -1;
    					}
    					j++;
    				}
    			}
    			j++;
    	}
    
    	return trovato;
    }
    //considerare anche il caso in cui all'interno delle parentesi non vi è alcun numero
    void GenerareStringaOutput(char **p_mstringa, char *stringa){
    	int i = 0;
    	int j = 0;
    
    	while(stringa[i] != '\0'){
    		AllocareMemoriaP_Mstringa(j + 1, p_mstringa);
    		*(*p_mstringa + j) = *(stringa + i);
    		if(*(stringa + i) == PA){
    			j++;
    			*(*p_mstringa + j) = '*';            
    			while(*(stringa + i) != PC){
    				i++;
    			}
    			j++;
    			*(*p_mstringa + j) = PC;             
    		}
    		i++;
    		j++;
    	}
    	*(p_mstringa + j) = '\0';
    }
    
    void AllocareMemoriaP_Mstringa(int j, char **p_mstringa){
    	*p_mstringa = (char *) realloc (*p_mstringa, j * sizeof(char));
    
    	return;
    }
    
    void StampaStringa(char *p_mstringa){
    	printf("%s\n",p_mstringa);
    
    }
  • Re: Dubbio puntatori

    Monkey ha scritto:


    La cosa che non capisco è come fare a scrivere gli elementi del puntatore char *mstringa attraverso la funzione GenerareStringaOutput che ha in input il doppio puntatore char **p_mstringa ,necessario per dare in input alla sottofunzione AllocareMemoriaP_Mstringa il puntatore a puntatore.
    
    void AllocareMemoriaP_Mstringa(int j, char **p_mstringa){
    	*p_mstringa = (char *) realloc (*p_mstringa, j * sizeof(char));
    
    	return;
    }
    A che serve una funzione di una riga che chiama un'altra funzione?
  • Re: Dubbio puntatori

    Non ho ben capito la tua domanda. A quale funzione ti riferisci?
    La funzione GenerareStringaOutput ha come sottofunzione la funzione AllocareMemoriaP_Mstringa che va ad allocare lo spazio di memoria che ospiterà gli elementi che verranno scritti all'interno della funzione GenerareStringaOutput.
  • Re: Dubbio puntatori

    Come ti ha mostrato (hai letto bene?) Weierstrass si riferisce alla AllocareMemoriaP_Mstringa che non fa altro che chiamare la realloc.

    Ritengo che sia solamente una questione didattica.
  • Re: Dubbio puntatori

    Nel senso che non c'é bisogno di utilizzare una sottofunzione e che posso inserire la realloc direttamente nella funzione GenerareStringaOutput ?
    In ogni caso non dovrebbe essere un errore, come posso far funzionare il programma ugualmente?
  • Re: Dubbio puntatori

    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char *GenerareStringaOutput(char *stringa);
    
    int main(void){
    	char *stringa = "a, b, (a, c, g), b, e, (p,q ), a, (x, x), f";
    	char *mstringa = GenerareStringaOutput(stringa);
            printf("%s\n", mstringa);
    	return 0;
    }
    
    char *GenerareStringaOutput(char *stringa){
        int i, j, open_parenthesis, was_space;
    
        char *p_mstringa = (char *)malloc(strlen(stringa) + 1);
    
        for(i = j = open_parenthesis = was_space = 0; stringa[i] != '\0'; i++){
            if(stringa[i] == '('){
                if(!open_parenthesis)
                    p_mstringa[j++] = '(';
                open_parenthesis++;
            }
            else if(stringa[i] == ')'){
                open_parenthesis--;
                if(!open_parenthesis){
                    p_mstringa[j++] = '*';
                    p_mstringa[j++] = ')';           
                }
                was_space = 0;
            }       
            else {
                if(!open_parenthesis && !(was_space && stringa[i] == ' '))
                    p_mstringa[j++] = stringa[i];    
                if(stringa[i] == ' ')
                    was_space = 1;
                else
                    was_space = 0;                         
            }             
        }
        p_mstringa[j] = '\0';  
    
        return p_mstringa;
    }
    
  • Re: Dubbio puntatori

    Weierstrass ti ringrazio per l'algoritmo, però io avrei preferito capire come far funzionare il mio algoritmo , in quanto a livello di logica è corretto, ho sbagliato solo ad utilizzare i puntatori e mi piacerebbe sapere dove ho sbagliato.
  • Re: Dubbio puntatori

    Versione doppio puntatore
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void GenerareStringaOutput(char **rstringa, char *stringa);
    
    int main(void){
    	char *stringa = "a, b, (a, c, g), b, e, (p,q ), a, (x, x), f";
    	char *mstringa;
    	GenerareStringaOutput(&mstringa, stringa);
            printf("%s\n", mstringa);
    	return 0;
    }
    
    void GenerareStringaOutput(char **rstringa, char *stringa){
        int i, j, open_parenthesis, was_space;
    
        char *p_mstringa = (char *)malloc(strlen(stringa) + 1);
    
        for(i = j = open_parenthesis = was_space = 0; stringa[i] != '\0'; i++){
            if(stringa[i] == '('){
                if(!open_parenthesis)
                    p_mstringa[j++] = '(';
                open_parenthesis++;
            }
            else if(stringa[i] == ')'){
                open_parenthesis--;
                if(!open_parenthesis){
                    p_mstringa[j++] = '*';
                    p_mstringa[j++] = ')';           
                }
                was_space = 0;
            }       
            else {
                if(!open_parenthesis && !(was_space && stringa[i] == ' '))
                    p_mstringa[j++] = stringa[i];    
                if(stringa[i] == ' ')
                    was_space = 1;
                else
                    was_space = 0;                         
            }             
        }
        p_mstringa[j] = '\0';  
    
        *rstringa = p_mstringa;
    }
    
  • Re: Dubbio puntatori

    Ok grazie, ora sono riuscito a modificare il mio codice seguendo quello che mi hai scritto e funziona correttamente, l'unico dubbio che ho è il perchè se scrivo
    
    void GenerareStringaOutput(char **rstringa, char *stringa){
    	int i = 0;
    	int j = 0;
    	char *p_mstringa = malloc(strlen(stringa) + 1 * sizeof(char));
    
    	while(stringa[i] != '\0'){
    		*(p_mstringa + j) = *(stringa + i);
    		if(*(stringa + i) == PA){
    			j++;
    			*(p_mstringa + j) = '*';          //se scrivo *(p_mstringa + j++) =  '*'; non funziona più 
    
    			while(*(stringa + i) != PC){
    				i++;
    			}
    			j++;
    			*(p_mstringa + j) = PC;              //se scrivo *(p_mstringa + j++) = PC; non funziona più
    
    		}
    		i++;
    		j++;
    	}
    	*(p_mstringa + j) = '\0';
    
    	*rstringa = p_mstringa;
    }
    

    funziona , mentre se scrivo
    
    void GenerareStringaOutput(char **rstringa, char *stringa){
    	int i = 0;
    	int j = 0;
    	char *p_mstringa = malloc(strlen(stringa) + 1 * sizeof(char));
    
    	while(stringa[i] != '\0'){
    		*(p_mstringa + j) = *(stringa + i);
    		if(*(stringa + i) == PA){
    			//j++;
    			*(p_mstringa + j++) = '*';        
    
    			while(*(stringa + i) != PC){
    				i++;
    			}
    			//j++;
    			*(p_mstringa + j++) = PC;              
    
    		}
    		i++;
    		j++;
    	}
    	*(p_mstringa + j) = '\0';
    
    	*rstringa = p_mstringa;
    }
    
    non funziona più
  • Re: Dubbio puntatori

    L'equivalente di
    
    	j++;
    	*(p_mstringa + j) = '*';  
    
    è
    
    	*(p_mstringa + ++j) = '*'; 
    
    Nel tuo codice ti serve il pre-incremento perché qui
    		
    	*(p_mstringa + j) = *(stringa + i);
    
    l'indice j non l'hai incrementato dopo l'istruzione.

    Quindi se per esempio la stringa da trasformare è "(a)", già al primo carattere sul nuovo array prima scrivi '(' e poi subito dopo lo sovrascrivi con '*'
Devi accedere o registrarti per scrivere nel forum
14 risposte