最近想着实现一个能够运动的障碍物,结果搞出一大堆的概念需要整理!
1. 依赖库
在网上找到一个用于解析和构造YAML文件的工具库yaml-cpp
。关于这个库,有几点需要提示的:
-
实践平台:Ubuntu 16.04
-
目前该库已经更新到
0.6
版本,其中0.5.x
以上的版本都使用新的API
接口,之前的版本使用的是旧的API
接口,本文使用yaml-cpp.0.6
版本。同时0.6
版本的需要C++11
支持 -
安装流程
$ git clone https://github.com/jbeder/yaml-cpp.git
# 也可以采用从Releases下载稳定版的方式下载源码
$ mkdir build
$ cd build
# 默认生成静态链接库,配置生成动态链接库
$ cmake -DYAML_BUILD_SHARED_LIBS=ON ..
$ make
$ sudo make install
2. 读取YAML文件
- 文件结构:典型的
cmake
项目
├── build
├── game.yaml
└── config.yaml
├── CMakeLists.txt
└── main.cpp
- config.yaml
yaml-cpp解析文件后,node
的数据类型如下:
1: none
2: Scalar
3: Sequence
4: Map
game.yaml文件内容如下:
trajectory:
- name: Tim
age: 18
numbers: [1, 2, 1, 4]
- name: John
age: 18
numbers: [1, 3, 1, 4]
config.yaml文件内容如下:
containers:
- name: Tim
age: 18
numbers: [1, 2, 1, 4]
- name: John
age: 18
numbers: [1, 3, 1, 4]
- CMakeLists.txt
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(yaml_demo)
SET( CMAKE_CXX_FLAGS "-std=c++11")
find_package(yaml-cpp REQUIRED)
if (yaml-cpp_FOUND)
message(STATUS "找到yaml-cpp:\"${YAML_CPP_INCLUDE_DIR}\"")
message(STATUS "找到yaml-cpp Libraries:\"${YAML_CPP_LIBRARIES}\"")
endif (yaml-cpp_FOUND)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} yaml-cpp)
- main.cpp
// https://github.com/jbeder/yaml-cpp/wiki/Tutorial
#include <string>
#include <iostream>
#include <fstream>
#include <yaml-cpp/yaml.h>
#include <yaml-cpp/node/parse.h>
struct Container
{
std::string name;
int age;
std::vector<int> numbers;
};
namespace YAML
{
template <>
struct convert<Container>
{
static Node encode(const Container &player)
{
Node node;
node.push_back(player.name);
node.push_back(player.age);
node.push_back(player.numbers);
return node;
}
static bool decode(const Node &node, Container &player)
{
player.name = node["name"].as<std::string>();
player.age = node["age"].as<int>();
player.numbers = node["numbers"].as<std::vector<int>>();
return true;
}
};
} // namespace YAML
int main(int argc, char **argv)
{
// 读取文件
// ============================================================================
std::string config_path = "./config.yaml";
std::cout << config_path << std::endl;
YAML::Node config = YAML::LoadFile(config_path);
// node类型也可以直接文件保存
// ofstream fout("testconfig.yaml");
// fout << config;
// fout.close();
// trajectory:
// - name: 222
// age: 18
// numbers: [1, 2, 1, 4]
// - name: 222
// age: 18
// numbers: [1, 2, 1, 4]
// 该文件的整体类型为Map格式,Size为1,包含trajectory节点
// trajectory节点类型为Sequences格式,Size为2,包含Map类型的数据
//
// 获取containers中的数据内容
std::vector<Container> vi = config["containers"].as<std::vector<Container>>();
std::vector<int> numberVec;
for (std::vector<Container>::iterator it = vi.begin(); it != vi.end(); ++it)
{
// 其中it为相关container的指针,而container为结构体,故it无法直接输出
std::cout << it->name << std::endl;
std::cout << it->age << std::endl;
// 无法直接输出numbers,因为numbers为一个vector
numberVec = it->numbers;
for (int n = 0; n < numberVec.size(); n++)
{
std::cout << numberVec[n] << " ";
}
std::cout << " " << std::endl;
}
// 保存文件:需要输出的文件名
// ============================================================================
std::ofstream fout("game.yaml");
YAML::Emitter emitter;
emitter << YAML::BeginMap;
emitter << YAML::Key << "trajectory";
emitter << YAML::BeginSeq;
for (int i = 0; i < vi.size(); i++)
{
emitter << YAML::BeginMap;
emitter << YAML::Key << "name" << YAML::Value << vi[i].name;
emitter << YAML::Key << "age" << YAML::Value << vi[i].age;;
emitter << YAML::Key << "numbers" << YAML::Flow << vi[i].numbers;
emitter << YAML::EndMap;
}
emitter << YAML::EndSeq;
emitter << YAML::EndMap;
std::cout << "Here's the output YAML:\n" << emitter.c_str() << std::endl;
fout << emitter.c_str();
fout.close();
return 0;
}
3. Errors
- 无法解析或打开软件包的列表或是状态文件
E: Encountered a section with no Package: header
E: Problem with MergeList /var/lib/apt/lists/ppa.launchpad.
net_maarten-baert_simplescreenrecorder_ubuntu_dists_xenial_main_binary-amd64_Packages
解决方案:
$ sudo rm /var/lib/apt/lists/* -vf
$ sudo apt-get update
- 软件卸载指令记录
# 只卸载软件包
$ sudo apt-get remove package_name
# 卸载软件包及其依赖
$ sudo apt-get remove --auto-remove package_name
# 清除软件包和软件的配置文件
$ sudo apt-get purge package_name
# 清除软件包及其依赖,以及对应的配置文件
$ sudo apt-get purge --auto-remove package_name
- 查看库位置
ldconfig -p | grep lib_name
- CMakeLists.txt语法糖
# 在CMakeLists.txt文件中打印出里面定义的变量的值
MESSAGE("include folder: "${include_dir})
# 实例:可以查看/usr/local/lib文件下的动态链接库的名字
find_package(yaml-cpp REQUIRED)
if (yaml-cpp_FOUND)
message(STATUS "找到yaml-cpp:\"${YAML_CPP_INCLUDE_DIR}\"")
message(STATUS "找到yaml-cpp Libraries:\"${YAML_CPP_LIBRARIES}\"")
endif (yaml-cpp_FOUND)
# 上述实例的yaml-cpp在两个地方均存在大小写的区别
# 常见的名字有:首字母大写,全部小写或大写
# name_INCLUDE_DIRS
# name_INCLUDE_DIR
# NAME_INCLUDE_DIRS
# NAME_INCLUDE_DIR
# name_LIBS
# NAME_LIBS
# name_LIBRARIES
# NAME_LIBRARIES
网友评论