[Duda C++] Leer fichero saltando los comentarios

Estoy haciendo un programa y para cargar determinados datos he creado un fichero de configuración (al estilo de los *.ini) donde guardo varios datos generales del programa.

Como quiero que la lectura del fichero sea lo mas sencilla posible, lo he hecho de la siguiente forma

xxxxxx1: yyyy1
xxxxxx2: yyyy2
...etc.


donde xxxxxx1 es el nombre de la variable que quiero cargar (sin caracteres de separacion como espacios o tabuladores), : son dos puntos y un separador (ahora mismo es un espacio) y yyyy1 es el valor que quiero leer. así se quedaría algo como:

variable1: 1.002
variable2: 3.141592
...etc.


El problema es que ahora me planteo añadir comentarios de una línea al estilo de:

# esto es un comentario de una linea
variable1: 1.002
# aqui viene la segunda variable
variable2: 3.141592
#fin del fichero


Y no se me ocurre una forma elegante de hacerlo. La idea que tenía en mente es leer el primer caracter de la línea: si es '#' hacer un getline, y si no leer un string (que sería el nombre de la variable) y despues la variable que me interese. El problema es tengo variables de distintos tipos, por lo que no puedo hacer un bucle para leerlas, y la otra solucion que se me ocurre es añadir una comprobación de comentarios para cada variable que lea.

Para aclarar esto último, la lectura ahora mismo la tengo así:

file>>trash;
file>>program_version;
file>>trash;
file>>build_time;
file>>build_date;
file>>trash;
file>>msg_final_mark;


Si las variables build_time y program_version son int y string respectivamente no podría hacer algo como

string variable[1000]; i=0;
while(!eof){
comprobar_comentarios();
file>>variable[i];
i++;


Ya que leería el int (o cualquier tipo de dato) como un string. A unas malas, con atoi y similares puedo hacer un apaño, pero si se os ocurre una solución más elegante, que seguro que las hay os lo agradezco.

PD: También he barajado usar un xml, pero para lo que lo voy a necesitar sería matar moscas a cañonazos...
No se muy bien lo que estas intentando hacer, pero seguramente no te interese leer todo de golpe, en ese caso, seguramente tendrias que montarte alguna manera de saber el tipo que estas guardando, y montarte alguna estructura de datos para guardarlo todo.

Si lo que estas intentando leer es algo como un fichero de configuración, es posible que te interese mas leer una por una todas las variables.
Tu ya sabes de que tipo son, asi que los tipos no son un problema, ademas, seguramente lo puedas montar en alguna estructura para ir consultando los datos.

Ahora mismo no tengo en la cabeza que podrias usar, pero por ejemplo, si quieres leer la variable xxxx, buscas en el fichero el patrón xxxx: y a continuación lees el valor, de esta manera ya no tienes el problema de los comentarios y seguramente tienes un sistema mas robusto que en lo que estabas pensando.
Piensa que como lo estas haciendo, si te meten 2 lineas de comentario, o una variable mas en medio, ya no te funcionaria nada

Ya nos diras como consigues solucionar el problema

Un saludo
Lo más fácil es que cada variable sea un objeto de una clase (según su tipo) y tengas un método virtual que sea capaz de construir un objeto de esa clase a partir de un std::ifstream. Con un poco de cuidado y un std::set o un std::map (según lo que necesites) es bastante fácil de hacer.

Saludos.
Ferdy escribió:Lo más fácil es que cada variable sea un objeto de una clase (según su tipo) y tengas un método virtual que sea capaz de construir un objeto de esa clase a partir de un std::ifstream. Con un poco de cuidado y un std::set o un std::map (según lo que necesites) es bastante fácil de hacer.

Saludos.


Mucho mejor, la verdad, en realidad creo que es mas o menos lo que propongo, pero bien hecho

PD: ya te echaba yo de menos por aqui ;)
A ver si lo he entendido, sería crear una clase general para todas las variables que quiera leer del fichero de configuracion y hacer un constructor parametrizado que reciba como argumento una cadena con el nombre de la variable, de manera que la busque en el fichero de configuración y le asigne el valor que lea de ahi no?

Me gusta, muchas gracias a ambos, mañana me pondré a ello a ver que consigo.

Supongo que a la hora de buscar, y teniendo en cuenta que los nombres de las variables estan al principio de cada línea, basta con hacer un getline, asignar la linea a un string y buscar por el nombre de la variable (con el find de la clase string) y cuando lo encuentre saco de ahí la variable, que tengo que pensar una manera sencilla para sacarla, ya que se supone que está en el string que he leído.

Sería entonces algo asi:
class Config{
public:
Config(string name);

//Variables a usar
int a;
float b;
string c;
};

Config(string name){
string aux;

ifstream file("config.txt");
while(!feof){
aux = getline(file);
if(aux.find(name)>string::npos){
//Busco la variable dentro de aux y la asigno al objeto correspondiente
}
}
}


Y a la hora de acceder al objeto a desde cualquier otra clase, bastaría con hacer un #include "config.hpp" y punto. Es eso?

De nuevo gracias por la ayuda :)


EDIT:

Al final he hecho una clase, pero en vez de implementar el metodo virtual, lo he hecho leyendo una vez todo el fichero y construyendome un diccionario, que a su vez he dividido en secciones, claves y valores. Así me evito tener que buscar en el fichero cada vez que necesite leer una variable. La estructura del fichero al final la he hecho exactamente igual que los *.ini de windows: considero que cualquier nombre al principio de linea entre corchetes es una sección, las claves y valores siguen la estructura clave=valor y el resto de líneas se consideran comentarios.

Para leer un valor uso el metodo GetValue(string section, string key) y accedo directamente a traves del arbol, que es mucho más cómodo.

Así que lo dicho, gracias y si alguien quiere el código no tiene más que pedirlo. Saludos.
4 respuestas