C++项目代码学习笔记2

1. #include <yaml-cpp/yaml.h>

yaml-cpp是用c++实现的用来解析和生成yaml文件的,

首先说一下YAML是啥?(原文来自维基百科链接:https://zh.wikipedia.org/wiki/YAML)

YAML(/ˈjæməl/,尾音类似camel骆驼)是一个可读性高,用来表达资料序列化的格式。YAML参考了其他多种语言,包括:C语言、Python、Perl,并从XML、电子邮件的数据格式(RFC 2822)中获得灵感。Clark Evans在2001年首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。目前已经有数种编程语言或脚本语言支持(或者说解析)这种语言。

YAML是"YAML Ain't a Markup Language"(YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML的意思其实是:"Yet Another Markup Language"(仍是一种标记语言),但为了强调这种语言以数据为中心,而不是以标记语言为重点,而用反向缩略语重命名。

功能

YAML的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等资料形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件、倾印调试内容、文件大纲(例如:许多电子邮件标题格式和YAML非常接近)。尽管它比较适合用来表达层次结构式(hierarchical model)的数据结构,不过也有精致的语法可以表示关系性(relational model)的资料。[6]由于YAML使用空白字符和分行来分隔资料,使得它特别适合用grep/Python/Perl/Ruby操作。其让人最容易上手的特色是巧妙避开各种封闭符号,如:引号、各种括号等,这些符号在嵌套结构时会变得复杂而难以辨认。

示例(简单的文件,数据结构可以用类似大纲的缩进方式呈现)

---
receipt:     Oz-Ware Purchase Invoice
date:        2012-08-06
customer:
    given:   Dorothy
    family:  Gale
   
items:
    - part_no:   A4786
      descrip:   Water Bucket (Filled)
      price:     1.47
      quantity:  4

    - part_no:   E1628
      descrip:   High Heeled "Ruby" Slippers
      size:      8
      price:     133.7
      quantity:  1

bill-to:  &id001
    street: | 
            123 Tornado Alley
            Suite 16
    city:   East Centerville
    state:  KS

ship-to:  *id001   

specialDelivery:  >
    Follow the Yellow Brick
    Road to the Emerald City.
    Pay no attention to the
    man behind the curtain.
...

注意在YAML中,字符串不一定要用双引号标示。另外,在缩进中空白字符的数目并不是非常重要,只要相同层次结构的元素左侧对齐就可以了(不过不能使用TAB字符)。这个文件的顶层由七个键值组成:其中一个键值"items",是两个元素构成的数组(或称清单),这清单中的两个元素同时也是包含了四个键值的散列表。文件中重复的部分用这个方法处理:使用锚点(&)和引用(*)标签将"bill-to"散列表的内容复制到"ship-to"散列表。也可以在文件中加入选择性的空行,以增加可读性。在一个文件中,可同时包含多个文件,并用"---"分隔。选择性的符号"..."可以用来表示文件结尾(在利用流的通信中,这非常有用,可以在不关闭流的情况下,发送结束信号)。

YAML构成元素:

YAML的基本组件:YAML提供缩进/区块以及内置(inline)两种格式,来表示清单和散列表。以下展示几种YAML的基本原件。

清单(数组)
习惯上清单比较常用区块格式(block format)表示,也就是用短杠+空白字符作为起始。

--- # 最喜愛的電影

- Casablanca

- North by Northwest

- Notorious

另外还有一种内置格式(inline format)可以选择──用方括号围住,并用逗号+空白区隔(类似JSON的语法)。

--- # 購物清單

[milk, pumpkin pie, eggs, juice]

关系数组
键值和资料由冒号及空白字符分开。区块形式(常使用于YAML数据文档中)使用缩进和换行符分隔key: value对。内置形式(常使用于YAML数据流中)在大括号中使用逗号+空白字符分隔key: value对。

--- # 區塊形式

name: John Smith

age: 33

--- # 內置形式

{name: John Smith, age: 33}

区块的字符

再次强调,字符串不需要包在引号之内。有两种语法可以书写多行文字(multi-line strings),一种为保留换行(使用|字符),另一种为折叠换行(使用>字符)。两种语法在其特殊字符之后都必须接着换行。

保留换行(Newlines preserved)

data: |                                     # 譯者注:這是一首著名的五行民謠(limerick)
   There once was a man from Darjeeling     # 這裡曾有一個人來自大吉嶺
   Who got on a bus bound for Ealing        # 他搭上一班往伊靈的公車
       It said on the door                  # 門上這麼說的
       "Please don't spit on the floor"     # "請勿在地上吐痰"
   So he carefully spat on the ceiling      # 所以他小心翼翼的吐在天花板上

根据默认,每行开头的缩进(以首行为基准)和行末空白会被去除,而不同的缩进会保留差异。

折叠换行(Newlines folded)

data: >
   Wrapped text         # 摺疊的文字
   will be folded       # 將會被收
   into a single        # 進單一一個
   paragraph            # 段落
   
   Blank lines denote   # 空白的行代表
   paragraph breaks     # 段落之間的區隔

和保留换行不同的是,只有空白行才视为换行,原本的换行字符会被转换成空白字符,而行首缩进会被去除。

层次结构化的元素

于清单中使用散列表

- {name: John Smith, age: 33}
- name: Mary Smith
  age: 27

于散列表中使用清单

men: [John Smith, Bill Jones]
women:
  - Mary Smith
  - Susan Williams

YAML的高级组件

这部分算是一个后续的讨论,在比较各种数资料列语言时,YAML最常被提到的特色有两个:关系树和资料形态。

树状结构之间的交互引用

资料合并和参考

为了维持文件的简洁,并避免资料输入的错误,YAML提供了节点参考(*)和散列合并(<<)参考到其他节点标签的锚点标记(&)。参考会将树状结构加入锚点标记的内容,并可以在所有数据结构中运作(可以参考上面"ship-to"的示例)合并只有散列表可以使用,可以将键值自锚点标记复制到指定的散列表中。

当资料被instantiate合并和参考会被分析器自动展开。

#眼部雷射手術之標準程序
---
- step:  &id001                  # 定義錨點標籤 &id001
    instrument:      Lasik 2000
    pulseEnergy:     5.4
    pulseDuration:   12
    repetition:      1000
    spotSize:        1mm

- step:
     <<: *id001                  # 合併鍵值:使用在錨點標籤定義的內容
     spotSize:       2mm         # 覆寫"spotSize"鍵值

- step:
     <<: *id001                  # 合併鍵值:使用在錨點標籤定義的內容
     pulseEnergy:    500.0       # 覆寫鍵值
     alert: >                    # 加入其他鍵值
           warn patient of 
           audible pop

资料形态

由于自动判定资料形态的功能,严格类型(也就是用户有宣告的资料形态)很难在大部分的YAML文件中看到。资料类型可以被区分成三大类:原码(core),定义(defined),用户定义(user-defined)。原码可以自动被解析器分析(例如:浮点数,整数,字符串,清单,映射,...)。有一些高级的资料形态──例如比特资料──在YAML中有被“定义”,但不是每一种解析器都有支持。最后,YAML支持用户自定的区域变量,包括:自定义的类别,结构或基本类型(例如:四倍精度的浮点数)。

强制转型

YAML的自动判定资料形态是哪一种实体。但有时用户会想要将资料强制转型成自定的某种类型。最常见的状况是字符串,有时候可能看起来像数字或布尔值,这种时候可以使用双引号,或是使用严格类型标签。

---
a: 123                     # 整數
b: "123"                   # 字串(使用雙引號)
c: 123.0                   # 浮點數
d: !!float 123             # 浮點數,使用!!表達的嚴格型態
e: !!str 123               # 字串,使用嚴格型態
f: !!str Yes               # 字串,使用嚴格型態
g: Yes                     # 布林值"真"
h: Yes we have No bananas  # 字串(包含"Yes"和"No")

其他特殊资料形态

除了一般的资料形态之外,用户也可以使用一些较为高级的类型,但不保证可被每种解析器分析。使用时和强制转型类似,要在形态名称之前加上两个惊叹号(!!)。有几种重要的形态在本篇没有讨论,包括集合(sets),有序映照(ordered maps),时间戳记(timestamps)以及十六进制资料(hexadecimal)。下面这个示例则是比特资料(binary)

---
picture: !!binary |
 R0lGODdhDQAIAIAAAAAAANn
 Z2SwAAAAADQAIAAACF4SDGQ
 ar3xxbJ9p0qa7R0YxwzaFME
 1IAADs=

用户自行扩展的资料形态

许多YAML的实现允许用户自定义资料形态。在将一个对象序列化时,这个方法还颇方便的。某些区域资料形态可能不存在默认的资料形态中,不过这种类型在特定的YAML应用程序中是有定义的。这种区域资料形态用惊叹号( ! )表示。

---
myObject:  !myClass { name: Joe, age: 15}

语法

在yaml.org[8](英文)可以找到轻巧而好用的小抄[9](亦是用YAML表示)及格式说明[10]。下面的内容,是关于基本组件的摘要。

  • YAML使用可打印的Unicode字符,可使用UTF-8UTF-16
  • 使用空白字符为文件缩进来表示结构;不过不能使用跳格字符(TAB)。
  • 注解由井字号( # )开始,可以出现在一行中的任何位置,而且范围只有一行(也就是一般所谓的单行注解)
  • 每个清单成员以单行表示,并用短杠+空白( -   )起始。或使用方括号 [ ] ),并用逗号+空白( ,   )分开成员。
  • 每个散列表的成员用冒号+空白( :   )分开键值和内容。或使用大括号( {   } ),并用逗号+空白( ,   )分开。
    • 散列表的键值可以用问号 ( ? )起始,用来明确的表示多个词汇组成的键值。
  • 字符串平常并不使用引号,但必要的时候可以用双引号 ( " )或单引号 ( ' )框住。
    • 使用双引号表示字符串时,可用倒斜线( \ )开始的转义字符(这跟C语言类似)表示特殊字符。
  • 区块的字符串用缩进和修饰符(非必要)来和其他资料分隔,有新行保留(preserve)(使用符号 | )或新行折叠(flod)(使用符号 > )两种方式。
  • 在单一文件中,可用连续三个连字号---)区分多个文件。
    • 另外,还有选择性的连续三个点号( ... )用来表示文件结尾。
  • 重复的内容可使从参考标记星号 ( * )复制到锚点标记( & )。
  • 指定格式可以使用两个惊叹号 ( !! ),后面接上名称。
  • 文件中的单一文件可以使用指导指令,使用方法是百分比符号( % )。有两个指导指令在YAML1.1版中被定义:
    • %YAML 指导指令,用来识别文件的YAML版本。
    • %TAG 指导指令,被用在URI的前缀标记。这个方法在标记节点的类型时相当有用。

YAML在使用逗号及冒号时,后面都必须接一个空白字符,所以可以在字符串或数值中自由加入分隔符号(例如:5,280或http://www.wikipedia.org)而不需要使用引号。

另外还有两个特殊符号在YAML中被保留,有可能在未来的版本被使用--( @ )和( ` )。

YAML cheet sheet:

%YAML 1.1   # Reference card
---
Collection indicators:
  '? ' : Key indicator.
  ': ' : Value indicator.
  '- ' : Nested series entry indicator.
  ', ' : Separate in-line branch entries.
  '[]' : Surround in-line series branch.
  '{}' : Surround in-line keyed branch.
Scalar indicators:
  '''' : Surround in-line unescaped scalar ('' escaped ').
  '"'  : Surround in-line escaped scalar (see escape codes below).
  '|'  : Block scalar indicator.
  '>'  : Folded scalar indicator.
  '-'  : Strip chomp modifier ('|-' or '>-').
  '+'  : Keep chomp modifier ('|+' or '>+').
  1-9  : Explicit indentation modifier ('|1' or '>2').
         # Modifiers can be combined ('|2-', '>+1').
Alias indicators:
  '&'  : Anchor property.
  '*'  : Alias indicator.
Tag property: # Usually unspecified.
  none    : Unspecified tag (automatically resolved by application).
  '!'     : Non-specific tag (by default, "!!map"/"!!seq"/"!!str").
  '!foo'  : Primary (by convention, means a local "!foo" tag).
  '!!foo' : Secondary (by convention, means "tag:yaml.org,2002:foo").
  '!h!foo': Requires "%TAG !h! <prefix>" (and then means "<prefix>foo").
  '!<foo>': Verbatim tag (always means "foo").
Document indicators:
  '%'  : Directive indicator.
  '---': Document header.
  '...': Document terminator.
Misc indicators:
  ' #' : Throwaway comment indicator.
  '`@' : Both reserved for future use.
Special keys:
  '='  : Default "value" mapping key.
  '<<' : Merge keys from another mapping.
Core types: # Default automatic tags.
  '!!map' : { Hash table, dictionary, mapping }
  '!!seq' : { List, array, tuple, vector, sequence }
  '!!str' : Unicode string
More types:
  '!!set' : { cherries, plums, apples }
  '!!omap': [ one: 1, two: 2 ]
Language Independent Scalar types:
  { ~, null }              : Null (no value).
  [ 1234, 0x4D2, 02333 ]   : [ Decimal int, Hexadecimal int, Octal int ]
  [ 1_230.15, 12.3015e+02 ]: [ Fixed float, Exponential float ]
  [ .inf, -.Inf, .NAN ]    : [ Infinity (float), Negative, Not a number ]
  { Y, true, Yes, ON  }    : Boolean true
  { n, FALSE, No, off }    : Boolean false
  ? !!binary >
      R0lG...BADS=
  : >-
      Base 64 binary value.
Escape codes:
 Numeric   : { "\x12": 8-bit, "\u1234": 16-bit, "\U00102030": 32-bit }
 Protective: { "\\": '\', "\"": '"', "\ ": ' ', "\<TAB>": TAB }
 C         : { "\0": NUL, "\a": BEL, "\b": BS, "\f": FF, "\n": LF, "\r": CR,
             "\t": TAB, "\v": VTAB }
 Additional: { "\e": ESC, "\_": NBSP, "\N": NEL, "\L": LS, "\P": PS }
...

2. std::nullopt

定义于头文件 <optional>

inline constexpr nullopt_t nullopt{/*unspecified*/};

(C++17 起)

std::nulloptstd::nullopt_t 类型常量,用于指示 optional 类型有未初始化状态。

参阅

nullopt_t

(C++17)

带未初始化状态的 optional 类型的指示器
(类)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值