2012-08-02 30 views
5

Tôi đang xây dựng trình tạo biểu đồ bằng cách sử dụng Biểu đồ tăng cường và Tùy chọn chương trình. Có, ví dụ, hai loại thành phần C và W, mỗi loại có 1 nguồn, 1 bồn rửa và một số thông số bổ sung để xác định cấu trúc liên kết ở giữa. Tôi muốn có thể ghép chúng lại với nhau theo thứ tự được cung cấp bởi thứ tự của các đối số dòng lệnh.Làm cách nào để trích xuất chuỗi các tùy chọn được phân tích bằng cách sử dụng Tùy chọn chương trình tăng cường?

Ví dụ:

./bin/make_graph -c4,5,1 -w3,3 -c3,1,2 

có nên tạo một đồ thị tương tự như sau:

C -- W -- C 

Nhưng:

./bin/make_graph -c4,5,1 -c3,1,2 -w3,3 

có nên tạo một đồ thị tương tự như sau:

C -- C -- W 

Sử dụng tăng :: program_options, tôi không thể xác định cách trích xuất thứ tự chính xác vì nó "soạn" các tùy chọn của cùng chuỗi_key thành bản đồ với chuỗi value_type == vector <> (trong trường hợp của tôi).

Bằng cách lặp lại bản đồ, đơn đặt hàng bị mất. Có cách nào để không sao chép phân tích cú pháp, nhưng có một chức năng gọi là (có lẽ là một cuộc gọi lại) mỗi khi một tùy chọn được phân tích cú pháp? Tôi không thể tìm thấy tài liệu theo hướng này. Bất cứ một đề nghị nào khác?

Để thuyết phục bạn rằng tôi sẽ không làm cho này lên, đây là những gì tôi có cho đến nay:

namespace bpo = boost::program_options; 
    std::vector<std::string> args_cat, args_grid, args_web; 
    bpo::options_description desc("Program options:"); 
    desc.add_options() 
      .operator()("help,h","Displays this help message.") 
      .operator()("caterpillar,c",bpo::value< std::vector<std::string> >(&args_cat)->default_value(std::vector<std::string>(1,"4,7,2"), "4,7,2"),"Caterpillar tree with 3 parameters") 
      .operator()("grid,g",bpo::value< std::vector<std::string> >(&args_grid)->default_value(std::vector<std::string>(1,"3,4"), "3,4"),"Rectangular grid with 2 parameters") 
      .operator()("web,w",bpo::value< std::vector<std::string> >(&args_web)->default_value(std::vector<std::string>(1,"3,4"), "3,4"),"Web with 2 parameters") 
      ; 
    bpo::variables_map ops; 
    bpo::store(bpo::parse_command_line(argc,argv,desc),ops); 
    bpo::notify(ops); 
    if((argc < 2) || (ops.count("help"))) { 
     std::cout << desc << std::endl; 
     return; 
    } 
    //TODO: remove the following scope block after testing 
    { 
     typedef bpo::variables_map::iterator OptionsIterator; 
     OptionsIterator it = ops.options.begin(), it_end = ops.options.end(); 
     while(it != it_end) { 
      std::cout << it->first << ": "; 
      BOOST_FOREACH(std::string value, it->second) { 
       std::cout << value << " "; 
      } 
      std::cout << std::endl; 
      ++it; 
     } 
     return; 
    } 

Tôi nhận ra rằng tôi cũng có thể bao gồm các loại như một tham số và giải quyết vấn đề này trivially, ví dụ như:

./bin/make_graph --component c,4,5,1 --component w,3,3 --component c,3,1,2 

nhưng đó là di chuyển theo hướng viết một phân tích cú pháp/validator bản thân mình (thậm chí có thể không sử dụng Boost Chương trình Options):

./bin/make_graph --custom c,4,5,1,w,3,3,c,3,1,2 
./bin/make_graph c,4,5,1,w,3,3,c,3,1,2 

Các bạn khuyên tôi nên làm điều này một cách thanh lịch như thế nào?

Cảm ơn trước!

PS: Tôi đã tìm kiếm trên SO cho "[boost] + tùy chọn chương trình tuần tự" và "[boost-program-options] + order" (và các biến thể của chúng) trước khi đăng bài này, vì vậy tôi xin lỗi trước nếu điều này hóa ra là một bản sao.

Trả lời

2

Làm thế nào về điều này:

./bin/make_graph c,4,5,1 c,3,1,2 w,3,3 

đâu "c,4,5,1", "c,3,1,2""w,3,3"đối số vị trí được lưu trữ (theo thứ tự) trong một std::vector<std::string> (giống như --input-file trong tutorial này). Sau đó, sử dụng Boost.Tokenizer hoặc boost::algorithm::split để trích xuất các subtokens từ mỗi chuỗi đối số.

Nếu đồ thị có thể phức tạp, bạn nên xem xét việc người dùng có thể chỉ định tệp đầu vào chứa thông số biểu đồ. Boost.Program_Options có thể phân tích cú pháp một người dùng config file sử dụng cú pháp giống như các tùy chọn dòng lệnh.

+0

Cảm ơn. Tôi đồng ý về các tệp cấu hình. Động cơ của tôi là để tránh tập tin I/O trên một số lượng lớn chạy. – scribbleink

4

Kể từ khi đăng câu hỏi, tôi đã thực hiện một số thao tác đào và có "hack" hoạt động với các ví dụ hiện có mà tôi đã nêu ở trên.

bpo::parsed_options p_ops = bpo::parse_command_line(argc,argv,desc); 
typedef std::vector< bpo::basic_option<char> >::iterator OptionsIterator; 
OptionsIterator it = p_ops.options.begin(), it_end = p_ops.options.end(); 
while(it != it_end) { 
    std::cout << it->string_key << ": "; 
    BOOST_FOREACH(std::string value, it->value) { 
     std::cout << value << " "; 
    } 
    std::cout << std::endl; 
    ++it; 
} 

Lý do tôi gọi nó là một hack là bởi vì nó truy cập tất cả các đối số như dây đàn, và người ta sẽ phải trích xuất các loại từ nó giống như BPO :: variables_map làm với chức năng .as<T>() thành viên. EDIT: Nó cũng truy cập một thành viên của các tùy chọn struct trực tiếp.

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