2008-12-13 18 views
20

Quiero un tutorial simple para mostrarme que cargue un archivo yaml y analice los datos. El estilo de expatriado sería genial, pero cualquier solución que realmente me muestre los datos de alguna forma sería útil.Archivos Parse YAML en C++

Hasta ahora ejecuté pruebas múltiples en la fuente yaml-0.1.1 para C y recibo un error, no hay salida alguna vez o en el caso run-emitter.c. Lee en el archivo yaml y lo imprime en STDOUT, no produce el texto a través de funciones/estructuras libyaml. En los casos con un error, no sé si el archivo era incorrecto o mi compilación es incorrecta (no modifiqué nada ...) El archivo se copió de yaml.org

¿Alguien puede señalar? a un tutorial? (Busqué en Google durante al menos 30 minutos leyendo cualquier cosa que pareciera relevante) o un nombre de una lib que tiene un buen tutorial o ejemplo. Quizás puedas decirme qué prueba de libyaml se carga en archivos y hace algo con ella o por qué recibí errores. Este documento no explica cómo usar el archivo, solo cómo cargarlo.

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

+3

Por favor, C y C++ no son lo mismo. Hay excelentes ejemplos de soluciones para cada uno, pero como ve, son muy diferentes. Supongo que de las etiquetas quieres C++ más que C. Si quieres C++, pregunta por C++. Pedir soluciones C a menudo puede hacer que un programa sea más confuso. –

Respuesta

5

Un Código de búsqueda de Google (ahora difunto) para "carga yaml lang: C++" dio esto como el primer enlace: 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 ejemplo - el análisis del árbol YAML a 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

Trate yaml-cpp (según lo sugerido por this question) para un analizador de C++.

Divulgación: soy el autor.

ejemplo de sintaxis (de la 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

¿Cuál es la configuración requerida para usar [yaml-cpp] (https://github.com/jbeder/yaml-cpp)? ¿Tengo que descargar los archivos de encabezado e incluirlos en mi programa C++? –

+0

@BruceWayne debe crear la biblioteca y vincularla a su proyecto. –

+1

Desafortunadamente, yaml-cpp apenas se mantiene. Las versiones son poco frecuentes, a veces con errores (las distribuciones como Debian empeoran al no actualizarse lo suficiente desde el inicio), y a partir de principios de 2018 la última versión todavía usa 'auto_ptr' que prohíbe el uso de yaml-cpp en cualquier proyecto de C++ 17. – akim