|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Jun 2003
Messaggi: 893
|
[Linguaggio C] Non so come fare!!!
Ciao a tutti,
ho sviluppato una libreria per reti neurali interamente in C. Ora mi sono imbattuto in un problema: Ho la mia bella libreria con i suoi header ed i suoi main; Però potrebbe capitare che qualcuno voglia estendere questa libreria, aggiungendo funzionalità, ossia codice in file .c. Come posso gestire le funzioni di un file.c aggiunto successivamente? Grazie |
![]() |
![]() |
![]() |
#2 | |
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Poi comunque se la libreria può essere (facilmente o meno) estendibile dipende esclusivamente da come è fatta. Una libreria in puro C non è detto che sia estendibile ... non siamo in C++ o Java dove si possono ereditare classi ed estenderle. Insomma ... il design deve essere tale da permettere facilmente l'aggiunta di nuove funzionalità.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
![]() |
![]() |
![]() |
#3 |
Senior Member
Iscritto dal: Jun 2003
Messaggi: 893
|
Ciao andbin,
hai perfettamente ragione..!!! non si capisce una mazza! ![]() I main li ho creati io per richiamare alcune funzioni di libreria (contenute nei .h). Allora, supponiamo che io abbia un header contenente alcune funzioni di utilità. Questo header viene quindi incluso ogni qualvolta sia utile. Ora supponiamo che qualcuno dall'esterno voglia utilizzare una nuova funzione di utilità da lui stesso implementata. Allora, dovrebbe scrivere un file con estensione .c (o .h) con all'interno il codice desiderato e poi? Come la faccio riconoscere alle altre funzioni della libreria? E' più chiaro orA? ![]() ![]() ![]() |
![]() |
![]() |
![]() |
#4 | |||
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Quote:
Quote:
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|||
![]() |
![]() |
![]() |
#5 | |
Senior Member
Iscritto dal: Jun 2003
Messaggi: 893
|
Quote:
![]() Ok..quindi solo prototipi e strutture Quindi in un file .h c'è il prototipo della funzione..e dove metto il suo corpo? in un file con lo stesso nome ma con estensione .c? Quindi dovrò includere anche quello nel mio main? es: #include prova.h //file dei prototipi #include prova.c // file dell'implementazione giusto? Ultima modifica di sonique : 25-09-2007 alle 09:39. |
|
![]() |
![]() |
![]() |
#6 | |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 1792
|
Quote:
Non hai un buon libro sul linguaggio C a portata di mano? ![]() |
|
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Jun 2003
Messaggi: 893
|
ah ok ok....
Si pippo.....posso procurarmelo..era solo per velocizzare le operazioni!!! ![]() In effetti dopo una stesura iniziale del progetto, volevo organizzare tutto per comandi: ossia: da linea di comando digitare: > funzione parametro1 parametro2.... In tal caso come potrei fare? Ultima modifica di sonique : 25-09-2007 alle 09:58. |
![]() |
![]() |
![]() |
#8 | |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 1792
|
Quote:
![]() |
|
![]() |
![]() |
![]() |
#9 |
Senior Member
Iscritto dal: Jun 2003
Messaggi: 893
|
Hai perfettamente ragione...e di più...
Però, lo scopo principale non è tanto "un buon sviluppo di codice che sia anche pulito ed efficientissimo" ma è lo sviluppo di un package per reti neurali. Purtroppo in tal caso, quando i tempi sono molto corti, ci si trova un pò ad arraffare ogni tipo di informazioni senza necessariamente dover passare per la teoria sottostante il linguaggio stesso. Ma comunque non appena finirò questa rogna, io passerò direttamente ad uno studio approfondito del linguaggio stesso, e forse direttamente a JAVA. |
![]() |
![]() |
![]() |
#10 | |
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Ok, meglio forse fare un esempio: si vuole realizzare una libreria (piccola, giusto di esempio) che analizza un array di interi e fornisce al chiamante le informazioni sul valore minore e maggiore presente nell'array. Si realizza un file di header, chiamiamolo arrstat.h che contiene: Codice:
#ifndef _ARRSTAT_H_ #define _ARRSTAT_H_ typedef struct { int min; int max; } ARRSTAT; int array_stat (int*, int, ARRSTAT*); #endif Codice:
#include "arrstat.h" int array_stat (int *arr, int arrlen, ARRSTAT *parrstat) { int i; if (arrlen < 1) return 0; parrstat->min = parrstat->max = arr[0]; for (i = 0; i < arrlen; i++) { if (arr[i] < parrstat->min) parrstat->min = arr[i]; if (arr[i] > parrstat->max) parrstat->max = arr[i]; } return 1; } A chi vuole solamente usare la libreria (senza voler indagare nei suoi sorgenti), basta fornire 2 file: il file di header arrstat.h e la libreria statica arrstat.lib. Se si vuole usare quindi la libreria innanzitutto bisogna mettere i due file da qualche parte e istruire il compilatore/linker affinché trovi questi due file (come farlo, dipende dal compilatore/ambiente, chiaramente). Volendo realizzare una applicazione si può quindi poi creare un progetto per una applicazione con un sorgente .c chiamiamolo provastat.c che contiene: Codice:
#include <stdio.h> #include <arrstat.h> int main (void) { int a[8] = { 4, 6, 3, 9, 14, 7, 4, 2 }; ARRSTAT as; array_stat (a, 8, &as); printf ("min = %d\n", as.min); printf ("max = %d\n", as.max); return 0; } Il progetto della applicazione dovrà anche fare il link con il file arrstat.lib e anche in questo caso il linker deve essere istruito sul path dove può trovare il file .lib. Più chiaro adesso? Non dirmi di no ti prego. ![]()
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Jun 2003
Messaggi: 893
|
Ti dico invece: si è chiaro..e vi ringrazio entrambi!!!!
La mia difficoltà stava nel fatto che avessi organizzato ogni funzione (tipo la funzione di training (training.c) della rete, oppure la funzione di feed forward (feed_for.c)) come file main() in quanto passavo ad essi degli argomenti, quindi: main (int argc, char *argv[]). Invece, giustamente come dite voi, io dovrei predisporre questi file .h e .c fondamentalmente, e poi un certo tizio interessato scrive un main ed include il mio header. Penso che la gestione da linea di comando sia più complessa..giusto? |
![]() |
![]() |
![]() |
#12 | ||
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Quote:
No, questa tua domanda è posta male. Non è più complessa .... è sbagliata concettualmente per quello che volevi fare.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||
![]() |
![]() |
![]() |
#13 |
Senior Member
Iscritto dal: Jun 2003
Messaggi: 893
|
ok andbin,
Quindi tornando al tuo consiglio; che ne dici se creo semplicemente .h e .c e poi chi ha interessa pensa ad includerli? O dovrei impacchettare tutto ?(perche non ho un solo .h ovviamente) |
![]() |
![]() |
![]() |
#14 | ||
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Tu potresti anche dare ad altri direttamente i file .c/.h e ci pensano poi loro a crearsi una libreria o addirittura ad inserirli direttamente in un loro progetto. Quote:
Insomma ... dipende.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Jun 2003
Messaggi: 893
|
..a questo punto...sarebbe utile fornire solo la libreria compilata senza altro
|
![]() |
![]() |
![]() |
#16 |
Senior Member
Iscritto dal: Jun 2003
Messaggi: 893
|
andbin saresti così gentile da darmi qualche riferimento su come creare una libreria ( uso pad c++)
|
![]() |
![]() |
![]() |
#17 |
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Che è?? Non lo conosco.
Il compilatore quale è?
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
![]() |
![]() |
![]() |
#18 |
Senior Member
Iscritto dal: Jun 2003
Messaggi: 893
|
Ciao andbin,
scusami ma ho dettato per cellulare il messaggio alla mia ragazza. ![]() Grazie |
![]() |
![]() |
![]() |
#19 |
Senior Member
Iscritto dal: Jun 2003
Messaggi: 893
|
Ciao Andbin,
ho seguito il tuo consiglio: Ossia, ho creato un file di intestazione .h ed il corrispondente file dell'implementazione .c, ma nulla da fare. Ho creato un banalissimo main di prova, ma quando provo ad utilizzare una funzione mi da errore del linker: undefinided reference. Ora ti posto il codice: Header struttura.h Codice:
//Header file contenente la definizione delle strutture dati per //rappresentare e gestire una rete neurale feed-forward, e le //operazioni utili ai fini della lettura da file e della inizializzazione //di tali strutture. //La lettura di una rete neurale avviene da file .net, compatibile //con lo standard Stuttgart JNNS. #ifndef _STRUTTURA_H_ #define _STRUTTURA_H_ struct node{ int funzione_act; //Tipo di funzione di attivazione int funzione_out; //Tipo di funzione di output float valore_in; //Valore di input float valore; //Valore di output float soglia; //Valore del bias }; typedef struct node info_nodo; typedef struct { char nome[30]; int N; //Numero totale dei nodi della rete float *w; //Vettore dei pesi int nodi_input;//Numero nodi di input int nodi_out; //Numero nodi di output info_nodo *nodo; } rete_neurale; ////////////////////////////////////////////////////// //Data una stringa ne estrae un numero convertendolo in float float estract_float(char *, int); //Restituisce il prossimo carattere speciale | int next_only_tab(char *, int); //Restituisce il prossimo carattere speciale '|' ':' o ',' int next_tab(char *, int); //Estrae il prossimo carattere valido void estract_str(char *, int , char *); //Lagge dal file .net il tipo di algoritmo di apprendimento void read_learning(FILE *, char *); //Lagge dal file .net il tipo di algoritmo di aggiornamento void read_update(FILE *, char *); //Legge dal file .net il nome della rete void read_nome(FILE *, char *); //Legge la configurazione della rete void read_unit(FILE *, rete_neurale, int *, int *, int *); //Inizializza la struttura ai valori di default void init(rete_neurale ,int ,int,int,char *,char *); //Legge i pesi e le connessioni presenti nella rete void read_weigth(FILE *, rete_neurale , int , int , int ); //Legge dal file .net i parametri di default della rete void read_def(FILE *, float *, float *, char *, char *, char *); rete_neurale leggiretefile (char *); //Lagge dal file .net il numero di nodi della rete int read_units(FILE *); //Legge dal file .net il numero di connessioni della rete int read_conness(FILE *); //Controlla la fine di un rigo non delimitato da alcun carattere speciale int contr_fine(char *, int); //Calcola i valori di uscita dei nodi, dati gli ingressi rete_neurale calcola_feed_forward (rete_neurale); #endif Codice:
#include "struttura.h" #include <string.h> float estract_float(char *buf, int index) //Data una stringa ne estrae un numero convertendolo in float { int i, j=0; float num; char stringa[15]; i=index+1; while ((buf[i]!='|')&&(buf[i]!=':') && (buf[i]!=',')) { if (buf[i]!=' ') { stringa[j]=buf[i]; j++; } i++; } stringa[j]='\0'; num=atof(stringa); return num; } int next_only_tab(char *buf, int index) //Restituisce il prossimo carattere speciale | { index++; while (buf[index]!='|') index++; return index; } int next_tab(char *buf, int index) //Restituisce il prossimo carattere speciale '|' ':' o ',' { index++; while ((buf[index]!='|') && (buf[index]!=':') && (buf[index]!=',')) index++; return index; } char estract_c(char *buf, int index) //Estrae il prossimo carattere valido { char car; int i; i=index+1; while (buf[i]!='|') { if (buf[i]!=' ') { car=buf[i]; break; } i++; } return car; } void read_learning(FILE *fd, char *learning) //Lagge dal file .net il tipo di algoritmo di apprendimento { char stringa[25]; fscanf(fd,"%s",stringa); while (1) { if (strcmp(stringa,"learning")==0) { fscanf(fd,"%s",stringa); if (strcmp(stringa,"function")==0) { fscanf(fd,"%s",stringa); fscanf(fd,"%s",stringa); strcpy(learning,stringa); break; } } fscanf(fd,"%s",stringa); } } void read_update(FILE *fd, char *update) //Lagge dal file .net il tipo di algoritmo di aggiornamento { char stringa[25]; fscanf(fd,"%s",stringa); while (1) { if (strcmp(stringa,"update")==0) { fscanf(fd,"%s",stringa); if (strcmp(stringa,"function")==0) { fscanf(fd,"%s",stringa); fscanf(fd,"%s",stringa); strcpy(update,stringa); break; } } fscanf(fd,"%s",stringa); } } //Legge dal file .net il nome della rete void read_nome(FILE *fd, char *nome) { char stringa[25]; fscanf(fd,"%s",stringa); while (1) { if (strcmp(stringa,"network")==0) { fscanf(fd,"%s",stringa); if (strcmp(stringa,"name")==0) { fscanf(fd,"%s",stringa); fscanf(fd,"%s",stringa); strcpy(nome,stringa); break; } } fscanf(fd,"%s",stringa); } } void read_unit(FILE *fd, rete_neurale rete, int *in, int *hi, int *out) //Legge la configurazione della rete { char *res, buf[200]; int index, num_input=0, num_hidden=0, num_output=0; int i, act_d=0, out_d=0, actv_d=0, outv_d=0, type_d=0; char nome[20], act_str[20], out_str[20], type; float act, bias; fscanf(fd,"%s",buf); while (strcmp(buf,"sites")!=0) fscanf(fd,"%s\n",buf); fscanf(fd,"%s\n",buf);//Legge il rigo dei tab for (index=1; index<=rete.N;index++) { act_d=0; out_d=0; actv_d=0; outv_d=0; type_d=0; res=fgets(buf,200,fd);//Legge un rigo intero if( res==NULL ) exit(1); i=next_tab(buf,0);//Salta di due tab in avanti i=next_tab(buf,i); estract_str(buf,i,nome);//Estrae il nome del nodo i=next_tab(buf,i); if (buf[i+1]=='|') actv_d=1; //Caso funzione di default else{ rete.nodo[index].valore_in=estract_float(buf,i);//Estrae il valore di attivazione rete.nodo[index].valore=rete.nodo[index].valore_in; } i=next_tab(buf,i); if (buf[i+1]=='|') outv_d=1; //Caso funzione di default else rete.nodo[index].soglia=estract_float(buf,i);//Estrae il valore del bias i=next_tab(buf,i); if (buf[i+1]=='|') type_d=1; //Caso funzione di default else type=estract_c(buf,i);//Estrae il tipo del nodo i=next_tab(buf,i);//Salta di due tab in avanti i=next_only_tab(buf,i); if (buf[i+1]=='|') act_d=1; //Caso funzione di default else estract_str(buf,i,act_str);//Estrae la funzione di attiv. i=next_tab(buf,i); if (buf[i+1]=='|') out_d=1; //Caso funzione di default else estract_str(buf,i,out_str);//Estrae la funzione di output if (type=='i') num_input++; if (type=='h') num_hidden++; if (type=='o') num_output++; if (act_d==0) rete.nodo[index].funzione_act=str2int(act_str); if (out_d==0) rete.nodo[index].funzione_out=str2int(out_str); } *in= num_input; *hi= num_hidden; *out= num_output; } void init(rete_neurale rete,int act_d,int bias_d,int tipo_d,char *act_fun_d,char *out_fun_d) //Inizializza la struttura ai valori di default { int i, j, d, act, out, N; N=rete.N+1; act=str2int(act_fun_d); out=str2int(out_fun_d); for (i=1; i<=rete.N; i++) { rete.nodo[i].soglia=bias_d; rete.nodo[i].valore_in=act_d; rete.nodo[i].valore=act_d; rete.nodo[i].funzione_act=act; rete.nodo[i].funzione_out=out; } //Inizializzazione vettore dei pesi for(j=0;j<=rete.N;j++) { for(d=0;d<=rete.N;d++) rete.w[j*N+d]=-bias_d; } } void read_weigth(FILE *fd, rete_neurale rete, int in, int hi, int out) //Legge i pesi e le connessioni presenti nella rete { char buf[200], *res; int N, num, index, i=0, j=0, numero_nodi=0 ,max, flag=0; float peso; max=in; N=rete.N+1; fscanf(fd,"%s",buf); while (strcmp(buf,"source:weight")!=0) fscanf(fd,"%s\n",buf); fscanf(fd,"%s\n",buf);//Legge il rigo dei tab res=fgets(buf,200,fd);//Legge un rigo intero if( res==NULL ) exit(1); //Per tutti i nodi non di input for (j=in+1;j<=in+hi+out;j++){ index=(int)estract_float(buf,-1);//Estrae l'indice del nodo ricevente i=next_tab(buf,0);//Salta due tab i=next_tab(buf,i); numero_nodi=0;//Inizializzazione flag=0; if (j==in+hi+1) max=hi; while (flag==0){ while ((buf[i+2]!='\0')&& (flag==0)) { num=(int)estract_float(buf,i);//Estrae l'indice del nodo collegato numero_nodi++; i=next_tab(buf,i);//Salta i due punti peso=estract_float(buf,i); if (numero_nodi<max) i=next_tab(buf,i);//Salta la virgola else flag=1; //Inserisce l'indice del nodo afferente ed il peso rete.w[index*N+num]=peso; } i=0; res=fgets(buf,200,fd);//Legge un rigo intero if( res==NULL ) break; //printf("%s\n",buf); } } } void read_def(FILE *fd, float *act_d, float *bias_d, char *tipo_d, char *act_fun_d, char *out_fun_d) //Legge dal file .net i parametri di default della rete { char stringa[25], *res, buf[200]; char car; float layer, subnet; int index; fscanf(fd,"%s",stringa); while (strcmp(stringa,"out")!=0) fscanf(fd,"%s",stringa); fscanf(fd,"%s\n",stringa); if (strcmp(stringa,"func")==0) fscanf(fd,"%s\n",buf);//Legge una riga intera res=fgets(buf,200,fd); if( res==NULL ) exit(1); *act_d=estract_float(buf,-1); index=next_tab(buf,0);//aggiorna il nuovo indice di tabulazione *bias_d=estract_float(buf,index); index=next_tab(buf,index); *tipo_d=estract_c(buf,index); index=next_tab(buf,index); subnet=estract_float(buf,index); index=next_tab(buf,index); layer=estract_float(buf,index); index=next_tab(buf,index); estract_str(buf,index,act_fun_d); index=next_tab(buf,index); estract_str(buf,index,out_fun_d); } rete_neurale leggiretefile (char *nomefile) { char nome[30]; char *delim; char *last; char check[30]; int N, conness, in, hi, out; int i, j, d; float act_d, bias_d; char tipo_d, act_fun_d[25], out_fun_d[25], learning[25], update[25]; FILE *fd; int conta=0; int num_afferenti=0; rete_neurale rete; // Controlla che l'estensione del file sia .net strcpy(check, nomefile); delim = strtok(check, "."); while (delim != NULL){ last = delim; delim = strtok(NULL, "."); } if(strcmp(last, "net") != 0){ printf("\nWarning: Stai aprendo un file con estensione diversa da .net\n"); getch(); } //---------------------------------------------- END CHECK fd=fopen(nomefile,"r"); if(fd == NULL){ printf("\nImpossibile aprire il file %s \n\n",nomefile); system("pause"); exit(0); } //Lettura del nome della rete read_nome(fd,nome); strcpy(rete.nome,nome); //Lettura del numero totale di nodi rete.N=read_units(fd); N=rete.N+1; //Lettura del numero di connessioni conness=read_conness(fd); //Lettura del tipo di apprendimento e dell'ordine di aggiornamento read_learning(fd,learning); read_update(fd,update); //Lettura dei valori di default read_def(fd,&act_d,&bias_d,&tipo_d,act_fun_d,out_fun_d); //Inizializzazione alla dimensione letta rete.w=(float *)malloc(N*N*sizeof(float)); rete.nodo=(info_nodo *)malloc(N*sizeof(info_nodo)); //Inizializzazione delle strutture init(rete,act_d,bias_d,tipo_d,act_fun_d,out_fun_d); //Per tutti i nodi di input read_unit(fd,rete,&in,&hi,&out); //Aggiornamento del numero di nodi input e output nella rete rete.nodi_input=in; rete.nodi_out=out; //Aggiorna i valori dei pesi ai bias for(i=1;i<=rete.N;i++) rete.w[i*N]=-rete.nodo[i].soglia; //Inserisce il valore dei pesi nelle connessioni read_weigth(fd,rete,in,hi,out); fclose(fd); return(rete); } int read_units(FILE *fd) //Lagge dal file .net il numero di nodi della rete { char stringa[25]; int units=0; fscanf(fd,"%s",stringa); while (1) { if (strcmp(stringa,"no.")==0) { fscanf(fd,"%s",stringa); if (strcmp(stringa,"of")==0) { fscanf(fd,"%s",stringa); if (strcmp(stringa,"units")==0) { fscanf(fd,"%s",stringa); fscanf(fd,"%d",&units); break; } } } fscanf(fd,"%s",stringa); } return units; } int read_conness(FILE *fd) //Legge dal file .net il numero di connessioni della rete { char stringa[25]; int conness=0; fscanf(fd,"%s",stringa); while (1) { if (strcmp(stringa,"no.")==0) { fscanf(fd,"%s",stringa); if (strcmp(stringa,"of")==0) { fscanf(fd,"%s",stringa); if (strcmp(stringa,"connections")==0) { fscanf(fd,"%s",stringa); fscanf(fd,"%d",&conness); break; } } } fscanf(fd,"%s",stringa); } return conness; } int contr_fine(char *buf, int index) //Controlla la fine di un rigo non delimitato da alcun carattere speciale { int i; i=index; while (buf[i]!='\0') i++; if (buf[i-1]==',') return 1; else return 0; } rete_neurale calcola_feed_forward (rete_neurale rete) //Calcola i valori di uscita dei nodi, dati gli ingressi { int N=rete.N+1; int i,j,s,k; //Per tutti i nodi di input Calcola il valore di uscita //tramite la funzione teta di attivazione for (j=1; j<=rete.nodi_input; j++) { // rete.nodo[j].valore_in=rete.nodo[j].valore_in-rete.nodo[j].soglia; rete.nodo[j].valore=teta(rete.nodo[j].valore_in,rete.nodo[j].funzione_out); } //Per tutti i nodi Hidden for(k=rete.nodi_input+1;k<=rete.N-rete.nodi_out;k++) { rete.nodo[k].valore_in=rete.nodo[k].soglia; //Per tutti i nodi di input for (i=1;i<=rete.nodi_input;i++) rete.nodo[k].valore_in+=rete.nodo[i].valore*rete.w[k*N+i]; rete.nodo[k].valore=teta(rete.nodo[k].valore_in,rete.nodo[k].funzione_act); } //Per tutti i nodi di output for(k=rete.N-rete.nodi_out+1;k<=rete.N;k++) { rete.nodo[k].valore_in=rete.nodo[k].soglia; //Per tutti i nodi Hidden for (i=rete.nodi_input+1;i<=rete.N-rete.nodi_out;i++) rete.nodo[k].valore_in+=rete.nodo[i].valore*rete.w[k*N+i]; rete.nodo[k].valore=teta(rete.nodo[k].valore_in,rete.nodo[k].funzione_act); } return rete; } Codice:
#include <stdio.h> #include "struttura.h" main() { char buf[] = "ciao pirla;"; int ind; printf("\n\nProva utilizzo libreria:\n\n"); ind = next_tab(buf, 0); return 0; } |
![]() |
![]() |
![]() |
#20 |
Senior Member
Iscritto dal: Jul 2006
Messaggi: 1568
|
Mi intrometto nella discussione.
![]() Domanda: perchè è sconsigliato implementare le funzioni direttamente nel file .h? |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 22:52.