亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

c++ 讀寫(xiě)yaml配置文件

 更新時(shí)間:2023年04月07日 11:10:51   作者:小魚(yú)兒飛呀飛  
YAML所表示的YAML Ain’t Markup Language,YAML 是一種簡(jiǎn)潔的非標(biāo)記語(yǔ)言,這篇文章主要介紹了在C語(yǔ)言開(kāi)發(fā)中如何讀寫(xiě)配置yaml配置文件,感興趣的同學(xué)可以參考一下

YAML基礎(chǔ)語(yǔ)法

YAML所表示的YAML Ain’t Markup Language,YAML 是一種簡(jiǎn)潔的非標(biāo)記語(yǔ)言。YAML以數(shù)據(jù)為中心,使用空白,縮進(jìn),分行組織數(shù)據(jù),從而使得表示更加簡(jiǎn)潔易讀。
一邊學(xué)習(xí)規(guī)則一邊可以在在線(xiàn)Demo這個(gè)YAML轉(zhuǎn)化JSON網(wǎng)頁(yè)中進(jìn)行上手練習(xí)

基本規(guī)則

YAML有以下基本規(guī)則:
1、大小寫(xiě)敏感
2、使用縮進(jìn)表示層級(jí)關(guān)系
3、禁止使用tab縮進(jìn),只能使用空格鍵
4、縮進(jìn)長(zhǎng)度沒(méi)有限制,只要元素對(duì)齊就表示這些元素屬于一個(gè)層級(jí)。
5、使用#表示注釋
6、字符串可以不用引號(hào)標(biāo)注

三種數(shù)據(jù)結(jié)構(gòu)

map,散列表

使用冒號(hào)(:)表示鍵值對(duì),同一縮進(jìn)的所有鍵值對(duì)屬于一個(gè)map,示例:

# YAML表示
age : 12
name : huang
 
# 對(duì)應(yīng)的Json表示
{'age':12,'name':'huang'}

list,數(shù)組

使用連字符(-)表示:

# YAML表示
- a
- b
- 12
# 對(duì)應(yīng)Json表示
['a','b',12]

也可以寫(xiě)在一行:

# YAML表示
[a,b,c]
 
# 對(duì)應(yīng)Json表示
[ 'a', 'b', 'c' ]

scalar,純量

數(shù)據(jù)最小的單位,不可以再分割。

數(shù)據(jù)結(jié)構(gòu)嵌套

map和list的元素可以是另一個(gè)map或者list或者是純量。由此出現(xiàn)4種常見(jiàn)的數(shù)據(jù)嵌套:

map嵌套map

# YAML表示
websites:
 YAML: yaml.org 
 Ruby: ruby-lang.org 
 Python: python.org 
 Perl: use.perl.org 
# 對(duì)應(yīng)Json表示
{ websites: 
   { YAML: 'yaml.org',
     Ruby: 'ruby-lang.org',
     Python: 'python.org',
     Perl: 'use.perl.org' } }

map嵌套list

# YAML表示
languages:
 - Ruby
 - Perl
 - Python 
 - c
# 對(duì)應(yīng)Json表示
{ languages: [ 'Ruby', 'Perl', 'Python', 'c' ] }

list嵌套list

# YAML表示
-
  - Ruby
  - Perl
  - Python 
- 
  - c
  - c++
  - java
# 對(duì)應(yīng)Json表示
[ [ 'Ruby', 'Perl', 'Python' ], [ 'c', 'c++', 'java' ] ]

除此以外,還可以如下表示該結(jié)構(gòu)

# 方法2
- - Ruby
  - Perl
  - Python 
- - c
  - c++
  - java
# 方法3
- [Ruby,Perl,Python]
- [c,c++,java]

list嵌套map

# YAML表示
-
  id: 1
  name: huang
-
  id: 2
  name: liao
 
# 對(duì)應(yīng)Json表示
[ { id: 1, name: 'huang' }, { id: 2, name: 'liao' } ]

利用yaml-cpp讀寫(xiě)yaml配置文件

yaml-cpp 是一個(gè)開(kāi)源庫(kù),地址在 github 上,https://github.com/jbeder/yaml-cpp

yaml-cpp 是通過(guò) CMake 來(lái)進(jìn)行構(gòu)建和編譯的。

首先下載源碼

