2013-02-26 2 views
11

Я использую Boost program_options для синтаксического анализа файла конфигурации как
, который показан в файле примеров multiple_sources.cpp program_options.Boost parse_config_file, пустое значение ключа

ifstream ini_file("config.ini"); 
    po::store(po::parse_config_file(ini_file, desc, true), vm); 
    po::notify(vm); 

файл config.ini однако имеет пустой ключ = значение пары, такие как:

key1=value1 
key2=value2 
key3= 
key4= 
key5=value5 

Попытка прочитать этот файл приводит к ошибке Форсирование:

boost::program_options::invalid_option_value 

Есть ли механизм в boost :: program_options для чтения таких файлов конфигурации с пустым?

Любая помощь будет высоко оценена.


Я редактирую этот вопрос, так как проблема еще не решена. Я просто приведу пример из Boost (1.53).

Это полный multiple_sources.cpp файл:

#include <boost/program_options.hpp> 
namespace po = boost::program_options; 


#include <iostream> 
#include <fstream> 
#include <iterator> 
using namespace std; 

// A helper function to simplify the main part. 
template<class T> 
ostream& operator<<(ostream& os, const vector<T>& v) 
{ 
    copy(v.begin(), v.end(), ostream_iterator<T>(os, " ")); 
    return os; 
} 


int main(int ac, char* av[]) 
{ 
    try { 
     int opt; 
     string config_file; 

     // Declare a group of options that will be 
     // allowed only on command line 
     po::options_description generic("Generic options"); 
     generic.add_options() 
      ("version,v", "print version string") 
      ("help", "produce help message") 
      //("optimization","optimization level")  
      ("config,c", po::value<string>(&config_file)->default_value("multiple_sources.cfg"), 
        "name of a file of a configuration.") 
      ; 

     // Declare a group of options that will be 
     // allowed both on command line and in 
     // config file 
     po::options_description config("Configuration"); 
     config.add_options() 
      ("optimization", po::value<int>(&opt)->default_value(10), 
        "optimization level") 
      ("include-path,I", po::value< vector<string> >()->composing(), 
       "include path") 
      ; 

     // Hidden options, will be allowed both on command line and 
     // in config file, but will not be shown to the user. 
     po::options_description hidden("Hidden options"); 
     hidden.add_options() 
      ("input-file", po::value< vector<string> >(), "input file") 
      ; 

     po::options_description cmdline_options; 
     cmdline_options.add(generic).add(config).add(hidden); 

     po::options_description config_file_options; 
     config_file_options.add(config).add(hidden); 

     po::options_description visible("Allowed options"); 
     visible.add(generic).add(config); 

     po::positional_options_description p; 
     p.add("input-file", -1); 

     po::variables_map vm; 
     store(po::command_line_parser(ac, av). 
       options(cmdline_options).positional(p).run(), vm); 
     notify(vm); 

     ifstream ifs(config_file.c_str()); 
     if (!ifs) 
     { 
      cout << "can not open config file: " << config_file << "\n"; 
      return 0; 
     } 
     else 
     { 
      store(parse_config_file(ifs, config_file_options), vm); 
      notify(vm); 
     } 

     if (vm.count("help")) { 
      cout << visible << "\n"; 
      return 0; 
     } 

     if (vm.count("version")) { 
      cout << "Multiple sources example, version 1.0\n"; 
      return 0; 
     } 

     if (vm.count("include-path")) 
     { 
      cout << "Include paths are: " 
       << vm["include-path"].as< vector<string> >() << "\n"; 
     } 

     if (vm.count("input-file")) 
     { 
      cout << "Input files are: " 
       << vm["input-file"].as< vector<string> >() << "\n"; 
     } 

     cout << "Optimization level is " << opt << "\n";     
    } 
    catch(exception& e) 
    { 
     cout << e.what() << "\n"; 
     return 1; 
    }  
    return 0; 
} 

И соответствующий файл конфигурации (multiple_sources.cfg) является:

