2013-02-26 36 views
11

Tôi đang sử dụng chương trình Boost_options để phân tích cú pháp tệp cấu hình theo cách chuẩn như
được hiển thị trong tệp ví dụ multiple_sources.cpp của program_options.Tăng parse_config_file, giá trị khóa rỗng

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

File config.ini tuy nhiên đã trống khóa = cặp giá trị như:

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

Đang cố gắng để đọc tập tin này kết quả trong một lỗi Boost:

boost::program_options::invalid_option_value 

Có cơ chế trong tăng :: program_options để đọc các tập tin cấu hình với entires rỗng?

Mọi trợ giúp sẽ được đánh giá cao.


Tôi đang chỉnh sửa Câu hỏi này vì sự cố chưa được giải quyết. Tôi sẽ trích dẫn ví dụ từ Boost (1.53).

Đây là tập tin đầy đủ 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; 
} 

Và các tập tin cấu hình tương ứng (multiple_sources.cfg) là:

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

Nếu tập tin này ngay bây giờ được sửa đổi để:

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

Thông báo lỗi sau được ném:

the argument for option 'optimization' is invalid 

Giải pháp được đề xuất với quá trình xác thực quá tải có vẻ phức tạp không cần thiết, đặc biệt là vì có thể phải viết chức năng xác thực cho từng loại dữ liệu, kết hợp khả năng nhận ra '\ n' không gian trắng khác.

Mọi đề xuất? Cảm ơn mọi người vì đã dành thời gian.


Tiếp theo đề nghị Aditya của tôi đã thay thế các dòng sau:

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

như sau:

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

và:

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

và không ai trong số họ đọc trống tùy chọn. Tăng chương trình ví dụ "parser_test.cpp" bỏ qua việc sử dụng các zero_tokens(), hoặc implicit_value() bằng cách đọc các cặp khóa-giá trị vào một vector như sau:

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

Hãy xem: http://stackoverflow.com/questions/4459650/skipping-unknown-options-without-throwing-with-boost-program-options – ypnos

+0

Cảm ơn bạn đã liên kết ypnos, tuy nhiên tôi đã có giao diện tại giải pháp đó và tôi đã thêm "true" làm tham số thứ 3 trong đối số parse_config_file. Điều này vẫn không giải quyết được vấn đề. Bạn đã gặp sự cố này và giải pháp đề xuất có khắc phục được sự cố không? –

+0

Xin lỗi, tôi không giúp gì cho bạn. :/ Nó có hoạt động nếu bạn có key3 = 1, key4 = 1 trong tệp cấu hình không? – ypnos

Trả lời

1

tôi muốn khuyên bạn nên để bao quanh với try/bắt ngoại lệ này và chỉ ném lỗi cho những trường thực sự cần thiết cho chương trình của bạn và không thể trống, nếu không trường sẽ bị bỏ qua.

1

Không, hiện tại không có cách nào để xử lý điều này trong khi tăng :: program_options. Có cặp khóa: giá trị rỗng trong tệp INI của bạn giống như chỉ định tùy chọn trên dòng lệnh mà không cung cấp đối số. Việc chấp thuận viết trình xác thực tùy chỉnh được đề xuất bởi ypnos có thể hoạt động nhưng có vẻ không thực tế vì bạn cần áp dụng nó cho mọi tùy chọn bạn mong đợi có thể để trống. Bạn sẽ phải tự thực hiện po :: parse_config_file để bỏ qua các dòng không có giá trị (trừ khi tùy chọn tương ứng được đánh dấu là zero_token) để có được kết quả mà bạn đang tìm kiếm.

+0

Trên thực tế, program_options cho phép chỉ định một tùy chọn trên dòng lệnh mà không có đối số, sử dụng [implicit_value()] (http://www.boost.org/doc/libs/1_43_0/doc/html/boost/program_options/typed_value .html # id887054-bb) trợ giúp. Nhưng điều này không làm việc cho các tập tin INI, thật không may. –

Các vấn đề liên quan