Entra

View Full Version : [Linguaggio C] Non so come fare!!!


sonique
24-09-2007, 22:15
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

andbin
25-09-2007, 08:24
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?Scusa se lo dico ma non è assolutamente chiaro. Innanzitutto se hai creato una libreria non vedo cosa ti serva metterci delle funzioni main, a meno che con la libreria tu rilasci delle applicazioni/tools di prova o di esempio che ne fanno uso (che però tecnicamente non farebbero parte della libreria).

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à.

sonique
25-09-2007, 08:38
Ciao andbin,
hai perfettamente ragione..!!! non si capisce una mazza! :D

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? :muro: :confused: :rolleyes:

andbin
25-09-2007, 09:14
I main li ho creati io per richiamare alcune funzioni di libreria (contenute nei .h).Cioè .. fammi capire: hai scritto i corpi delle funzioni in file .h?? No, non si fa così!

Allora, supponiamo che io abbia un header contenente alcune funzioni di utilità.Ripeto: i file di header non devono contenere fisicamente le funzioni ma semmai (al massimo) i prototipi delle funzioni (più qualunque altra dichiarazione di macro, strutture, ecc... che possano servire). La implementazione vera e propria delle funzioni va fatta esclusivamente nei sorgenti .c/.cpp.

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?Cioè??? Continui a non essere chiaro e personalmente posso solo dedurre che non ti è molto chiaro come strutturare i file sorgenti e di header.

sonique
25-09-2007, 09:37
Cioè??? Continui a non essere chiaro e personalmente posso solo dedurre che non ti è molto chiaro come strutturare i file sorgenti e di header. Straquoto :(

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?

variabilepippo
25-09-2007, 09:49
giusto?


No, in pippo.H inserisci prototipi ed eventuali strutture, nel relativo pippo.C implementi le funzioni ed in main.C includi solo pippo.H.

Non hai un buon libro sul linguaggio C a portata di mano? :rolleyes:

sonique
25-09-2007, 09:56
ah ok ok....

Si pippo.....posso procurarmelo..era solo per velocizzare le operazioni!!!:D

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?

variabilepippo
25-09-2007, 10:00
Si pippo.....posso procurarmelo..era solo per velocizzare le operazioni!!!

Io non riuscirei a progettare e successivamente realizzare una libreria senza avere le basi di un dato linguaggio, studiare su un libro PRIMA di scrivere il codice serve proprio per "velocizzare le operazioni". ;)

sonique
25-09-2007, 10:04
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.

andbin
25-09-2007, 10:07
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?La risposta secca è: NO

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:
#ifndef _ARRSTAT_H_
#define _ARRSTAT_H_

typedef struct
{
int min;
int max;
} ARRSTAT;

int array_stat (int*, int, ARRSTAT*);

#endif

Si realizza poi la implementazione delle funzioni (qui è solo una) in uno o più sorgenti .c (anche qui basta solo uno), chiamiamolo arrstat.c che contiene:
#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;
}

Con il tuo compilatore/ambiente di sviluppo scegli il tipo di progetto appropriato per realizzare, ad esempio, una libreria statica (perché si potrebbe anche realizzare una libreria dinamica). Dopo la fase di build del progetto, avrai un file .lib, chiamiamolo ad esempio arrstat.lib

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:
#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;
}
Notare che ho incluso <arrstat.h> e non "arrstat.h". Questo presuppone che il compilatore/ambiente sia stato opportunamente configurato in modo da specificare il path di include della libreria.
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. ;)

sonique
25-09-2007, 10:14
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?

andbin
25-09-2007, 10:27
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[]).E poi cosa ci facevi? Non ha molto senso .... anzi non ne ha proprio!

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.Se fai una libreria devi dare la possibilità di poterla linkare insieme a del codice fatto da altri. E questo lo puoi fare solo se fornisci la libreria nei formati appropriati per essere usati da un compilatore/ambiente di sviluppo (lo stesso che hai usato tu o magari anche un altro).

Penso che la gestione da linea di comando sia più complessa..giusto?No, questa tua domanda è posta male. Non è più complessa .... è sbagliata concettualmente per quello che volevi fare.

sonique
25-09-2007, 12:19
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)

andbin
25-09-2007, 12:30
Quindi tornando al tuo consiglio; che ne dici se creo semplicemente .h e .c e poi chi ha interessa pensa ad includerli?Ma scusa ... hai letto bene il mio esempio completo sopra?
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.

O dovrei impacchettare tutto ?(perche non ho un solo .h ovviamente)Non lo so ... dipende da cosa vuoi fornire. Intendo se vuoi fornire i sorgenti, solo la libreria compilata e gli include o altro.

Insomma ... dipende.

sonique
25-09-2007, 12:39
..a questo punto...sarebbe utile fornire solo la libreria compilata senza altro

sonique
25-09-2007, 13:38
andbin saresti così gentile da darmi qualche riferimento su come creare una libreria ( uso pad c++)

andbin
25-09-2007, 13:49
( uso pad c++)Che è?? Non lo conosco.
Il compilatore quale è?

sonique
25-09-2007, 17:31
Ciao andbin,
scusami ma ho dettato per cellulare il messaggio alla mia ragazza. :p Ovviamente pad c++ diventa dev c ++

Grazie

sonique
27-09-2007, 11:14
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

//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


funzione struttura.c

#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;
}





funzione di prova

#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;
}


