Estoy tratando de crear un simple archivo de configuración que se parece a esto

url = http://mysite.com
file = main.exe
true = 0

cuando se ejecuta el programa, me gustaría que se carga la configuración de los programas de variables enumeradas a continuación.

string url, file;
bool true_false;

He hecho un poco de investigación y este enlace parecía ayudar (nucleones del post), pero me parece que no puede conseguir que funcione y es demasiado complicado de entender por mi parte. Hay una manera simple de hacer esto? Puedo cargar el archivo con ifstream pero eso es lo más lejos que puedo conseguir en mi propia. Gracias!

  • Boost.program_options viene a la mente, que apoya sin fisuras la transición de argumentos de línea de comandos a un archivo de configuración.
  • He oído mucho sobre el impulso de las bibliotecas. Yo podría darles una oportunidad, pero yo estaba esperando algo simple usando las operaciones de cadena. Yo no tengo planes de hacer cualquier trabajo pesado archivos de configuración.
  • ¿Has considerado la posibilidad de que su archivo de configuración XML, de modo que usted no tiene que escribir un analizador de cadena? A continuación, puede utilizar uno de los innumerables XML bibliotecas que están ahí fuera.
  • Ahora es el tiempo para buscar las bibliotecas de boost – boost.program_options hace exactamente lo que quiere, y lo hace de forma muy sencilla.
  • Vas a aceptar una respuesta?
  • Ha visto usted este? Me pareció muy interesante!

InformationsquelleAutor llk | 2011-07-31