# 
# Comment out this line to use hard-coded default value of 10 
# 
optimization = 1 
include-path = /opt 

Если этот файл теперь изменен на:

# 
# Comment out this line to use hard-coded default value of 10 
# 
optimization = 
include-path = /opt 

Выдается следующее сообщение об ошибке:

the argument for option 'optimization' is invalid 

Предлагаемые решения с проверкой перегрузки и т. Д. Кажутся излишне сложными, тем более что для каждого типа данных может потребоваться написать функцию проверки, включающую возможность распознавания «\ n» другого белого пространства.

Любые предложения? Спасибо всем за то, что нашли время.


По предложению Адитья, я заменил следующую строку:

  ("optimization", po::value<int>(&opt)->default_value(10), 
        "optimization level") 

со следующим:

  ("optimization", po::value<int>(&opt)->zero_tokens(), 
        "optimization level") 

и:

  ("optimization", po::value<int>(&opt)->implicit_value(10), 
        "optimization level") 

и ни один из них читал пустым опции. Повысьте пример программы «parser_test.cpp» обходит использование zero_tokens(), или implicit_value(), читая пары ключ-значение в вектор следующим образом:

void test_config_file(const char* config_file) 
{ 
    options_description desc; 
    desc.add_options() 
     ("gv1", new untyped_value) 
     ("gv2", new untyped_value) 
     ("empty_value", new untyped_value) 
     ("plug*", new untyped_value) 
     ("m1.v1", new untyped_value) 
     ("m1.v2", new untyped_value) 
     ("b", bool_switch()) 
    ; 

    const char content1[] = 
    " gv1 = 0#asd\n" 
    "empty_value = \n" 
    "plug3 = 7\n" 
    "b = true\n" 
    "[m1]\n" 
    "v1 = 1\n" 
    "\n" 
    "v2 = 2\n"  
    ; 

    vector<option> a2 = parse_config_file<char>(config_file, desc).options; 
    BOOST_REQUIRE(a2.size() == 6); 
    check_value(a2[0], "gv1", "0"); 
    check_value(a2[1], "empty_value", ""); 
    check_value(a2[2], "plug3", "7"); 
    check_value(a2[3], "b", "true"); 
    check_value(a2[4], "m1.v1", "1"); 
    check_value(a2[5], "m1.v2", "2"); 
} 
+0

Посмотрите на: http://stackoverflow.com/questions/4459650/skipping-unknown-options-without-throwing-with-boost-program-options – ypnos

+0

Спасибо за ссылку ypnos, однако у меня уже был взгляд в этом решении, и я добавил «true» в качестве третьего параметра в аргументах parse_config_file. Это все еще не решает проблему. Вы столкнулись с этой проблемой и решили ли это решение? –

+0

Извините, тогда я вам не помогу. :/ Будет ли он работать, если у вас есть key3 = 1, key4 = 1 в файле конфигурации? – ypnos

ответ

1

Я бы рекомендовал вам окружить попробовать/поймать это исключение и бросить ошибки только для тех полей, которые действительно необходимы для вашей программы и не могут быть пустыми, иначе поле будет проигнорировано.

1

Нет, в настоящее время нет способа справиться с этим в boost :: program_options. Наличие пустого ключа: пара значений в вашем файле INI совпадает с заданием опции в командной строке без предоставления аргумента. Подход к написанию пользовательских валидаторов, предложенный ypnos, может работать, но кажется непрактичным, так как вам нужно будет применить его к каждой ожидаемой вами опции, которая может быть оставлена ​​пустой. Вам нужно будет написать собственную реализацию po :: parse_config_file, которая игнорирует строки без значения (если соответствующая опция не помечена как zero_token), чтобы получить результат, который вы ищете.

+0

На самом деле, program_options позволяют указать опцию в командной строке без аргумента, используя [implicit_value()] (http://www.boost.org/doc/libs/1_43_0/doc/html/boost/program_options/typed_value .html # id887054-bb). К сожалению, это не работает для файлов INI. –

 Смежные вопросы

  • Нет связанных вопросов^_^