然后,在源碼目錄創(chuàng)建一個(gè) build 文件夾。

mkdir build

進(jìn)入到 build 文件夾,然后執(zhí)行 cmake 命令。

cd build
cmake ..

注意的是 cmake 后面是 …,這代表從 build 上一層目錄查找 CMakeLists.txt ,然后編譯的文件都會(huì)存放在 build 文件夾,如果對(duì)編譯的效果不滿(mǎn)意,只要?jiǎng)h除 build 文件就好了,其他源碼目錄并不受影響,這是 cmake 編譯時(shí)的基本套路。

yaml-cpp 默認(rèn)構(gòu)建的就是靜態(tài)庫(kù),也就是 unix 類(lèi)系統(tǒng)下的 .a 文件,如果你想構(gòu)建動(dòng)態(tài)庫(kù)的話(huà),就需要在 cmake 時(shí)指定。

cmake .. -D BUILD_SHARED_LIBS=ON

編譯成功后,會(huì)生成庫(kù)文件,你只需要將庫(kù)文件和頭文件拷貝到你自己的工程當(dāng)中,就可以使用了。

需要處理好頭文件。

你如果不想每次都到 copy 頭文件到不同的工程中,那么你可以將頭文件 copy 到系統(tǒng)默認(rèn)的頭文件目錄,比如 ubuntu 的地址是 /usr/local/include,
在這里插入圖片描述

將庫(kù)文件拷貝到系統(tǒng)默認(rèn)的 lib 文件就好了,比如 ubuntu 是 /usr/local/lib。
在這里插入圖片描述

有了頭文件和庫(kù),我們就可以順利寫(xiě)代碼了。

讀取 yaml 配置文件

假如我們有這樣一個(gè)配置文件
config.yaml

name: frank
sex: male
age: 18

skills: 
  c++: 1
  java: 1
  android: 1
  python: 1

溫馨提示:yaml 中的內(nèi)容,:后面一定要加空格哦
現(xiàn)在,我們的目標(biāo)是要把它正確的讀取出來(lái)。

yaml_test.cpp

#include <iostream>
#include "include/yaml-cpp/yaml.h"

using namespace std;

int main(int argc,char** argv)
{
    YAML::Node config = YAML::LoadFile("../config.yaml");

    cout << "name:" << config["name"].as<string>() << endl;
    cout << "sex:" << config["sex"].as<string>() << endl;
    cout << "age:" << config["age"].as<int>() << endl;
    return 0;
}

頭文件在/usr/local/include目錄下
庫(kù)文件在/usr/local/lib目錄下
然后通過(guò) cmake 編譯,因?yàn)槲伊?xí)慣用 cmake,如果讀者喜歡用原始的 g++ 編譯或者 makefile 也是可以的。

我的 CMakeFileLists.txt 如下:

cmake_minimum_required(VERSION 3.2)

project(yaml_test)

add_definitions(-std=c++11)
#set(CMAKE_CXX_STANDARD 11)

include_directories(/usr/local/include/yaml-cpp)#頭文件路徑
set(SRCS src/yaml_test.cpp)
add_executable(yamltest ${SRCS})

target_link_libraries(yamltest /usr/local/lib/libyaml-cpp.so)#庫(kù)文件路徑

在當(dāng)前目錄創(chuàng)建 build 文件夾,然后進(jìn)入 build 文件執(zhí)行 cmake 操作。

mkdir buildcd buildcmake ..

最終生成了名為 yamltest 的可執(zhí)行文件。

執(zhí)行后,輸出的信息如下。

name:frank
sex:male
age:18

Node

Node 是 yaml-cpp 中的核心概念,它用于存儲(chǔ)解析后的 yaml 信息。

生成 Node 的形式有很多種, loadFile() 是最常見(jiàn)的一種。

Node LoadFile(const std::string& filename)

filename 就是配置文件的路徑。

有了 Node 之后,所有的信息都可以檢索到。

比如 name.

cout << "name:" << config["name"].as<string>() << endl;

as()表示將解析的內(nèi)容轉(zhuǎn)換成 string 類(lèi)型。
你也可以轉(zhuǎn)換成其它類(lèi)型。

它是一個(gè)模板方法。

有同學(xué)可能會(huì)有疑惑。

skills:  
  c++: 1
  java: 1
  android: 1
  python: 1

