Post by Q de quiloBuenas,
a ver si a alguien se le ocurre la opcion mas correcta de hacer lo
-----------------------------
nombre=un nombre cualquiera
loglevel=3
debug=yes
-----------------------------
Si desde un programa C quisieramos leerlo y parsear cada propiedad, que
funciones o que manera de leer el fichero seria la mejor?
En principio se me ocurre leer linea por linea y hacer split con strtok.
Pero quiza no sea la mejor opcion, unido al problema de la deteccion de
final-de-fichero.
Estuve pobrando fscanf("%s=%s") con unos resultados algo desastrosos.
Existe alguna funcion predefinada tipo getopt para estos casos?
Un saludo
Algo parecido es lo que hacen las funciones de windows:
GetPrivateProfileInt()
GetPrivateProfileString()
WritePrivateProfileString()
Por ejemplo, dado un fichero "config.dat" con este formato:
==========================
[Seccion1]
loglevel=1
debug=2
[Seccion2]
loglevel=1
debug=2
===========================
Para obtener el loglevel de Seccion2 harias:
int x= GetPrivateProfileInt( "Seccion2", "loglevel", -1, "config.dat");
Si no estas trabajando en windows, o te interesa crear una aplicacion
portable a otras plataformas, deberas crear tu propia version. Por
ejemplo una version compatible con la funcion GetPrivateProfileInt
podria quedar asi:
/* tamaño maximo de linea en fichero */
#define MAX_LINE_LENGTH 120
/*****************************************************************
int read_line(FILE* fp, char* bp);
fp - puntero a fichero de lectura
bp - puntero a buffer de copia
szbp - tamaño de buffer
Lee una linea de fp dejando un maximo de szbp-1 caracteres en bp
La string dejada en sp siempre termina en '\0'.
Return: 1 OK, 0 en otro caso
******************************************************************/
static int read_line(FILE *fp, char *bp, int szbp)
{
char c = '\0';
int i = 0;
if(!bp || szbp<1 )
return 0;
/* Leer una linea del fichero fuente
* eliminando \n en final de linea
*/
for( i=0; i<szbp-1 && (c = getc(fp)) != '\n'; i++ ) {
if( c == EOF ) /* EOF */
break;
bp[i] = c;
}
bp[i] = '\0';
if( c=='\n' || c==EOF )
return 1;
return 0;
}
/************************************************************************
int getPrivateProfileInt( const char* section, const char* entry,
int def, const char* file_name);
section - nombre de seccion a buscar
entry - entrada a buscar
def - Valor por defecto a devolver en caso de fallo
file_name - el nombre del fichero .ini
Return: Valor localizado para la entrada
*************************************************************************/
int getPrivateProfileInt(const char *asection, const char *aentry,
int adef, const char *afile_name)
{
char buff[MAX_LINE_LENGTH+1];
char *ep;
char section[MAX_LINE_LENGTH+1];
int i;
FILE *fp;
int val;
int len = strlen(entry);
fp = fopen(afile_name,"r");
if( !fp )
return adef;
/* Formatear el nombre de seccion */
strcpy(section, "[");
strncat(section,asection,sizeof(section)-3);
strcat(section,"]");
/* Buscar la seccion */
do {
if( !read_line(fp,buff, sizeof(buff)) ) {
fclose(fp);
return adef;
}
} while( strcmp(buff, section) );
/* Encontrar la entrada dentro de esta seccion */
do {
/* la seccion termina cuando empieza otra seccion */
if( !read_line(fp,buff,sizeof(buff)) || buff[0] == '[' ) {
fclose(fp);
return def;
}
} while( strncmp(buff,aentry,len) );
fclose(fp);
/* Encontrar la string de valor (despues del signo =)*/
ep = strrchr(buff,'=');
if( ep)
ep++;
if( !ep || !strlen(ep) ) /* hay valor asignado ? */
return adef;
/* devolver valor */
if(sscanf( ep, "%d", &val)==1)
return val;
return adef;
}
No he probado el codigo, espero que no este muy mal.
Un saludo,
Martin.