9 Comentarios

  1. 49

    En general, es más fácil analizar los archivos de configuración en dos etapas: en primer lugar, lea las líneas y, a continuación, analizar quienes uno por uno.

    En C++, las líneas se puede leer a partir de una secuencia utilizando std::getline(). Mientras que por defecto se lee hasta el siguiente '\n' (que va a consumir, pero no devolución), puede pasar algún otro delimitador, también, que la convierte en un buen candidato para la lectura-a-algunos-char, como = en su ejemplo.

    De la simplicidad, la siguiente se supone que el = son no rodeado por un espacio en blanco. Si desea permitir que los espacios en blanco en estas posiciones, usted tendrá que colocar estratégicamente is >> std::ws antes de leer el valor y eliminando los espacios en blanco de las teclas. Sin embargo, la OMI la poca flexibilidad en la sintaxis no es la pena la molestia de un archivo de configuración del lector.

    const char config[] = "url=http://example.com\n"
                          "file=main.exe\n"
                          "true=0";
    
    std::istringstream is_file(config);
    
    std::string line;
    while( std::getline(is_file, line) )
    {
      std::istringstream is_line(line);
      std::string key;
      if( std::getline(is_line, key, '=') )
      {
        std::string value;
        if( std::getline(is_line, value) ) 
          store_line(key, value);
      }
    }

    (Añadiendo el manejo de errores se deja como ejercicio para el lector.)

  2. 33

    Como otros han señalado, probablemente será menos trabajo hacer uso de una configuración existente-analizador de archivos de la biblioteca en lugar de re-inventar la rueda.

    Por ejemplo, si usted decide utilizar el Config4Cpp de la biblioteca (que mantener), entonces su archivo de configuración de la sintaxis será ligeramente diferente (poner comillas alrededor de los valores y terminar instrucciones de asignación con un punto y coma) como se muestra en el siguiente ejemplo:

    # File: someFile.cfg
    url = "http://mysite.com";
    file = "main.exe";
    true_false = "true";

    El siguiente programa analiza el anterior archivo de configuración, copias los valores deseados en las variables y los imprime:

    #include <config4cpp/Configuration.h>
    #include <iostream>
    using namespace config4cpp;
    using namespace std;
    
    int main(int argc, char ** argv)
    {
        Configuration *  cfg = Configuration::create();
        const char *     scope = "";
        const char *     configFile = "someFile.cfg";
        const char *     url;
        const char *     file;
        bool             true_false;
    
        try {
            cfg->parse(configFile);
            url        = cfg->lookupString(scope, "url");
            file       = cfg->lookupString(scope, "file");
            true_false = cfg->lookupBoolean(scope, "true_false");
        } catch(const ConfigurationException & ex) {
            cerr << ex.c_str() << endl;
            cfg->destroy();
            return 1;
        }
        cout << "url=" << url << "; file=" << file
             << "; true_false=" << true_false
             << endl;
        cfg->destroy();
        return 0;
    }

    La Config4Cpp sitio web proporciona la documentación completa, pero leyendo los Capítulos 2 y 3 de la «Guía de inicio» debería ser más que suficiente para sus necesidades.

    • Seguro de que desea que su config4star tenía un público repositorio git de manera que se podía utilizar en otro proyecto con un enlace en lugar de incluir el código real…
    • «Hasta donde yo sé, Config4* es por lejos el mejor del archivo de configuración del analizador en el mundo. Otras tecnologías (tales como XML, JSON, Java propiedades, el Registro de Windows y así sucesivamente) son mediocres y simplista en comparación». – No descargar el porque de este pretencioso declaración en su sitio web.
  3. 13

    Un enfoque ingenuo podría tener este aspecto:

    #include <map>
    #include <sstream>
    #include <stdexcept>
    #include <string>
    
    std::map<std::string, std::string> options; //global?
    
    void parse(std::istream & cfgfile)
    {
        for (std::string line; std::getline(cfgfile, line); )
        {
            std::istringstream iss(line);
            std::string id, eq, val;
    
            bool error = false;
    
            if (!(iss >> id))
            {
                error = true;
            }
            else if (id[0] == '#')
            {
                continue;
            }
            else if (!(iss >> eq >> val >> std::ws) || eq != "=" || iss.get() != EOF)
            {
                error = true;
            }
    
            if (error)
            {
                //do something appropriate: throw, skip, warn, etc.
            }
            else
            {
                options[id] = val;
            }
        }
    }

    Ahora usted puede tener acceso a cada valor de la opción de la global options mapa en cualquier parte del programa. Si desea moldeabilidad, podría hacer que el asignado un tipo de boost::variant.

    • ¿Qué pasa si un comentario tiene más de 2 palabras? ¿Funcionará? Es saltarse la línea, o sólo el próximo 2 cadenas si id == '#'?
    • Sí, eso fue bastante terrible código. He hecho algunas mejoras. Demo
    • no sabía nada de C++ en aquel entonces…)
  4. 12

    libconfig es muy fácil, y lo mejor de todo, usa un pseudo notación json para una mejor legibilidad.

    Fácil de instalar en Ubuntu: sudo apt-get install libconfig++8-dev

    y enlace: -lconfig++

  5. 4

    ¿Por qué no intentar algo simple y legible, como JSON (o XML) ?

    Hay muchos pre-hechos de la abrir-fuente implementaciones de JSON (o XML) para C++ – me gustaría usar uno de ellos.

    Y si quieres algo más «binario» – trate de BJSON o HIJO 🙂

    • JSON o XML son legibles por máquina, pero realmente no es legible por humanos.
    • JSON es bastante legible, si se formatea correctamente (véase: docs.npmjs.com/files/package.json). XML es menos legible, pero ambos están diseñados para ser legible por humanos/editable.
  6. 3

    He buscado config análisis de bibliotecas para mi proyecto recientemente y encontré estas bibliotecas:

  7. 3

    Cómo sobre el formato de su configuración como JSON, y el uso de una biblioteca como jsoncpp?

    por ejemplo,

    {"url": "http://mysite dot com",
    "file": "main.exe",
    "true": 0}

    A continuación puede leer en nombre de las variables, o incluso almacenar todo en un std::map, etc. Esto último significa que usted puede agregar opciones sin tener que cambiar y volver a compilar la configuración del analizador.

  8. 2

    Yo estaba buscando algo que funcionaba como el módulo de python ConfigParser y encontré este: https://github.com/jtilly/inih

    Esto es un encabezado de C++ versión de inih.

    inih (INI No Inventado Aquí) es una forma sencilla .INI analizador de archivos escrito en
    C. Es sólo un par de páginas de código, y fue diseñado para ser
    simple y pequeño, así que es bueno para sistemas embebidos. También es más o
    menos compatible con Python ConfigParser estilo de .Los archivos INI
    incluyendo RFC 822-estilo multi-línea de la sintaxis y nombre: valor de las entradas.

  9. 1

    Aquí es un simple trabajo en torno a los espacios en blanco entre las ‘=’ signo y el de datos, en el archivo de configuración. Asignar a la istringstream de la ubicación después de que el ‘=’ signo y cuando la lectura de ella, todo el espacio en blanco es ignorado.

    Nota: durante el uso de un istringstream en un bucle, asegúrese de llamar a clear() antes de asignar un nuevo hilo.

    //config.txt
    //Input name = image1.png
    //Num. of rows = 100
    //Num. of cols = 150
    
    std::string ipName;
    int nR, nC;
    
    std::ifstream fin("config.txt");
    std::string line;
    std::istringstream sin;
    
    while (std::getline(fin, line)) {
     sin.str(line.substr(line.find("=")+1));
     if (line.find("Input name") != std::string::npos) {
      std::cout<<"Input name "<<sin.str()<<std::endl;
      sin >> ipName;
     }
     else if (line.find("Num. of rows") != std::string::npos) {
      sin >> nR;
     }
     else if (line.find("Num. of cols") != std::string::npos) {
      sin >> nC;
     }
     sin.clear();
    }
    • ¿por qué obtengo segmentation fault (core objeto de dumping) cuando utilizo el método?
    • Es la entrada en la forma que se muestra en los comentarios en la parte superior de mi fragmento de código?

Dejar respuesta

Please enter your comment!
Please enter your name here