2008-12-13 43 views
20

Tôi muốn một hướng dẫn đơn giản để chỉ cho tôi tải tệp yaml và phân tích cú pháp dữ liệu. Phong cách người nước ngoài sẽ là tuyệt vời nhưng bất kỳ giải pháp nào thực sự cho tôi thấy dữ liệu ở một dạng nào đó sẽ hữu ích.Phân tích các tệp YAML trong C++

Cho đến nay tôi đã chạy nhiều thử nghiệm trong nguồn yaml-0.1.1 cho C và tôi hoặc gặp phải lỗi, không có kết quả đầu ra hoặc trong trường hợp run-emitter.c. Nó đọc trong tệp yaml và in nó vào STDOUT, nó không tạo ra văn bản thông qua các hàm/cấu trúc libyaml. Trong các trường hợp có lỗi, tôi không biết nếu tệp đó là bc tệp không đúng hoặc bản dựng của tôi không chính xác (tôi không sửa đổi bất cứ điều gì ...) Tệp được sao chép từ yaml.org

Bất kỳ ai cũng có thể tôi đến một hướng dẫn? (Tôi googled cho ít nhất 30 phút đọc bất cứ điều gì có liên quan) hoặc một tên của một lib có một hướng dẫn hay ví dụ tốt. Có lẽ bạn có thể cho tôi biết thử tải libyaml nào trong các tệp và thực hiện điều gì đó với nó hoặc tại sao tôi nhận được lỗi. Tài liệu này không giải thích cách sử dụng tệp, chỉ cách tải tệp đó.

http://pyyaml.org/wiki/LibYAML#Documentation

+3

Xin vui lòng, C và C++ không giống nhau. Có những ví dụ tuyệt vời về các giải pháp cho mỗi, nhưng khi bạn thấy chúng rất khác nhau. Tôi đoán từ các thẻ bạn muốn C + + nhiều hơn C. Nếu bạn muốn C + +, yêu cầu C + +. Yêu cầu các giải pháp C thường có thể làm cho chương trình trở nên khó hiểu hơn. –

Trả lời

5

Code Search của Google (nay không còn tồn tại) cho "tải yaml lang: C++" đã cho điều này là mắt xích đầu tiên: demo.cc:

#include <iyaml++.hh> 
#include <tr1/memory> 
#include <iostream> 
#include <stdexcept> 

using namespace std; 

// What should libyaml++ do when a YAML entity is parsed? 
// NOTE: if any of the event handlers is not defined, a respective default 
// no-op handler will be used. For example, not defining on_eos() is 
// equivalent to defining void on_eos() { }. 
class my_handler : public yaml::event_handler { 
    void on_string(const std::string& s) { cout << "parsed string: " << s << endl; } 
    void on_integer(const std::string& s) { cout << "parsed integer: " << s << endl; } 
    void on_sequence_begin() { cout << "parsed sequence-begin." << endl; } 
    void on_mapping_begin() { cout << "parsed mapping-begin." << endl; } 
    void on_sequence_end() { cout << "parsed sequence-end." << endl; } 
    void on_mapping_end() { cout << "parsed mapping-end." << endl; } 
    void on_document() { cout << "parsed document." << endl; } 
    void on_pair() { cout << "parsed pair." << endl; } 
    void on_eos() { cout << "parsed eos." << endl; } 
}; 

// ok then, now that i know how to behave on each YAML entity encountered, just 
// give me a stream to parse! 
int main(int argc, char* argv[]) 
{ 
    tr1::shared_ptr<my_handler> handler(new my_handler()); 
    while(cin) { 
     try { yaml::load(cin, handler); } // throws on syntax error 

     catch(const runtime_error& e) { 
      cerr << e.what() << endl; 
     } 
    } 
    return 0; 
} 
10

C dụ - phân tích cây YAML đến một glib "N-ary tree" :

#include <yaml.h> 
#include <stdio.h> 
#include <glib.h> 

void process_layer(yaml_parser_t *parser, GNode *data); 
gboolean dump(GNode *n, gpointer data); 



