@@ -421,7 +421,7 @@ <h2 id="index-_1">前言</h2>
421421<blockquote>
422422<p><img src="../img/bulb.png" height="30px" width="auto" style="margin: 0; border: none"/> 本书还在持续更新中……要追番的话,可以在 <a href="https://github.com/parallel101/cppguidebook">GitHub</a> 点一下右上角的 “Watch” 按钮,每当小彭老师提交新 commit,GitHub 会向你发送一封电子邮件,提醒你小彭老师更新了。</p>
423423</blockquote>
424- <p>更新时间:2025年02月26日 10:08:22 (UTC+08:00)</p>
424+ <p>更新时间:2025年02月26日 10:10:17 (UTC+08:00)</p>
425425<p><a href="https://parallel101.github.io/cppguidebook">在 GitHub Pages 浏览本书</a> | <a href="https://142857.red/book">在小彭老师自己维护的镜像上浏览本书</a></p>
426426<h2 id="index-_2">格式约定</h2>
427427<blockquote>
@@ -16914,7 +16914,7 @@ <h3 id="unicode-utf-8_2">UTF-8 确实几乎完美支持字符串所有操作</h3
1691416914// 会打印 “小�”
1691516915</code></pre>
1691616916<pre><code class="language-cpp">std::u32string s = U"小彭老师公开课万岁";
16917- fmt::println("UTF-32 下,前四个字符:{}", s.substr(0, 4));
16917+ fmt::println("UTF-32 下,前四个字符:{}", utf8::utf32to8( s.substr(0, 4) ));
1691816918// 会打印 “小彭老师”
1691916919</code></pre>
1692016920<p>只有当索引是来自 <code>find</code> 的结果时,UTF-8 字符串的切片才能正常工作:</p>
@@ -16925,7 +16925,7 @@ <h3 id="unicode-utf-8_2">UTF-8 确实几乎完美支持字符串所有操作</h3
1692516925</code></pre>
1692616926<pre><code class="language-cpp">std::u32string s = U"小彭老师公开课万岁";
1692716927size_t pos = s.find(U'公'); // pos = 4
16928- fmt::println("UTF-32 下,“公”前的所有字符:{}", s.substr(0, pos));
16928+ fmt::println("UTF-32 下,“公”前的所有字符:{}", utf8::utf32to8( s.substr(0, pos) ));
1692916929// 会打印 “小彭老师”
1693016930</code></pre>
1693116931<blockquote>
@@ -16938,7 +16938,7 @@ <h3 id="unicode-utf-8_2">UTF-8 确实几乎完美支持字符串所有操作</h3
1693816938// 也可能是乱码“�”,取决于终端理解的编码格式
1693916939</code></pre>
1694016940<pre><code class="language-cpp">std::u32string s = U"小彭老师公开课万岁";
16941- fmt::print("UTF-32 下第一个字符:{}", s[0] );
16941+ fmt::print("UTF-32 下第一个字符:{}", utf8::utf32to8(s.substr(0, 1)) );
1694216942// 会打印 ‘小’
1694316943</code></pre>
1694416944<p>UTF-8 字符串的反转也会出问题:</p>
@@ -17325,8 +17325,8 @@ <h3 id="unicode-utf-8_3">UTF-8 阵营</h3>
1732517325<p>方法1:使用 <code>utf8to32</code> 一次性完成转换,用完后再转回去。</p>
1732617326<pre><code class="language-cpp">std::string s = "你好";
1732717327std::u32string u32 = utf8::utf8to32(s);
17328- fmt::println("U+{:04X}", u32[0]);
17329- fmt::println("U+{:04X}", u32[1]);
17328+ fmt::println("U+{:04X}", static_cast<std::uint32_t>( u32[0]) );
17329+ fmt::println("U+{:04X}", static_cast<std::uint32_t>( u32[1]) );
1733017330u32[1] = U'坏';
1733117331s = utf8::utf32to8(u32);
1733217332fmt::println("{}", s); // 你坏
@@ -17337,7 +17337,7 @@ <h3 id="unicode-utf-8_3">UTF-8 阵营</h3>
1733717337utf8::unchecked::iterator<char *> eit(s + strlen(s));
1733817338for (auto it = bit; it != eit; ++it) {
1733917339 // *it: char32_t
17340- fmt::println("U+{:04X}", *it);
17340+ fmt::println("U+{:04X}", static_cast<std::uint32_t>( *it) );
1734117341}
1734217342
1734317343// 安全(带边界检测)的版本
@@ -17346,7 +17346,7 @@ <h3 id="unicode-utf-8_3">UTF-8 阵营</h3>
1734617346utf8::iterator<char *> eit(s + strlen(s), s, s + strlen(s));
1734717347for (auto it = bit; it != eit; ++it) {
1734817348 // *it: char32_t
17349- fmt::println("U+{:04X}", *it);
17349+ fmt::println("U+{:04X}", static_cast<std::uint32_t>( *it) );
1735017350}
1735117351
1735217352// 基于 std::string 的版本
@@ -17355,7 +17355,7 @@ <h3 id="unicode-utf-8_3">UTF-8 阵营</h3>
1735517355utf8::iterator<std::string::iterator> eit(s.end(), s.begin(), s.end());
1735617356for (auto it = bit; it != eit; ++it) {
1735717357 // *it: char32_t
17358- fmt::println("U+{:04X}", *it);
17358+ fmt::println("U+{:04X}", static_cast<std::uint32_t>( *it) );
1735917359}
1736017360</code></pre>
1736117361<p>由于迭代器接口复杂难懂,建议先封装成带有 <code>begin()</code> 和 <code>end()</code> 的 range 对象,方便使用 C++17 range-based loop 语法直观遍历:</p>
@@ -17378,7 +17378,7 @@ <h3 id="unicode-utf-8_3">UTF-8 阵营</h3>
1737817378// 以下是新类的使用方法
1737917379std::string s = "你好";
1738017380for (char32_t c : Utf8Range(s)) {
17381- fmt::println("U+{:04X}", c );
17381+ fmt::println("U+{:04X}", static_cast<std::uint32_t>(c) );
1738217382}
1738317383</code></pre>
1738417384<h3 id="unicode-utf-16_2">UTF-16 阵营</h3>
@@ -17441,8 +17441,8 @@ <h3 id="unicode-utf-16_2">UTF-16 阵营</h3>
1744117441<p>在刚刚介绍的 C++ 库 <code>utfcpp</code> 中,也有针对 UTF-16 的转换函数,如 <code>utf16to32</code>:</p>
1744217442<pre><code class="language-cpp">std::u16string s = u"你好";
1744317443std::u32string u32 = utf16::utf16to32(s);
17444- fmt::println("U+{:04X}", u32[0]);
17445- fmt::println("U+{:04X}", u32[1]);
17444+ fmt::println("U+{:04X}", static_cast<std::uint32_t>( u32[0]) );
17445+ fmt::println("U+{:04X}", static_cast<std::uint32_t>( u32[1]) );
1744617446u32[1] = U'𰻞';
1744717447s = utf16::utf32to16(u32);
1744817448fmt::println("{}", s); // 你𰻞
0 commit comments