Puntatori a Funzione[C]

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Puntatori a Funzione[C]

Messaggio da gila75 »

Mi scuso con tutti per il battibecco. Chi vorrà mi darà ancora una mano, chi non vuole ok.
Sono solo un principiante che s'impunta perchè non sta capendo e vuole capire i propri errori e non perchè dice di aver ragione.
Ci tengo a precisarlo.
Studio il C da circa un anno da solo e si e no 1 ora al giorno...quindi non ho voci in capitolo e sono l'ultimo degli ignoranti.
Se ho dato l'idea del sapientone e provocatore, mi scuso. Ma davvero non sono così.
Gila
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Puntatori a Funzione[C]

Messaggio da gila75 »

Probabilmente quello che intendevate (mi riferisco a quanto detto da vbextreme sul qsort), è un prototipo più o meno simile:

Codice: Seleziona tutto

#include <math.h>
#include <stdio.h>

double seno (double (*f)(double), double x);

double seno (double(*f)(double), double x)
{
    return (*f)(x);
    
}

int main (void)
{
    double y=45;
    double res;  
    double (*ptr)(double)=sin;
    res=seno ((*ptr),y);
    printf ("risultato di sin %3.0f = %f\n",y,res);
    return 0;

}
Oppure:

Codice: Seleziona tutto

#include <math.h>
#include <stdio.h>

double seno (double (*f)(double), double x);

double seno (double(*f)(double), double x)
{
    return (*f)(x);
    
}

int main (void)
{
    double y=45;
    double res;  
    res=seno (sin,y);
    printf ("risultato di sin %3.0f = %f\n",y,res);
    return 0;

}
La seconda versione è un po' più compatta.
Praticamente, creo un puntatore a sin (che è già una funzione inclusa in <math.h>), le passo il valore, poi passo tutto alla funzione seno.
Poi ritorno il valore.
Avrei potuto usare anche una funzione void.
Giusto il ragionamento?
Avatar utente
vbextreme
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1214
Iscrizione: domenica 12 gennaio 2014, 14:06
Desktop: lxde
Distribuzione: xubuntu 14.10

Re: Puntatori a Funzione[C]

Messaggio da vbextreme »

e bravo gila.
Ora a grandi linee hai capito il concetto,quindi li sai usare e passare, manca solo un bel vettore di puntatori a funzione e chiudi definitivamente il capitolo.
Puoi vedere l'esempio nel mio ultimo codice postato sulla qsort e simili.
Easy framework per il linguaggio C.
vbextreme hack your life
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Puntatori a Funzione[C]

Messaggio da gila75 »

vbextreme [url=http://forum.ubuntu-it.org/viewtopic.php?p=4559335#p4559335][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:e bravo gila.
Ora a grandi linee hai capito il concetto,quindi li sai usare e passare, manca solo un bel vettore di puntatori a funzione e chiudi definitivamente il capitolo.
Puoi vedere l'esempio nel mio ultimo codice postato sulla qsort e simili.
Bhè, diciamo che mi piacerebbe prendere più confidenza,quello era solo un esempio banale. In questi giorni mi esercito.
Non sto qui a spiegare cosa mi aveva incasinato oltre al ben noto discorso del **.
Io avevo capito che dovevo implementare funzioni tipo qsort, sin ecc nelle funzioni e non come ho fatto che le chiamo nel main e definisco il puntatore a funzione di sin, qsort, ecc fuori dal main.
Non so se mi riesco a spiegare.
Nel frattempo, mi prendo una pausa e rileggo bene i puntatori, mi avete messo la pulce nell'orecchio.
Credo di averli capiti, al di la della ben nota gaffe, sicuramente non nel profondo e in tutte le loro sfaccettature, logico, sono uno degli argomenti più complessi.
Facili finchè si fa:
int a=10;
int *p=&a;

ma poi usarli bene è un altro paio di maniche.
Grazie vbextreme :)
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Puntatori a Funzione[C]

Messaggio da gila75 »

Sto facendo un po' di prove, inventando esempi, e nel frattempo rispolverando\approfondendo i puntatori.
é corretto, ricollegandomi al discorso del doppio puntatore questo esempio?
Sono esercizi ancora sui puntatori a funzioni.
Ma al posto di passare le variabili a e b per valore, le passo per indirizzo alla prima funzione.
Siccome la funzione, deve passare ancora le variabili alla seconda funzione, penso sia corretto passare il doppio puntatore.
Se ho sbagliato, pace amen, mi esercito ancora.
Il discorso del puntatore a funzione, inizio ad assimilarlo, ma ci vuole pratica.
Ecco il codice:

Codice: Seleziona tutto

#include <math.h>
#include <stdio.h>
int somma (int **x,int **y);
int ritorna (int (*f)(int**,int**), int *x,int *y);

int somma (int **x,int **y)
{
    return (**x)+(**y); //45+55=100
}


int  ritorna ( int(*f)(int**,int**), int *x, int *y)