skills 的信息怎么讀呢?

其實(shí)也非常簡(jiǎn)單。

cout << "skills c++:" << config["skills"]["c++"].as<int>() << endl;
cout << "skills java:" << config["skills"]["java"].as<int>() << endl;
cout << "skills android:" << config["skills"]["android"].as<int>() << endl;
cout << "skills python:" << config["skills"]["python"].as<int>() << endl;

yaml-cpp 中的迭代

yaml-cpp 中也可以通過(guò)迭代的方式,訪(fǎng)問(wèn) Node 中的內(nèi)容。

比如,訪(fǎng)問(wèn) skills 下面的各個(gè)元素。

for(YAML::const_iterator it= config["skills"].begin(); it != config["skills"].end();++it)
{
    cout << it->first.as<string>() << ":" << it->second.as<int>() << endl;
}

用 begin() 獲取迭代器,用 end() 判斷迭代器是否結(jié)束。

NodeType

yaml 支持 Scalar、List、Map 類(lèi)型,yaml-cpp 通過(guò) NodeType 定義了 Node 的可能類(lèi)型

namespace YAML {
struct NodeType {
  enum value { Undefined, Null, Scalar, Sequence, Map };
};
}

對(duì)應(yīng)未定義、空、標(biāo)量、序列、字典。

YAML::Node test1 = YAML::Load("[1,2,3,4]");
cout << " Type: " << test1.Type() << endl;

YAML::Node test2 = YAML::Load("1");
cout << " Type: " << test2.Type() << endl;

YAML::Node test3 = YAML::Load("{'id':1,'degree':'senior'}");
cout << " Type: " << test3.Type() << endl;

上面的代碼是為了判斷 NodeType。

結(jié)果如下:

 Type: 3
 Type: 2
 Type: 4

分別對(duì)應(yīng) Sequence、Scalar、Map。

yaml-cpp 寫(xiě)配置文件

日常開(kāi)發(fā)中,除了讀取配置參數(shù),我們經(jīng)常需要保存參數(shù),yaml-cpp 自然也提供了相應(yīng)的功能。

ofstream fout("testconfig.xml");

config["score"] = 99;

fout << config;

fout.close();

前面代碼解析成功的 config,現(xiàn)在添加一個(gè) score,然后保存。

運(yùn)行代碼后,發(fā)現(xiàn) build 文件夾下正確保存了 testconfig.xml 文件,score 被正確添加進(jìn)去了。

name: frank
sex: male
age: 18
skills:
  c++: 1
  java: 1
  android: 1
  python: 1
score: 99

到此,yaml-cpp 的簡(jiǎn)單使用就 OK 了,讀者可以查看代碼去深入學(xué)習(xí)。
完整代碼:
yaml_test.cpp

#include <iostream>
#include <fstream>
#include <yaml-cpp/yaml.h>

using namespace std;

int main(int argc,char ** argv)
{
    YAML::Node config = YAML::LoadFile("../config/config.yaml");

    cout<<"Nod Type"<<config.Type()<<endl;
    cout<<"skills type" <<config["skills"].Type()<<endl;

    cout<<"name:"<<config["name"].as<string>()<<endl;
    cout<<"sex:"<<config["sex"].as<string>()<<endl;
    cout<<"age"<<config["age"].as<int>()<<endl;

    cout<<"skills c++:"<<config["skills"]["c++"].as<int>()<<endl;
    cout<<"skills java:"<<config["skills"]["java"].as<int>()<<endl;
    cout<<"skills android:"<<config["skills"]["android"].as<int>()<<endl;
    cout<<"skills python:"<<config["skills"]["python"].as<int>()<<endl;

    for (YAML::const_iterator it=config["skills"].begin(); it!=config["skills"].end(); ++it) {
        cout<<it->first.as<string>()<<":"<<it->second.as<int>()<<endl;
    }
    YAML::Node test1 = YAML::Load("[1,2,3,4]");
    cout<<"Type:"<<test1.Type()<<endl;

    YAML::Node test2 = YAML::Load("1");
    cout << " Type: " << test2.Type() << endl;

    YAML::Node test3 = YAML::Load("{'id':1,'degree':'senior'}");
    cout << " Type: " << test3.Type() << endl;

    ofstream fout("../config/testconfig.yaml");

    config["score"] = 99;

    fout << config;

    fout.close();

    return 0;

}

