Newsgroup: it.comp.lang.c
Titolo: Scrivere e leggere variabili da file

Salve,
vorrei gestire i valori delle mie variabili all'interno di un file, tipo
file di configurazione.
Avete degli esempi di come poter gestire la cosa?
Grazie mille.

Sauro Sgatti wrote:

Il formato sara' ASCII o binario? ... Le cose cambiano e di parecchio.
C:\>iao Angelo
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it


Non puoi semplicemente utilizzare dei file sequenziali (fopen() e
compagnia)?
EMG
--
EMAG Software Homepage:     
http://www.emagsoftware.it
The EMG's ZX-Spectrum Page: 
http://www.emagsoftware.it/spectrum
The Best of Spectrum Games: 
http://www.emagsoftware.it/tbosg


In formato ASCII, l'idea è di gestire i file generali di configurazione tipo
Apache, Samba etc, in modo da fare
un menu' con la possibilita' di gestire le variabili comuni di
configurazione tipo Hostname, ip address, etc..
Però non sò come gestire questi file, ovvero trovare all'interno del file
determnate variabili.
Avete un'idea?

 determnate variabili.
cosa c'e' che trovi difficile ? Spiegati !
A me sembra banale (al limite noioso, ma non difficile)
il file e' un insieme di righe.
Quindi leggi e tratti una riga per volta (puoi leggere una riga
alla volta con fgets)
data la riga devi decidere quale sintassi utilizzare.
per esempio puoi decidere che vuoi usare il carattere iniziale #
per identificare le righe di commento e
usare la sintassi
VARIABILE = VALORE
allora quando leggi il file
(ti conviene leggerlo tutto all'inizio e non ogni volta
che ti serve una variabile)
scandisci ogni riga.
Se il carattere iniziale e' # allora la scarti.
altrimenti cerchi il simbolo = e quello ti
divide in due la stringa.
Eliminando dai due pezzi i blank (e fine linea) in eccesso hai due
stringhe, per esempio:
da
XY =   331
ottieni le due stringhe "XY" e "331" e le memorizzi
in una opportuna struttura.
dopo di che sta a te decidere come trattare le variabili.
(dipende se sono poche, tante, numeriche o alfanumeriche,
etc.etc.).
Dopo, per esempio
le puoi mettere in ordine alfabetico per nome della variabile
e poi reperirle con una ricerca binaria (se sono poche basta la
scansione lineare...)
e convertirle subito tutte nella loro versione interna, tipo
int xy;
xy = atoi(CercaVar(Vars, "XY"));
dove CercaVar(char *s) cerca la stringa associata (nella struttura dati
Vars che avrai predisposto) alla variabile "XY", cioe "331" e poi
lo converte in numero.
tipicamente una entry di Vars potrebbe essere composta da due
puntatori a stringa, il nome della variabile e il contenuto della
variabile.
etc.etc.
ciao,
g.

 alla volta con fgets)
A leggere il tuo post sembra facile, quasi quasi ti spedisco i miei
sorgenti e ti chiedo di farmi una parte del lavoro :-)
In ogni caso alcune delle affermazioni che hai fatto non sono proprio
corrette. Il fatto che il carattere '#' sia l'inizio di un commento e'
una pura convenzione (il VB usa ';' come inizio di commento), cosi'
come lo e' il carattere '=' per dividere la variabile dal valore.
Inoltre le cose si complicano non poco (te lo garantisco) se il valore
puo' essere composto da piu' parti (es. il nome) e se tra queste parti
puo' esserci piu' di uno spazio. Oppure se tra separatore, variabile e
valore puo' non esserci lo spazio (es. VARIABILE=VALORE) o puo' esserci
piu' di uno spazio (es. VARIABILE       =VALORE).
In ogni caso io preferisco leggere tutto il file.


 piu' di uno spazio (es. VARIABILE       =VALORE).