{
    int j;
    j=(*f)(&x,&y);
    return j*3; //return 100*3=300
}

int main (void)
{
    int a=45;
    int b=55;  
    int res;
    res=ritorna (somma,&a,&b);
    printf ("risultato di somma %d\n",res);
    return 0;

}
Poi proverò gli array di puntatori a funzione, ma con calma...
Avatar utente
ienaplinsky
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 954
Iscrizione: giovedì 21 gennaio 2010, 9:56
Località: Napoli

Re: Puntatori a Funzione[C]

Messaggio da ienaplinsky »

gila75 ha scritto: Ma al posto di passare le variabili a e b per valore, le passo per indirizzo alla prima funzione.
Siccome la funzione, deve passare ancora le variabili alla seconda funzione, penso sia corretto passare il doppio puntatore.

Codice: Seleziona tutto

#include <math.h>
#include <stdio.h>
int somma (int **x,int **y);
int ritorna (int (*f)(int**,int**), int *x,int *y);

int somma (int **x,int **y)
{
    return (**x)+(**y); //45+55=100
}


int  ritorna ( int(*f)(int**,int**), int *x, int *y)

{
    int j;
    j=(*f)(&x,&y);
    return j*3; //return 100*3=300
}
è corretto sintatticamente, ma più corretto (secondo me) logicamente passare il singolo puntatore
nulla vietava di fare

Codice: Seleziona tutto

int somma (int *x,int *y)
{
    return (*x)+(*y); //45+55=100
}
int  ritorna ( int(*f)(int*,int*), int *x, int *y)

{
    int j;
    j=(*f)(x,y);
    return j*3; //return 100*3=300
}
antex
Prode Principiante
Messaggi: 85
Iscrizione: mercoledì 14 marzo 2012, 20:59

Re: Puntatori a Funzione[C]

Messaggio da antex »

