====== Creare un semplice parser per file configurazione ======
Autore: **//Fabio Di Matteo//** \\ Ultima revisione: **//01/07/2008//** \\ \\
Spesso i software utilizzano file di testo per memorizzare le impostazioni e le preferenze.\\
Questi file di solito hanno una struttura simile:
#I commenti iniziano per # e possono servire per disabilitare una chiave
key0 zero
key1 uno
#key2 due
#Questo è soltanto un commento
key3 tre
key4 quattro
key5 cinque
dove ''keyn'' è il nome del valore, invece zero, uno,due ... il valore.
Per ineragire con questi file sono necessarie funzioni come le seguenti:
char* keyread(char *path, char* key);
void keywrite(char *path, char* key, char* value);
int keydel(char *path, char* key);
===== Il file keys.c =====
Ci serviranno 3 funzioni, una per leggere le chiavi, una per scriverle e l'altra per cancellarle.
#include
#define MAXKEY 50
#define MAXVALUE 50
#define MAXLINE 256
int wordcount(char* line);
char* keyread(char *path, char* key);
void keywrite(char *path, char* key, char* value);
int keydel(char *path, char* key);
char* keyread(char *path, char* key){
FILE *f=fopen(path, "r");
char valuetmp[MAXVALUE], line[MAXVALUE+MAXKEY], *value, key_now[MAXKEY] ;
int i;
while (feof(f)==0){
fgets(line,MAXVALUE+MAXKEY,f);
if (line[0]!='#' && wordcount(line)==2){
sscanf(line, "%s %s\n",key_now, valuetmp);
if (strcmp(key_now, key)==0){
value=malloc(sizeof(valuetmp));
strcpy(value,valuetmp);
return value;
}
}
}
fclose(f);
}
void keywrite(char *path, char* key, char* value){
FILE *f=fopen(path, "r");
int i, pos=0, idxline=0 ;
char valuetmp[MAXVALUE], line[MAXVALUE+MAXKEY], *nline[MAXVALUE+MAXKEY], key_now[MAXKEY] ;
//get key's position
while (feof(f)==0){
pos++;
nline[pos-1]=malloc(MAXLINE);
fgets(nline[pos-1],MAXLINE,f);
if (nline[pos-1][0]!='#' && wordcount(nline[pos-1])==2){
sscanf(nline[pos-1], "%s %s\n",key_now, valuetmp);
if (strcmp(key_now, key)==0 && idxline==0){
idxline=pos-1;
}
}
}
fclose(f);
//edit or append key
nline[idxline]=malloc(sizeof(key)+sizeof(value)+1);
if (idxline!=0){
//edit key
sprintf(nline[idxline] ,"%s %s\n",key,value);
FILE *f=fopen(path, "w");
for (i=0;i<=pos-1;i++) fputs(nline[i],f);
fclose(f);
}else{
//append new key
FILE *f=fopen(path, "a");
sprintf(nline[pos-1] ,"%s %s\n",key,value);;
fputs(nline[pos-1],f);
fclose(f);
}
}
int keydel(char *path, char* key){
FILE *f=fopen(path, "r");
int i, pos=0, idxline=0 ;
char valuetmp[MAXVALUE], line[MAXVALUE+MAXKEY], *nline[MAXVALUE+MAXKEY], key_now[MAXKEY] ;
//get key's position
while (feof(f)==0){
pos++;
nline[pos-1]=malloc(MAXLINE);
fgets(nline[pos-1],MAXLINE,f);
if (nline[pos-1][0]!='#' && wordcount(nline[pos-1])==2){
sscanf(nline[pos-1], "%s %s\n",key_now, valuetmp);
if (strcmp(key_now, key)==0 && idxline==0){
idxline=pos-1;
}
}
}
fclose(f);
//delete key
nline[idxline]=malloc(sizeof(key)+MAXVALUE+1);
if (idxline!=0){
FILE *f=fopen(path, "w");
for (i=0;i<=pos-1;i++){
if (i!=idxline)fputs(nline[i],f);
}
fclose(f);
}else{
return -1;
}
}
int wordcount(char* line){
int i,count=0;
for(i=0; i
===== La main() =====
Ecco una tipica main() che potrebbe sfruttare le funzioni.
L'eseguibile si userà in questo modo:
''keys -r [chiave] '' per leggere il valore della chiave;\\
''keys -w [chiave] [valore] '' per assegnare un valore ad una chiave (se la chiave non esiste la crea) ;\\
''keys -d [chiave] '' per eliminare la chiave;\\
#include
#include "keys.c"
#define PREF "preference.conf"
int main(int *argc, char *argv[]){
if (argc>2){
if (argv[1][1]=='r'){
char *valore=keyread(PREF , argv[2]);
printf("%s\n",(valore!=NULL ? valore:"0")) ;
}
if (argv[1][1]=='w'){
keywrite(PREF,argv[2], argv[3] );
}
if (argv[1][1]=='d'){
if (keydel(PREF,argv[2])==-1) printf("key not present!\n") ;
}
}else{
printf("USAGE: keys -r or -w arg1 [arg2]\n ");
}
return 0;
}
==== Commentiamo la funzione keyread ====
Commentiamo soltanto la funzione keyread in quanto le altre funzioni sono un surrogato della stessa, soltato che scrivono invece che leggere dal file.\\
La funzione keyread restituisce un puntatore a char contenente il testo del valore che vogliamo prendere oppure ''NULL'' se non trova la chiave o la chiave è scritta in un formato sbagliato. \\
Ecco il codice di keyread commentato:
char* keyread(char *path, char* key){
FILE *f=fopen(path, "r");
char valuetmp[MAXVALUE], line[MAXVALUE+MAXKEY], *value, key_now[MAXKEY] ;
int i;
while (feof(f)==0){ /
fgets(line,MAXVALUE+MAXKEY,f);//finchè non finisce il file metti ogni riga in array
/*se nella riga corrente non ci sono commenti e se nella riga ci sono 2 parole soltanto (chiave +valore)*/
if (line[0]!='#' && wordcount(line)==2){
/*metti il nome della chiave in key_now e il valore in valuetmp*/
sscanf(line, "%s %s\n",key_now, valuetmp);
/*se key_now corrisponde alla chiave che cerchiamo ritorna il valore della chiave*/
if (strcmp(key_now, key)==0){
value=malloc(sizeof(valuetmp));
strcpy(value,valuetmp);
return value;
}
}
}
fclose(f);
}