int main (int argc, char **argv) { 
    char *file_path = "test.yaml"; 
    GNode *cfg = g_node_new(file_path); 
    yaml_parser_t parser; 

    FILE *source = fopen(file_path, "rb"); 
    yaml_parser_initialize(&parser); 
    yaml_parser_set_input_file(&parser, source); 
    process_layer(&parser, cfg); // Recursive parsing 
    yaml_parser_delete(&parser); 
    fclose(source); 

    printf("Results iteration:\n"); 
    g_node_traverse(cfg, G_PRE_ORDER, G_TRAVERSE_ALL, -1, dump, NULL); 
    g_node_destroy(cfg); 

    return(0); 
} 



enum storage_flags { VAR, VAL, SEQ }; // "Store as" switch 

void process_layer(yaml_parser_t *parser, GNode *data) { 
    GNode *last_leaf = data; 
    yaml_event_t event; 
    int storage = VAR; // mapping cannot start with VAL definition w/o VAR key 

    while (1) { 
     yaml_parser_parse(parser, &event); 

     // Parse value either as a new leaf in the mapping 
     // or as a leaf value (one of them, in case it's a sequence) 
     if (event.type == YAML_SCALAR_EVENT) { 
      if (storage) g_node_append_data(last_leaf, g_strdup((gchar*) event.data.scalar.value)); 
      else last_leaf = g_node_append(data, g_node_new(g_strdup((gchar*) event.data.scalar.value))); 
      storage ^= VAL; // Flip VAR/VAL switch for the next event 
     } 

     // Sequence - all the following scalars will be appended to the last_leaf 
     else if (event.type == YAML_SEQUENCE_START_EVENT) storage = SEQ; 
     else if (event.type == YAML_SEQUENCE_END_EVENT) storage = VAR; 

     // depth += 1 
     else if (event.type == YAML_MAPPING_START_EVENT) { 
      process_layer(parser, last_leaf); 
      storage ^= VAL; // Flip VAR/VAL, w/o touching SEQ 
     } 

     // depth -= 1 
     else if (
      event.type == YAML_MAPPING_END_EVENT 
      || event.type == YAML_STREAM_END_EVENT 
     ) break; 

     yaml_event_delete(&event); 
    } 
} 


gboolean dump(GNode *node, gpointer data) { 
    int i = g_node_depth(node); 
    while (--i) printf(" "); 
    printf("%s\n", (char*) node->data); 
    return(FALSE); 
} 
35

Hãy thử yaml-cpp (theo đề nghị của this question) cho một C++ phân tích cú pháp.

Tiết lộ: Tôi là tác giả.

Ví dụ cú pháp (từ Tutorial):

YAML::Node config = YAML::LoadFile("config.yaml"); 

if (config["lastLogin"]) { 
    std::cout << "Last logged in: " << config["lastLogin"].as<DateTime>() << "\n"; 
} 

const std::string username = config["username"].as<std::string>(); 
const std::string password = config["password"].as<std::string>(); 
login(username, password); 
config["lastLogin"] = getCurrentDateTime(); 

std::ofstream fout("config.yaml"); 
fout << config; 
+1

Thiết lập cần thiết để sử dụng [yaml-cpp] (https://github.com/jbeder/yaml-cpp) là gì? Tôi chỉ cần tải xuống các tệp tiêu đề và đưa chúng vào chương trình C++ của tôi? –

+0

@BruceWayne bạn phải xây dựng thư viện và liên kết nó với dự án của bạn. –

+1

Thật không may là yaml-cpp hầu như không được duy trì. Các bản phát hành không thường xuyên, đôi khi lỗi (các bản phân phối như Debian xấu đi do không cập nhật đủ từ phía trên), và vào đầu năm 2018 bản phát hành mới nhất vẫn sử dụng 'auto_ptr' ngăn cấm sử dụng yaml-cpp trong bất kỳ dự án C++ 17 nào. – akim

10

Tôi đã viết một hướng dẫn tại http://wpsoftware.net/andrew/pages/libyaml.html.

Điều này bao gồm các khái niệm cơ bản về việc sử dụng libyaml trong C, sử dụng phân tích dựa trên mã thông báo và dựa trên sự kiện. Nó bao gồm mã mẫu để xuất các nội dung của một tệp YAML.

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