gila75 [url=http://forum.ubuntu-it.org/viewtopic.php?p=4559809#p4559809][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:Siccome la funzione, deve passare ancora le variabili alla seconda funzione, penso sia corretto passare il doppio puntatore.
E se la seconda funzione passava le variabili a una terza funzione usavi int***? :nono: Basta una sola indirezione, se vuoi che la seconda funzione modifichi il valore originario. Con la doppia indirezione permetti alla seconda funzione (somma) di modificare non solo la variabile originaria (scrivendo su **x), ma anche quella della prima funzione (ritorna, scrivendo su *x).

Anzi, logicamente in quell'esempio non serve alcuna indirezione. I puntatori a variabili si usano sostanzialmente per due motivi:
  • devi far sì che la funzione possa modificare il valore di una variabile (e allora per forza devi passarne il puntatore)
  • dovresti passare una struttura (o qualcos'altro) che occupa molti byte e per questioni di efficienza passi il puntatore (che è più piccolo)
Nel caso che hai mostrato non vale nessuna delle due. :ciao:
Avatar utente
ienaplinsky
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 954
Iscrizione: giovedì 21 gennaio 2010, 9:56
Località: Napoli

Re: Puntatori a Funzione[C]

Messaggio da ienaplinsky »

antex ha scritto:
gila75 [url=http://forum.ubuntu-it.org/viewtopic.php?p=4559809#p4559809][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:Siccome la funzione, deve passare ancora le variabili alla seconda funzione, penso sia corretto passare il doppio puntatore.
E se la seconda funzione passava le variabili a una terza funzione usavi int***? :nono: Basta una sola indirezione, se vuoi che la seconda funzione modifichi il valore originario. Con la doppia indirezione permetti alla seconda funzione (somma) di modificare non solo la variabile originaria (scrivendo su **x), ma anche quella della prima funzione (ritorna, scrivendo su *x).

Anzi, logicamente in quell'esempio non serve alcuna indirezione. I puntatori a variabili si usano sostanzialmente per due motivi:
  • devi far sì che la funzione possa modificare il valore di una variabile (e allora per forza devi passarne il puntatore)
  • dovresti passare una struttura (o qualcos'altro) che occupa molti byte e per questioni di efficienza passi il puntatore (che è più piccolo)
Nel caso che hai mostrato non vale nessuna delle due. :ciao:
concordo ma gila per esercitarsi voleva passarle per riferimento, per questo ho detto che in quel caso il singolo * era la cosa più corretta
gila75 ha scritto: Ma al posto di passare le variabili a e b per valore, le passo per indirizzo alla prima funzione.
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Puntatori a Funzione[C]

Messaggio da gila75 »

Grazie Antex e Ienaplinsky
Ho capito l'errore, e ho capito che coi puntatori a puntatori ho ancora lacune.

Codice: Seleziona tutto

int  ritorna ( int(*f)(int**,int**), int *x, int *y)

{
    int j;
    j=(*f)(&x,&y);
    return j*3; //return 100*3=300
}
qui l'errore è che ho non ho considerato che x e y sono puntatori e quindi viene passato l'indirizzo anche senza l'operatore &.Diventerebbe così:

Codice: Seleziona tutto

   j=(*f)(x,y);
x e y contengono già l'indirizzo delle variabili originarie a e b era li l'errore ecco la riprova degli indirizzi:

Codice: Seleziona tutto

#include <math.h>
#include <stdio.h>
void f1 (int *x,int *y);
void f2 (int *w,int *j);


void f2 (int *w,int *j)
{
    printf ("-----------------------------\n\n");
    printf ("in funz f2 indirizzo di w(x->a) %p\n",w);
    printf ("in funz f2 indirizzo di j(y->b) %p\n",j);

    *w=1000;
    *j=5000;
    return;
}


void  f1 (int *x,int *y)

{
    printf ("in funz f1 indirizzo di x(a) %p\n",x);
    printf ("in funz f1 indirizzo di y(b) %p\n",y);
    f2(x,y);
    return ;
}

int main (void)
{
    int a=45;
    int b=55;  
    printf ("indirizzo di a nel main %p\n",&a);
    printf ("indirizzo di b nel main %p\n",&b);
    printf ("-----------------------------\n\n");
    f1 (&a,&b);
    printf ("a=%d b=%d\n ",a,b);
    return 0;

}
L'errore e la confusione del puntatore a puntatore, nasce da questo esempio:

Codice: Seleziona tutto

#include <math.h>
#include <stdio.h>


int main (void)
{
    int a=45;
    int *p=&a;
    int **q=&p;
    **q=451;
    printf ("valore modificato di a %d\n", **q);
    return 0;

}
Qui credo che sia lecito parlare di puntatore a puntatore...ma nell'esempio sopra, corretto da voi no.
Come detto, non ho considerato che nella funzione, ho già passato un indirizzo, quindi alla seconda funzione passo ancora un indirizzo.
La riprova è che sono due funzioni void e nel main ho le modifiche. Passando semplici copie di variabili, nel main ritroverei le variabili a e b NON modificate.
Comunque i punt a punt sono un po' OT.
Li riprenderò con calma.
Vorrei la conferma se ciò che ho detto è corretto, poi mi esercito per mio conto e non rompo più.
Mi rendo conto di essere pesante :D
Avatar utente
matteovid
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 368
Iscrizione: mercoledì 9 dicembre 2009, 9:09
Desktop: Openbox, XFCE, XMonad
Distribuzione: GNU/Linux Arch - openSUSE Leap
Sesso: Maschile
Località: Parma

Re: Puntatori a Funzione[C]

Messaggio da matteovid »

ciao

@ vbextreme:
sono d'accordo, aiutare il più possibile, ma anche stimolare...
il mio intervento era per stimolare Gila, non per criticarlo, per il suo impegno che ci mette è da stimolarlo e di molto, ma mi sono impazientito...
è andata così, mi sono spiegato male e ho fatto casino... oltre a in un certo punto a criticare :shy:
non sono d'accordo sul manuale, anche il più pessimo può risultare comodo in certi punti...
Invece per quanto mi riguarda sarebbe molto importante dedicare tempo a studiare i parametri del compilatore in uso, che meglio di me saprai può darti informazioni su quello che stai compilando, non solo su il debugger... e farti capire anche cosa compila e come, oltre a avere un flusso sulla compilazione con argomento -pipe... o il comando -v verbose, ma già è il C importante, poi alla prima difficoltà, tak ci si ferma... Purtroppo il C è un linguaggio che ad ogni manuale e per i primi capitoli sembra facile, poi alle funzioni e ai pointer ci si ferma (nel corso sul linguaggio C, siamo stati fermi sulle funzioni e pointer per 1 anno), ma perchè non si sa come mai non funziona, vi è il segment foult ed altro... Poi si chiede sui forum a ognuno risponde per quello che sa... A volte confondendo il richiedente, (non è il tuo caso @ vbextreme)
Sarebbe bello anche consigliare di approfondire il gdb, il debugger GNU,
Ma ben pochi lo fanno sia per gli argomenti del compilatore in uso che del gdb... ricordo che quando ho intrapreso lo studio del C, per prima cosa il prof. ci ha fatto studiare gli argomenti del compilatore, poi un esempio del C basilare e del debugger nei vari formati e usi, ci siamo soffermati su questo per circa 4 mesi, ma forse era indirizzato al studio della programmazione in C per elettronici...
anche io imparo da chi ne sa infinitamente più di me, infatti seguo per quanto possibile la parte programmazione di questo forum...

@ Gila:
ti metto un esempio di puntatore a funzione, proprio il più semplice che mi è venuto in mente...

Codice: Seleziona tutto

#include <stdio.h>

int addi (const int, const int);
int sott (const int, const int);
int dividi (const int, const int);
int molt (const int, const int);

int funz (const int, const int, int (*fprincipale)());


int main (void)
{
  int q = 34, e = 2;

  printf ("somma %d + %d = %d\n", q, e, funz (q, e, addi));
  printf ("sottrazione %d - %d = %d\n", q, e, funz (q, e, sott));
  printf ("prodotto %d * %d = %d\n", q, e, funz (q, e, molt));
  printf ("divisione %d / %d = %d\n", q, e, funz (q, e, dividi));

  return (0);
}

int addi (const int x, const int y)
{
  return (x + y);
}

int sott (const int x, const int y)
{
  return (x - y);
}

int dividi (const int x, const int y)
{
  return (x / y);
}

int molt (const int x, const int y)
{
  return (x * y);
}

int funz (const int z, const int a, int (*fprincipale)())
{
  return (*fprincipale)(z, a);
}

compila con

Codice: Seleziona tutto

gcc -W -pedantic -Wall -g -o nomeprogrammachevuoi nomeprogrammachevuoi.c
se sai usare il gdb, il debugger GNU, sarebbe interessante che seguisti il flusso del programma...
il -g nelle opzioni del compilatore serve proprio per avere i dati per il debugger nell'eseguibile...

Gila (non ho litigato, quindi pace sarebbe oltremodo un più) scuse sì te ne devo, volevo solo stimolarti, non ci sono riuscito, è ho perso la pasienza, vedo comunque che hai ripreso... e meno male direi... sorry for all.. (scusa se non mi sono più fatto sentire per alcuni giorni, studio/lavoro e altro mi impegnano tantissimo)

Matteo

Scusate il mio pessimo Italiano scritto, sono Australiano, (si coi nonni Italiani e Tedeschi), ma ci provo lo stesso a scrivere in Italiano :shy:
miglia da percorrere, prima di dormire
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Puntatori a Funzione[C]

Messaggio da gila75 »

Ciao Matteovid...felice di risentirti :)
Purtroppo il C è un linguaggio che ad ogni manuale e per i primi capitoli sembra facile, poi alle funzioni e ai pointer ci si ferma (nel corso sul linguaggio C, siamo stati fermi sulle funzioni e pointer per 1 anno), ma perchè non si sa come mai non funziona
Ecco, è quello che cercavo di far capire: se all'università, ci si ferma così tanto tempo, e hai i professori, i compagni di corso (dove non arriva uno, arriva l'altro), in più 5 anni precedenti
magari di scuola tecnica...figurati le difficoltà che incontro io: neofita, nessuna scuola precedente, da solo (tranne il prezioso aiuto di tutti voi), si e no una o due ora al giorno
dopo il lavoro, quindi stanco...somma tutto e bingo.
Tutto quello che dici, debugger, flusso del programma ecc..sacrosante parole, ma chi ha il tempo purtroppo?
La mia idea era d'iniziare a studiare il C, diciamo il grosso, e poi approfondire...tanto non sarà mai la mia professione (purtroppo), non si può iniziare a 39 anni da zero :)
Pure i geni dell'informatica (e io non sono un genio), hanno iniziato a smanettare in giovane età: Stallman, Wozniak,ecc.
Ma come dici tu, all'inizio, printf, for ecc, tutto è semplice, poi viene il bello.
Sul libro, intendo dire che bhò...forse pretendo troppo io essendo un testo introduttivo.
Le liste per esempio le trattava solo semplici, non circolari, non doppiamente concatenate. Passaggi a funzione ? Nisba, tutto dichiarato fuori dal main e tutto richiamato con funzioni
void ().
A sto punto, forse avrei dovuto dire, ok, so le liste, perchè il manuale quello mi proponeva, ma aveva senso?
Anche sui puntatori a funzione, stando all'esempio proposto dal libro, li saprei, ma li so davvero? Ho dimestichezza? Colgo i pregi e le potenzialità? NO!
Ho scritto il puntatore a funzione che punta a sin (seno, incluso in <math.h>) e ho fatto un programma, non so se l'hai visto.
Funziona, tutto ok, ma appena le cose si complicano, devo riflettere e spendere molto tempo.
Per questo che i miei 3d sono sempre molto lunghi, e so che non tutti apprezzano...ma in fondo segue solo chi vuole.
Grazie per l'esempio :)
Sono andato anche a rifare esercizi coi puntatori, e se hai notato ho proposto nuovamente un programma dove secondo me serviva il puntatore a puntatore,
ma come vedi ho sbagliato nuovamente...o meglio era superfluo.
Altre cose dei puntatori invece credo di averle capite.
Ma il punto, non è capire l'esempio sciocco
int a=10;
int *p=&a;

Fin li ci arriva anche il mio cane...è saper applicare il tutto..e non è facile coi puntatori.
Gila (non ho litigato, quindi pace sarebbe oltremodo un più) scuse sì te ne devo, volevo solo stimolarti, non ci sono riuscito, è ho perso la pasienza, vedo comunque che hai ripreso... e meno male direi... sorry for all.. (scusa se non mi sono più fatto sentire per alcuni giorni, studio/lavoro e altro mi impegnano tantissimo)
Dai..non è successo nulla...forse tu potevi evitare delle cose, e io forse non rispondere così piccato.
Dimentichiamocene no?
Siamo tutti qui per l'interesse e passione di determinate cose, quello conta.
Sapevo che per far scaldare gli animi ci sono: sport,politica e religione...io aggiungo anche la programmazione!!! :D
Ora vado avanti un po' a esercitarmi...magari rimando il risolto, quando avrò capito tutto bene, lo metto.
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Puntatori a Funzione[C]

Messaggio da gila75 »

@vbextreme, finalmente ho "decifrato" il tuo esempio del qsort.
L'ho riadattato a me, cioè ho cercato di capire, non solo copiare il tuo codice, e morta li...
Ho sostituito una funzione int con void, perchè secondo me può non ritornare nulla, visto che la variabile che conta gli scambi è globale.
Ecco la mia versione:

Codice: Seleziona tutto

#include <stdio.h>
#include <stdlib.h>
#define CMP int (*cmp)(const void*,const void*)
#define QUICK void (*quick) (void*,size_t,size_t,CMP)
#define N 15
int n_scambi=0;


void conta (int* v,int n,size_t sz,QUICK,CMP);
int comp (const void * a, const void * b);
void stampa (int *v,int numb_of_array);


void stampa (int *v,int numb_of_array)
{
    int i;
    for (i=0; i<numb_of_array; i++)
        printf ("%d\n", v[i]);
    return ;
}

int comp (const void * a, const void * b)
{   
    ++n_scambi;
    return ( *(int*)a - *(int*)b );  
}


void conta (int*v,int n,size_t sz,QUICK,CMP)
{
    quick(v,n,sz,cmp);  
}



int main (void)
{
    int v[N]={33,21,1,55,555,123,456,2,678,-852,-651,34,11,11,987};
    conta(v,N,sizeof(int),qsort,comp);
    printf ("Numero scambi effettuati %d\n",n_scambi);
    stampa (v,N);    
    return 0;

}
Un esercizio interessante e che mi sto riproponendo di fare è di eliminare n_scambi, che tiene traccia degli scambi totali fatti da qsort.
La suddetta variabile è globale e io vorrei passarla dalla funzione nel main.
Per far ciò, credo vada aggiunto un parametro a CMP (e altro ancora logicamente...era solo per far capire)

Codice: Seleziona tutto

#define CMP int (*cmp)(const void*,const void*,INT*)
in maiuscolo la presunta modifica.
Ogni volta che viene fatta la funzione di comparazione, la variabile aumenta.
Non posso ritornare dalla funzione cmp perchè il risultato serve alla quick sort:

Codice: Seleziona tutto

return ( *(int*)a - *(int*)b );  
Ma se io passo dal main la variabile, per indirizzo, le modifiche fatte nella funzione, me le ritrovo pure nel main...
Ho provato a modificare un po' di cose, ma per ora non funziona.
Non vorrei che aggiungendo

Codice: Seleziona tutto

#define CMP int (*cmp)(const void*,const void*,INT*)
Si possa andare in conflitto col prototipo di qsort, visto che qui:

Codice: Seleziona tutto

#define QUICK void (*quick) (void*,size_t,size_t,CMP)
includo CMP che ora conterrà un parametro in più.
Avatar utente
vbextreme
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1214
Iscrizione: domenica 12 gennaio 2014, 14:06
Desktop: lxde
Distribuzione: xubuntu 14.10

Re: Puntatori a Funzione[C]

Messaggio da vbextreme »

Codice: Seleziona tutto

non sono d'accordo sul manuale
Il manuale è molto importante,e va scelto in base alle proprie conoscenze.
Io ho studiato il c solo sul K&R ma venivo da anni di programmazione e mi è bastato(per le basi ovvio).Consigliare però a un "neofita" della programmazione la bibbia è assurdo! è un libro che necessita di avere basi profonde e consolidate sulla programmazione.
Tali considerazioni vanno fatte su tutti i manuali, aggiungendo che non tutti sono scritti bene, bisogna poi trovare il manuale fatto per noi!
Invece per quanto mi riguarda sarebbe molto importante...
Per affrontare lo studio del c io preferisco insegnare cosi:
0) Leggere tutto il manuale senza scrivere nemmeno una riga di codice.
1) Scaricare un Ide che permetta di compilare senza tanti problemi qualsiasi esercizio trovato su un libro.
2) Tornare a leggere il manuale e limitarsi a riscrivere gli esempi.
3) Tornare a leggere il manuale e svolgere solo gli esercizi che siamo in grado di fare
4) Tornare a leggere il manuale e cercare di svolgere gli esercizi che non siamo stati in grado di fare
5) Anche se non abbiamo chiari alcuni passaggi del c iniziare con qualche programmino CHE CI PIACCIA esempio una rubbrica o un piccolo gestore dei consumi carburante o un'agenda,etc,etc,etc...
6) Pian pianino colmeremo le nostre lacune con poca difficoltà
7) A questo punto Inizieremo con lo sviluppo di applicazioni piu complicate e verrà l'obbligo di imparare il debugger
8 ) Scopriremo i flags
9) Siamo pronti a compilare da riga di comando.