Pensando fosse un problema del dev, ho provato ad aggiungere il percorso contenente il mio progetto negli include del compilatore (sostituendo "struttura.h" con <struttura.h>) ma nulla da fare!!!

nico88desmo
27-09-2007, 14:16
Mi intrometto nella discussione. :D
Domanda: perchè è sconsigliato implementare le funzioni direttamente nel file .h?

andbin
27-09-2007, 14:26
Domanda: perchè è sconsigliato implementare le funzioni direttamente nel file .h?Nei file di header non si dovrebbero fare definizioni di variabili o funzioni. Il motivo è semplice: cosa succederebbe se 2 sorgenti che appartengono allo stesso progetto (quindi compilati e poi linkati insieme) includessero un header che definisce una variabile o funzione?? Succederebbe che quel poveraccio del linker non saprebbe cosa fare con due moduli che contengono simboli con nomi uguali.

nico88desmo
27-09-2007, 14:28
Un'altra domanda.


#ifndef _STRUTTURA_H_
#define _STRUTTURA_H_


A cosa serve l'underscore prima del nome della libreria nel file .h?
Guardando in alcuni file .h ci sono addirittura due underscore


#ifndef __glu_h__
#define __glu_h__

andbin
27-09-2007, 14:47
A cosa serve l'underscore prima del nome della libreria nel file .h?Dal punto di vista puramente pratico, mettere FILE_H oppure _FILE_H_ oppure __FILE_H__ o in qualunque altro modo, sarebbe del tutto indifferente. È chiaro che la macro deve essere scelta in modo che sia "ragionevolmente" univoca.
Però mi sembra di ricordare che gli identificatori che iniziano con 1 underscore siano "riservati" alla libreria standard/compilatore. Quindi sarebbe preferibile la prima o la terza forma.

nico88desmo
27-09-2007, 14:52
Dal punto di vista puramente pratico, mettere FILE_H oppure _FILE_H_ oppure __FILE_H__ o in qualunque altro modo, sarebbe del tutto indifferente. È chiaro che la macro deve essere scelta in modo che sia "ragionevolmente" univoca.
Però mi sembra di ricordare che gli identificatori che iniziano con 1 underscore siano "riservati" alla libreria standard/compilatore. Quindi sarebbe preferibile la prima o la terza forma.

Trovato il motivo . :D

In un programma C, tutti gli identificatori con linkaggio esterno devono essere preceduti dal carattere '_' (underscore); il carattere underscore è associato al codice ASCII 95.
I compilatori C aggiungono automaticamente l'underscore all'inizio di ogni identificatore con linkaggio esterno presente nei vari moduli C di un programma; per non generare confusione, nei moduli C è consigliabile quindi evitare l'uso di nomi preceduti dall'underscore.

andbin
27-09-2007, 15:20
In un programma C, tutti gli identificatori con linkaggio esterno devono essere preceduti dal carattere '_' (underscore)Questo lo sapevo ma secondo me c'entra solo relativamente con la questione delle macro per evitare la inclusione multipla.
Quello che dici tu ha anche e sopratutto a che fare con le convenzioni di chiamata.

nico88desmo
27-09-2007, 15:35
Questo lo sapevo ma secondo me c'entra solo relativamente con la questione delle macro per evitare la inclusione multipla.
Quello che dici tu ha anche e sopratutto a che fare con le convenzioni di chiamata.

Esatto, è proprio questo che intendevo io :)

nico88desmo
27-09-2007, 15:41
Per curiosità ho provato a fare anche io una libreria.
Questo è l'esempio:

file lib.h
#ifndef __lib_h_
#define __lib_h_

struct numero {

char *nome;
unsigned int valore;

};

typedef struct numero numero;


// assegna il nome del numero e il valore
void ins_nomval (numero *, char *, unsigned int);

#endif


file lib.c

void ins_nomval (numero *n, char *nome, unsigned int val) {

unsigned int lstr;

lstr = strlen(nome);

n->nome = (char *) malloc (sizeof(char)*lstr);
strcpy(n->nome, nome);
n->valore = val;
}


file usolib.c

#include <stdio.h>
#include "lib.h"

#define MAX 10

numero vet_num[MAX];

int main (int argc, char **args) {

unsigned int num;
char c;

c = (char) args[2][0];
num = (unsigned int) c-0x30;
ins_nomval(&(vet_num[0]), args[1], num);
}


Ora come faccio a compilare in modo che "veda" la libreria?
Come compilatore utilizzo GCC

andbin
27-09-2007, 16:02
Ora come faccio a compilare in modo che "veda" la libreria?
Come compilatore utilizzo GCCNota che dovresti includere lib.h pure in lib.c

Comunque per la compilazione dipende se vuoi creare una libreria statica o dinamica.
Nel primo caso (statica) fai:

gcc -c -o lib.o lib.c
ar r lib.a lib.o

per creare la libreria lib.a

Poi:

gcc -c -o usolib.o usolib.c
gcc -o usolib usolib.o lib.a

e ottieni un eseguibile usolib

nico88desmo
27-09-2007, 16:41
Nota che dovresti includere lib.h pure in lib.c

Comunque per la compilazione dipende se vuoi creare una libreria statica o dinamica.
Nel primo caso (statica) fai:

gcc -c -o lib.o lib.c
ar r lib.a lib.o

per creare la libreria lib.a

Poi:

gcc -c -o usolib.o usolib.c
gcc -o usolib usolib.o lib.a

e ottieni un eseguibile usolib

Grazie :D