Lectura de formatos de archivo personalizados en C++
Leo archivos de configuración del siguiente formato en mi código C++:
<h1>name score</h1>
Marc 19.7
Alex 3.0
Julia 21.2
Hasta ahora, he adaptado una solución encontrada aquí: https://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c. Por ejemplo, el siguiente fragmento de código lee el archivo línea por línea y, para cada línea, llama a parseDictionaryLine
, que descarta la primera línea, divide la cadena como se describe en el hilo original e inserta los valores en una tabla hash (implementada por mí).
void parseDictionaryLine(std::string &line, std::string &delimiter, hash<table> &table) {
size_t position = 0;
std::string name;
float score;
while((position = line.find(delimiter)) != std::string::npos) {
name = line.substr(0, position);
line.erase(0, position + delimiter.length());
score = stof(line);
table.hinsert(name, score);
}
}
void loadDictionary(const std::string &path, hash</table><table> &table) {
std::string line;
std::ifstream fin(path);
std::string delimiter = " ";
int lineNumber = 0;
if(fin.is_open()) {
while(getline(fin, line)) {
if(lineNumber++ < 1) {
continue; // first line
}
parseDictionaryLine(line, delimiter, table);
}
fin.close();
}
else {
std::cerr << "Unable to open file." << std::endl;
}
}
Mi pregunta sería, ¿hay una forma más elegante en C++ para lograr esta tarea? En particular, ¿hay (1) una mejor función de split
como por ejemplo en Python, (2) un mejor método para probar si una línea es una línea de comentario (comienza con #), como startsWith
? (3) ¿potencialmente incluso un iterador que maneje archivos de manera similar a un gestor de contexto en Python y se asegure de que el archivo realmente se cerrará? Mi solución funciona para casos simples mostrados aquí, pero se vuelve más engorrosa con variaciones más complicadas, como varias líneas de comentarios en posiciones impredecibles y más parámetros. Además, me preocupa que mi solución no verifique si el archivo realmente cumple con el formato prescrito (dos valores por línea, el primero es una cadena, el segundo es un número decimal). Implementar estas verificaciones con mi método parece muy complicado.
Entiendo que existen JSON y otros formatos de archivo con bibliotecas creadas para este caso de uso, pero estoy trabajando con código heredado y no puedo utilizarlos.
davy.ai
Como modelo de lenguaje de IA, te sugiero lo siguiente:
boost::split
de la biblioteca incluyendoEste código dividiría la cadena
line
en tokens, donde cada token está separado por la cadena delimitadora.string::find
para verificar si una línea comienza con un carácter específico o una subcadena. Por ejemplo, podrías utilizar el siguiente código para comprobar si una línea empieza con ‘#’:Este código verificaría si el primer carácter de la línea es ‘#’. Si lo es, entonces la línea sería considerada como un comentario.
Este código abriría el archivo “nombrearchivo.txt” para lectura, leería su contenido línea por línea y cerraría el archivo cuando termine.
En cuanto a las variaciones complejas del archivo de entrada, te sugiero implementar alguna verificación de errores dentro de la función
parseDictionaryLine
, como verificar que la línea tenga dos valores con los tipos de datos correctos. Además, agregar códigos de error o excepciones puede ayudar a identificar el tipo de error que ocurre en el archivo de entrada.