C'è chi preferisce partire dalla mia fine ma a mio avviso è piu complicato.Io preferisco sfogare la voglia di imparare il linguaggio,solo in un sucessivo momento, quando la nostra mente si è aperta al c, allora e solo allora approfondire tutto il mondo che lo circonda.
Questa è la mia visione ma non sono il supremo, persone altamente qualificate come M.A.W. intraprenderebbero strade piu lunghe e sicuramente piu redditizie ma molto probabilmente rivolte ad un corso universitario piu che allo studio autodidattico del C.Ovvero si partirebbe prima su cose ben lontane dal c e si arriberebbe a imparare il c conoscendolo già perchè si conoscerebbe già l'architettura che l'ha creato(Esistono miglioni di post dove spiega benissimo come imparare il c ,con che manuali e che strada intraprendere.)
Come vedi esistono molte strade e ognuno deve percorrere la sua con le sue esigenze.

Codice: Seleziona tutto

Ho sostituito una funzione int con void, perchè secondo me può non ritornare nulla, visto che la variabile che conta gli scambi è globale.
L'ho messa per intraprendere una strada.
Nel secondo codice postato,dove si usa un vettore di puntatori a funzione serve!
Vorrei che ti togliessi un pò questo tabu sui parametri globali.
Per il momento evita queste sottigliezze che a volte sono anche errate.Cerca di imparare il linguaggio un pò piu grossolanamente.
Es:
Io me ne sono sempre fregato che la gets fosse deprecata, io l'ho sempre usata.Adesso che ho un pò di conoscenza,uso la mia con_gets.
Easy framework per il linguaggio C.
vbextreme hack your life
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Puntatori a Funzione[C]

