C++ : fichier de configuration

De Wiki de Calcul Québec
Aller à : Navigation, rechercher
Autres langues :anglais 100% • ‎français 100%

La classe Configuration présentée ici peut lire et conserver les valeurs de n'importe quel fichier de configuration écrit dans un format comme celui-ci :

#
# Simulation parameters
#
 
nbDimensions    = 2
temperature     = 25.001
epsilon         = 1.013e-14
writeLogFile    = false      # NOTE: Set to "true" in debug mode only.
                             #       Logging slows down the program.
errorMessage    = the simulation failed

Ce format est très flexible et facile à utiliser. Quelques avantages :

  • on peut insérer des lignes blanches, des espaces et des tabulations pour rendre le fichier plus lisible;
  • l'ordre des variables n'a pas d'importance;
  • on peut écrire des commentaires n'importe où en les précédant du caractère « # ».

La classe est basée sur le conteneur std::map<T> de la STL (Standard Template Library). Ce conteneur, dit associatif, emmagasine les données sous forme de paires clé-valeur. Il est analogue à un annuaire téléphonique : on utilise la clé (le nom) pour rechercher la valeur (le numéro de téléphone).

Fichier : configuration.cpp
#include <map>
#include <string>
#include <fstream>
#include <iostream>
 
using namespace std;
 
class Configuration
{
public:
    // clear all values
    void Clear();
 
    // load a configuration file
    bool Load(const string& File);
 
    // check if value associated with given key exists
    bool Contains(const string& key) const;
 
    // get value associated with given key
    bool Get(const string& key, string& value) const;
    bool Get(const string& key, int&    value) const;
    bool Get(const string& key, long&   value) const;
    bool Get(const string& key, double& value) const;
    bool Get(const string& key, bool&   value) const;
 
private:
    // the container
    map<string,string> data;
 
    // remove leading and trailing tabs and spaces
    static string Trim(const string& str);
};
 
 
// ----------------------------------
// method implementations
// ----------------------------------
 
void Configuration::Clear()
{
    data.clear();
}
 
bool Configuration::Load(const string& file)
{
    ifstream inFile(file.c_str());
 
    if (!inFile.good())
    {
        cout << "Cannot read configuration file " << file << endl;
        return false;
    }
 
    while (inFile.good() && ! inFile.eof())
    {
        string line;
        getline(inFile, line);
 
        // filter out comments
        if (!line.empty())
        {
            int pos = line.find('#');
 
            if (pos != string::npos)
            {
                line = line.substr(0, pos);
            }
        }
 
        // split line into key and value
        if (!line.empty())
        {
            int pos = line.find('=');
 
            if (pos != string::npos)
            {
                string key     = Trim(line.substr(0, pos));
                string value   = Trim(line.substr(pos + 1));
 
                if (!key.empty() && !value.empty())
                {
                    data[key] = value;
                }
            }
        }
    }
 
    return true;
}
 
bool Configuration::Contains(const string& key) const
{
    return data.find(key) != data.end();
}
 
bool Configuration::Get(const string& key, string& value) const
{
    map<string,string>::const_iterator iter = data.find(key);
 
    if (iter != data.end())
    {
        value = iter->second;
        return true;
    }
    else
    {
        return false;
    }
}
 
bool Configuration::Get(const string& key, int& value) const
{
    string str;
 
    if (Get(key, str))
    {
        value = atoi(str.c_str());
        return true;
    }
    else
    {
        return false;
    }
}
 
bool Configuration::Get(const string& key, long& value) const
{
    string str;
 
    if (Get(key, str))
    {
        value = atol(str.c_str());
        return true;
    }
    else
    {
        return false;
    }
}
 
bool Configuration::Get(const string& key, double& value) const
{
    string str;
 
    if (Get(key, str))
    {
        value = atof(str.c_str());
        return true;
    }
    else
    {
        return false;
    }
}
 
bool Configuration::Get(const string& key, bool& value) const
{
    string str;
 
    if (Get(key, str))
    {
        value = (str == "true");
        return true;
    }
    else
    {
        return false;
    }
}
 
string Configuration::Trim(const string& str)
{
    int first = str.find_first_not_of(" \t");
 
    if (first != string::npos)
    {
        int last = str.find_last_not_of(" \t");
 
        return str.substr(first, last - first + 1);
    }
    else
    {
        return "";
    }
}


Exemple d'utilisation :

Fichier : exemple_configuration.cpp
Configuration   config;
int             nbDimensions;
double          temperature;
double          epsilon;
bool            writeLogFile;
string          errorMessage;
 
config.Load("./simulation.cfg");
 
if (config.Get("nbDimensions", nbDimensions)    &&
    config.Get("temperature",  temperature)     &&
    config.Get("epsilon",      epsilon)         &&
    config.Get("writeLogFile", writeLogFile)    &&
    config.Get("errorMessage", errorMessage))
{
    ...
}
else
{
    cout << "Missing parameter in configuration file." << endl;
}


Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Ressources de Calcul Québec
Outils
Partager