====== 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); }