Messaggio da gila75 »

L'ho messa per intraprendere una strada.
Nel secondo codice postato,dove si usa un vettore di puntatori a funzione serve!
Vorrei che ti togliessi un pò questo tabu sui parametri globali.
Per il momento evita queste sottigliezze che a volte sono anche errate.Cerca di imparare il linguaggio un pò piu grossolanamente.
Es:
Io me ne sono sempre fregato che la gets fosse deprecata, io l'ho sempre usata.Adesso che ho un pò di conoscenza,uso la mia con_gets.
Ok, anche io sono del tuo parere (anche se il mio conta poco in virtù della poca esperienza), le variabili globali, saranno "pericolose", ma con un po' di accortezza....
Non capisco perchè siano così deprecate, idem per scanf, gets ecc...logico devi sapere bene quello che fai.
.Cerca di imparare il linguaggio un pò piu grossolanamente.
Ci proverò...ma come detto nel post prima, scrivere una funzione o programma e capirlo si e no, forse è peggio che non capire del tutto.
Ora,per esempio, un po' di prove coi puntatori a funzione le ho fatte, e nel corso di tutto questo 3d, ho capito un po' di cose, e ho anche capito che avevo/ho lacune su cose già studiate.
Ora andrò avanti, coi vettori di puntatori a funzione.
Lascio aperta la discussione, ma la ritengo conclusa, mi avete davvero aiutato, grazie a tutti e soprattutto della pazienza :)
Se qualcuno ha qualcosa da aggiungere....
P.S.: il K&R è davvero impossibile per un neofita. Io ce l'ho, ma ho lasciato perdere...magari mi verrà buono più avanti.
Ciao e grazie a tutti :)

