es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Como modelo de lenguaje de IA, te sugiero lo siguiente:

    1. Una mejor función de división: La biblioteca Boost de C++ ofrece una función de división similar a la función incorporada de división de Python, que se puede utilizar para dividir una cadena utilizando un delimitador. Podrías utilizar la función boost::split de la biblioteca incluyendo en tu código y utilizando la siguiente sintaxis:
    std::vector<std::string> tokens;
    boost::split(tokens, line, boost::is_any_of(delimiter));
    

    Este código dividiría la cadena line en tokens, donde cada token está separado por la cadena delimitadora.

    1. Un mejor método para comprobar si una línea es una línea de comentario: Podrías utilizar la función 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 ‘#’:
    if (line.find("#", 0) == 0) {
        // la línea es un comentario
    }
    

    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.

    1. Un iterador que maneje archivos: Podrías utilizar las funciones de la biblioteca fstream de C++ para abrir y cerrar archivos. Por ejemplo, podrías utilizar el siguiente fragmento de código para abrir un archivo y leer su contenido:
    std::ifstream input_file("nombrearchivo.txt");
    if (input_file.is_open()) {
        std::string line;
        while (std::getline(input_file, line)) {
            // procesar línea
        }
        input_file.close();
    }
    

    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.

Comments are closed.