Guarda che le cose si semplificano non poco (te lo garantisco) con
un approccio razionale e i blank non danno nessun fastidio.
Per esempio, (e' un esempio di come farei io, non una legge di natura)
stabiliamo che (blank a parte) ci siano 2 possibili sintassi
VAR = VALORE
e
VAR = "VALORE"
per consentire delle cose come
PIPPO = "  CIAO "
con blank iniziali e finali, mentre supponiamo che le virgolette in
NOME = "Giovanni Resta"
siano inutili, nel senso che i blank "in mezzo" siano mantenuti comunque.
Allora supponiamo sia data una stringa char *linea restituita da
fgets (e supponiamo che tu abbia gia' eliminato il newline in fondo a s).
(controlla sul tuo sistema/compilatore esattamente cosa restituisce
fgets)
allora, intanto scriviamo una funzione che elimina i caratteri
blank davanti e dietro una stringa: (non e' proprio
che sia la versione piu' efficiente, ma sto improvvisando).
void Trimmalo(char *s)
{
   char *p, buf[250]; // suppongo che 250 sia la lunghezza max
   p=s; // punto a inizio stringa
   while (*p == ' ') p++; // avanzo per eliminare i blank
   strcpy(buf,p); // copio in buf;
   p=buf+strlen(buf)-1; // p punta all'ultimo carattere di buf
   while (p>=buf && *p==' ') // torno indietro cancellando i blank
      {*p=0; p--;}
   strcpy(s,buf);  // ricopio nella stringa originaria
}
Allora adesso supponiamo di avere due
variabili per tenere nome variabile e valore
char var[80], val[200];
e la linea letta char *linea;
supponiamo io abbia gia' controllato che non sia un commento,
allora cerco il carattere '=':
char *p;
p=strchr(linea,'=');
if (p==NULL) {printf("Mannaggia! una linea senza l'uguale!\n");
               fai_qualcosa();}
// ora p punta all'= dentro linea;
allora, metto un bel 0 al posto dell'=
*p = 0;
cosi' posso copiare il primo pezzo della linea dentro var,
strcpy(var,linea);
e il secondo dentro val
strcpy(val,p+1);
a questo punto li "trimmo"
per eliminare eventuali blank iniziali e finali
Trimmalo(val); Trimmalo(var);
ora considero la possibilita'
che il valore sia incluso tra doppi apici,
nel qual caso li elimino:
if (val[0]='\"' && val[strlen(val)-1]=='\"')
{
   strcpy(temp,val+1); strcpy(val,temp);
   val[strlen(val)-1]=0;
}
(dove temp e' un array di char di lunghezza opportuna)
ora ho in var la variabile e in val il valore con tutti
e soli i blank che ho voluto metterci, cioe' quelli compresi
tra due parole o quelli compresi tra gli apici.
non e' stato difficile,
(non ho compilato i pezzettini di codice, quindi non prenderli
per oro colato, ma l'idea dovrei averla resa).
ciao,
g.

 come lo e' il carattere '=' per dividere la variabile dal valore.
A parte il fatto che il VB usa l'apice per i commenti, non il punto e
virgola, che c'è di male ad adottare delle convenzioni come il
cancelletto e l'uguale?


 cancelletto e l'uguale?
Nessuna, volevo solo evidenziare che la scelta di un separatore e' solo
una convenzione.
Per inciso, nell'ultimo parser che ho realizzato, avevo deciso di usare
il carattere ':'. Poi ho preferito cambiare, visto che ':' viene (anche)
usato come separatore nei MAC address delle schede di rete.
Ho scelto '=' sperando di avere meno casini.
Happy parsing!


 > > come lo e' il carattere '=' per dividere la variabile dal valore.
Grazie a tutti per le risposte provero' a scriverlo.
Mi sembra che sul K&R ci sia qualcosa che possa aiutarmi, avete anche dei
siti dove prendere spunti?

 siti dove prendere spunti?
Se proprio non vuoi dire in pubblico quali sono i tuoi problemi con
i file di configurazione, scrivi alla mia m-box :-)