EDIT:
il -g nelle opzioni del compilatore serve proprio per avere i dati per il debugger nell'eseguibile...
Mi puoi dare più informazioni per favore? Avevo già sentito, ma magari se mi posti un esempio, su come si usa ecc...
Magari nel frattempo guardo in rete
Grazie nel caso :)
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Puntatori a Funzione[C]

Messaggio da gila75 »

Domanda lampo, sempre inerente (più o meno al 3d).
é possibile con quick sort ordinare un vettore di stringhe?

Codice: Seleziona tutto

char stringa [5][10]={"ciao","pippo","cane","Zio","marco"};
So che funziona con le strutture, array di numeri, ma in questo caso non so se funziona...forse si deve ricorrere solo alla strcmp?
è un caso un po' particolare l'array di stringhe...sono più vettori, mentre il qsort (per esempio un array di int) opera sullo stesso array, no?
Come sempre grazie :H)
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Puntatori a Funzione[C]

Messaggio da gila75 »

Ho risolto, fa nulla...ho pensato una stupidata, si può fare....ma io sbagliavo delle cose..
Avatar utente
matteovid
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 368
Iscrizione: mercoledì 9 dicembre 2009, 9:09
Desktop: Openbox, XFCE, XMonad
Distribuzione: GNU/Linux Arch - openSUSE Leap
Sesso: Maschile
Località: Parma

Re: Puntatori a Funzione[C]

Messaggio da matteovid »