到此這篇關(guān)于c++ 開(kāi)發(fā)中讀寫(xiě)yaml配置文件的文章就介紹到這了,更多相關(guān)c++ 開(kāi)發(fā)中讀寫(xiě)yaml配置文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++實(shí)現(xiàn)LeetCode(115.不同的子序列)

    C++實(shí)現(xiàn)LeetCode(115.不同的子序列)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(115.不同的子序列),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C++實(shí)現(xiàn)廣度優(yōu)先遍歷圖

    C++實(shí)現(xiàn)廣度優(yōu)先遍歷圖

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)廣度優(yōu)先遍歷圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • C++中的作用域案例詳解

    C++中的作用域案例詳解

    作用域規(guī)定了標(biāo)識(shí)符在代碼中的可見(jiàn)性和可訪(fǎng)問(wèn)性,全局作用域中的標(biāo)識(shí)符可以在整個(gè)程序中使用,局部作用域中的標(biāo)識(shí)符只能在其所在的代碼塊中使用,而命名空間作用域提供了一種組織和封裝代碼的方式,以避免命名沖突,這篇文章主要介紹了C++中的作用域,需要的朋友可以參考下
    2024-02-02
  • 詳解如何將Spire.PDF for C++集成到C++程序中

    詳解如何將Spire.PDF for C++集成到C++程序中

    Spire.PDF for C++ 是一個(gè)專(zhuān)業(yè)的 PDF 庫(kù),供開(kāi)發(fā)人員在任何類(lèi)型的 C++ 應(yīng)用程序中閱讀、創(chuàng)建、編輯和轉(zhuǎn)換 PDF 文檔,本文主要介紹了兩種不同的方式將 Spire.PDF for C++ 集成到您的 C++ 應(yīng)用程序中,希望對(duì)大家有所幫助
    2023-11-11
  • C語(yǔ)言實(shí)現(xiàn)按月顯示的日歷

    C語(yǔ)言實(shí)現(xiàn)按月顯示的日歷

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)按月顯示的日歷,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • C++引用的使用與const修飾符

    C++引用的使用與const修飾符

    這篇文章介紹了C++引用使用與const修飾符,引用是給已經(jīng)定義的變量一個(gè)別名,可以簡(jiǎn)單理解成同一個(gè)變量的昵稱(chēng),既然是昵稱(chēng)或者是別名,顯然它和原本的變量名有著同樣的效力,所以我們對(duì)別名進(jìn)行修改,原本的變量值也一樣會(huì)發(fā)生變化,下面來(lái)看看詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-11-11
  • C++移除序列中連續(xù)重復(fù)的特定值示例代碼

    C++移除序列中連續(xù)重復(fù)的特定值示例代碼

    這篇文章主要給大家介紹了關(guān)于在C++中如何移除序列中連續(xù)重復(fù)的特定值,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-01-01
  • C++實(shí)例代碼詳解友元函數(shù)

    C++實(shí)例代碼詳解友元函數(shù)

    采用類(lèi)的機(jī)制后實(shí)現(xiàn)了數(shù)據(jù)的隱藏與封裝,類(lèi)的數(shù)據(jù)成員一般定義為私有成員,成員函數(shù)一般定義為公有的,依此提供類(lèi)與外界間的通信接口。但是,有時(shí)需要定義一些函數(shù),這些函數(shù)不是類(lèi)的一部分,但又需要頻繁地訪(fǎng)問(wèn)類(lèi)的數(shù)據(jù)成員,這時(shí)可以將這些函數(shù)定義為該類(lèi)的友元函數(shù)
    2022-06-06
  • C語(yǔ)言中進(jìn)制知識(shí)匯總

    C語(yǔ)言中進(jìn)制知識(shí)匯總

    在C語(yǔ)言里,整數(shù)有三種表示形式:十進(jìn)制,八進(jìn)制,十六進(jìn)制。 其中以數(shù)字0開(kāi)頭,由0~7組成的數(shù)是八進(jìn)制。以0X或0x開(kāi)頭,由0~9,A~F或a~f 組成是十六進(jìn)制。除表示正負(fù)的符號(hào)外,以1~9開(kāi)頭,由0~9組成是十進(jìn)制。
    2016-05-05

最新評(píng)論