2008-12-13 8 views
20

Je veux un tutoriel simple pour me montrer pour charger un fichier yaml et analyser les données. Le style d'expatrié serait génial, mais toute solution qui me montre réellement les données sous une forme serait utile. Jusqu'à présent, j'ai exécuté plusieurs tests dans la source yaml-0.1.1 pour C et j'ai soit une erreur, pas de sortie quoi que ce soit ou dans le cas run-emitter.c. Il lit dans le fichier yaml et l'imprime sur STDOUT, il ne produit pas le texte via libyaml functions/structs. Dans les cas avec une erreur je ne sais pas si c'était le bc le fichier était mauvais ou ma construction est incorrecte (je n'ai rien modifié ...) Le fichier a été copié de yaml.orgParse YAML fichiers en C++

Quelqu'un peut-il pointer moi à un tutoriel? (J'ai googlé pendant au moins 30 minutes en lisant tout ce qui semblait pertinent) ou le nom d'une lib qui a un bon tutoriel ou exemple. Peut-être que vous pouvez me dire quel test libyaml charge dans les fichiers et fait quelque chose avec lui ou pourquoi j'ai eu des erreurs. Ce document n'explique pas comment utiliser le fichier, seulement comment le charger.

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

+3

S'il vous plaît, C et C++ ne sont pas les mêmes. Il y a d'excellents exemples de solutions pour chacun, mais comme vous le voyez, ils sont très différents. Je suppose que parmi les balises vous voulez plus de C++ que C. Si vous voulez C++, demandez C++. Demander des solutions C peut souvent rendre un programme plus confus. –

Répondre

5

A Google Recherche de code (aujourd'hui disparu) pour "charge yaml lang: C++" a donné cela comme le premier lien: 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

exemple C - analyse syntaxique arbre YAML à un 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

Essayez yaml-cpp (comme suggéré par this question) pour un analyseur C++.

Divulgation: Je suis l'auteur.

syntaxe Exemple (à partir du 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

Quelle est la configuration requise pour utiliser [yaml-cpp] (https://github.com/jbeder/yaml-cpp)? Dois-je simplement télécharger les fichiers d'en-tête et les inclure dans mon programme C++? –

+0

@BruceWayne vous devez construire la bibliothèque et la lier à votre projet. –

+1

Malheureusement, yaml-cpp est difficilement maintenu. Les versions sont peu fréquentes, parfois boguées (les distributions telles que Debian s'aggravent en ne se mettant pas assez à jour en amont), et au début de 2018, la dernière version utilise 'auto_ptr' qui interdit l'utilisation de yaml-cpp dans tout projet C++ 17. – akim