gila75 [url=http://forum.ubuntu-it.org/viewtopic.php?p=4561807#p4561807][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto: Mi puoi dare più informazioni per favore? Avevo già sentito, ma magari se mi posti un esempio, su come si usa ecc...
Magari nel frattempo guardo in rete
Grazie nel caso :)
Ciao Gila

per avere un minimo di aiuto dal gdb il deugger GNU
basta che metti da terminale

Codice: Seleziona tutto

ulimit -c 90000
e verifichi con

Codice: Seleziona tutto

ulimit -a
nel mio caso

Codice: Seleziona tutto

$ ulimit -a
core file size          (blocks, -c) 90000
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7835
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7835
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
poi ti metto un programmino con un errore

Codice: Seleziona tutto

#include <stdio.h>

void fun1 (void);


int main (int argc, char **argv)
{
  fun1 ();
  /* se non si usano i parametri con nomeprogramma parametri
   * e non ricevere warning con il parametro :
   * -pedantic
   */
  (void) argc;
  (void) argv;

  return (0);
}

void fun1 (void)
{
    char *cp = 0;

    *cp = 'k'; /* qui vi è un problema */
}
poi conpilo da terminale con

Codice: Seleziona tutto

$ gcc -W -pedantic -Wall -g -o myerror myerror.c
il terminale mi risponde con

Codice: Seleziona tutto

$ ./myerror 
Errore di segmentazione (core dump creato)


verifico se ho il core

Codice: Seleziona tutto

$ ls core
lancio il gdb da terminale con

Codice: Seleziona tutto

$ gdb ./myerror core
il gdb mi risponde con

Codice: Seleziona tutto

gdb ./myerror core
GNU gdb (GDB) 7.5-ubuntu
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/matteo/languageC/myerror/myerror...done.

warning: exec file is newer than core file.
[New LWP 3357]

warning: Can't read pathname for load map: Errore di input/output.
Core was generated by `./myerror'.
Program terminated with signal 11, Segmentation fault.
#0  0x080483fe in fun1 () at myerror.c:23
31	    *cp = 'k'; /* qui vi è un problema */
(gdb) 
poi dò il comando da terminale

Codice: Seleziona tutto

(gdb) where
#0  0x080483fe in fun1 () at myerror.c:23
#1  0x080483e7 in main (argc=1, argv=0xbfb99384) at myerror.c:8
(gdb) 
come noterai il gdb di dà la linea con l'errore, 23 del listato, con where viene mostrato lo stack al momento dell'errore, la chiamata al main, qui alla linea 8 e la linea 23 dove vi è l'errore, per uscire dal gdb

Codice: Seleziona tutto

(gdb) quit
questo è solo un esempio, ma se fai man gdb da terminale oppure info gdb sempre da terminale hai un aiuto in linea che dà molte informazioni... si esce dal man e/o info premendo q...
Ti consiglio di non sottovalutare il man e info di GNU/Linux, è il tuo amico sia man che info, quindi impara ad usarli...

come nel comando ulimit, appena esci dal terminale i limiti di ulimit tornano quelli di default, cioè non creano nessun core file, studiati come avere sempre il core file di default.... se vuoi sapere come e dove vi sono errori o warning nei programmi, ma i comandi del gdb sono infiniti, basta che li studi....

Matteo
miglia da percorrere, prima di dormire
gila75
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 2739
Iscrizione: mercoledì 16 gennaio 2013, 17:28
Desktop: ubuntu-2d
Distribuzione: Ubuntu 12.04.2 LTS i686
Località: Airuno(Lecco)

Re: Puntatori a Funzione[C]

Messaggio da gila75 »

Grazie Matteo,proverò...ora sono impegnato ad "ammazzarmi" con esercizi di strutture,unioni, funzioni, puntatori, puntatori a funzione ecc...quick sort abbinato a strutture ecc..
Ho deciso di soffermarmi parecchio, credo che siano l'essenza del C.
Appena penso di aver capito bene, mi si apre un altro dubbio...e ricomincio daccapo.
é come una scatola cinese il C: risolvendo un dubbio e una perplessità, se ne svelano automaticamente altre.
Comunque davvero, credo che gli argomenti elencati sopra siano davvero i fondamenti (e le cose più complesse del C)
Tutti capaci a fare un ciclo for o un if ... :D
Scappo al lavoro, buona giornata a tutti :)
Avatar utente
matteovid
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 368
Iscrizione: mercoledì 9 dicembre 2009, 9:09
Desktop: Openbox, XFCE, XMonad
Distribuzione: GNU/Linux Arch - openSUSE Leap
Sesso: Maschile
Località: Parma

Re: Puntatori a Funzione[C]

Messaggio da matteovid »

Ciao vbextreme

sono d'accordo su quello che dici, sia nello studio del C che di ogni altra materia....
però sul manuale non tanto, il K e R è essenziale come dici e anzi non capisco perchè in tanti non lo studiano....
un buon manuale è essenziale come dici, ma se uno comincia nel dire ho un manuale difficile o non alla altezza o ddirittura banale, secondo me è un errore, si dà un alibi per non avere capito un certo argomento... è come dire sempre colpa degli altri...

basterebbe essere modesti, cercare di capire, nessuni nasce genio, basta applicarsi, cercare informazioni
e in questo GNU/Linux è illuminante, vi è il man e info da consulatre, ma nessuno vi dà importanza....

Come in un post Gila dice che la scanf che dà problemi, ma stiamo scherzando?
in tanti qui dicono che scanf è inutile e si danno interpretazioni errate, esempi banali....

ma la scanf ha anche un argomento di ritorno, che sarebbe int

infatti la definizione di scanf è

Codice: Seleziona tutto

int scanf(const char *format, ...);
ma se nessuno usa il ritorno della scanf, cosa si vuole che non funziona? invece qui in questo forum si dà consigli come evitare la scanf, certo in certi input e interazione con l'utente vi sono dei comandi migliori, ma secondo me basterebbe spiegare i difetti della scanf, non dire che dà problemi e che non si deve usare, non dette da te vbExtreme... Anzi ti seguo con interesse

Scusa Gila se metto un tua dichiarazione in un post... non vuole essere una critica anzi uno spunto di discussione

@ Gila
lascia perdere per ora la qsort, insisti sulle funzioni e sui puntatori, ma questo è un mio consiglio, conta niente, per carità...
Quando dicevo che nel corso di C dell'Univ. che seguo siamo rimasti un anno su funzioni e puntatori, è perchè abbiamo studiato tanti compilatori, tante cpu, dal Z80 al pentium, dai 4 bit ai 64 bit, da 1 Kb di memoria a 1 Tb di memoria e via andare, e studiato tanti di quei sorgenti dai più banali a quelli scritti da esperti, come poi tutti i sorgenti del Kernel Linux e tantissimi programmi GNU, anche quelli che si interfacciano all'hardware... questo non per dire che sono esperto, per carità... ma per dirti che bisogna studiare, anche solo per hobby, in un certo metodo.... detto da prof a cui credo...
Poi certo vi è il tempo e altro...

Matteo
miglia da percorrere, prima di dormire
Avatar utente
matteovid
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 368
Iscrizione: mercoledì 9 dicembre 2009, 9:09
Desktop: Openbox, XFCE, XMonad
Distribuzione: GNU/Linux Arch - openSUSE Leap
Sesso: Maschile
Località: Parma

Re: Puntatori a Funzione[C]

Messaggio da matteovid »

ciao Gila

ti metto un listato, se vuoi provalo....

Codice: Seleziona tutto

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXSTRINGHE 80

/* per stampare array di stringhe */
int perGila (char **, size_t);
/* funzione per il confronto array stringhe per la qsort della libreria */
int ast_confronto (const void *, const void *);

int main (int argc, char **argv)
{
  /* dichiaro astringa come array a stringhe, e le inizializzo
   * senza dichiarare quante
   */
  char *astringa[] = { "Gila", "Tex", "Alex", "Anne Marie", "Verbose", "Earth Quake" };

  /* size_t è un alias per unsigned int
   * definita in <stddef.h> <stdio.h> <stdlib.h> <string.h> <time.h> <wchar.h>
  */
  /* calcolo indice array astring */
  size_t stringa_lun = sizeof(astringa) / sizeof(char *);
  size_t ciclo = 0;

  /* se non si usano i parametri con nomeprogramma parametri
   * e non ricevere warning con il parametro :
   * -pedantic
   * Gila: questa per ora non ti interessa...
   */
  (void) argc;
  (void) argv;
  /* fine avvertimento per non usare argc e argv con -pedantic */

  printf ("indici componenti astringa %d\n", stringa_lun);

  ciclo = perGila (astringa, stringa_lun);

  printf ("cicli ritornati dalla funzione perGila (char **, size_t): %u\n", ciclo);

  /* chaimo la qsort per ordinare array a stringa */

  qsort(astringa, stringa_lun, sizeof(char *), ast_confronto);

  /* chiamo la perGila per stampare in ordine array stringa */
  ciclo = perGila (astringa, stringa_lun);

  printf ("cicli ritornati dalla funzione perGila (char **, size_t) dopo l'ordinato: %u\n", ciclo);

  return (0);
}

int perGila (char **as, size_t l)
{
  size_t ciclo = 0;

  for (ciclo = 0; ciclo < l; ciclo++)
    printf ("[%u] %s\n", ciclo, as[ciclo]);

   return (ciclo);
}

int ast_confronto (const void *a, const void *b)
{
    const char **ia = (const char **)a;
    const char **ib = (const char **)b;
    return strcmp(*ia, *ib);
}
secondo te che errori ci sono, se ve ne sono...
se vi sono errori o argomenti che secondo te possono essere gravare o rendere migliore il codice....
se possibile fai tu un esempio di dove migliorare questo esempio....
la costante MAXSTRINGHE bisogna usarla? puoi gentilmente spiegare come

Matteo
miglia da percorrere, prima di dormire
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 2 ospiti