@@ -83,14 +83,22 @@ std::wstring utf8_to_wstring(std::string const &s) {
83
83
## 读取整个文件到字符串
84
84
85
85
``` cpp
86
- TODO
86
+ std::string file_get_content (std::string const &filename) {
87
+ std::ifstream ifs(filename, std::ios::in | std::ios::binary);
88
+ std::istreambuf_iterator<char > iit(ifs), iite;
89
+ std::string content(iit, iite);
90
+ return content;
91
+ }
92
+
93
+ void file_put_content(std::string const &filename, std::string const &content) {
94
+ std::ofstream ofs(filename, std::ios::out | std::ios::binary);
95
+ ofs << content;
96
+ }
87
97
```
88
98
89
- ## 位域(bit-field)
99
+ 这样就可以把整个文件读取到内存中,进行处理后再写回文件。
90
100
91
- ``` cpp
92
- TODO
93
- ```
101
+ > {{ icon.detail }} 用 `std::ios::binary` 选项打开文件,是为了避免文件中出现 `'\n'` 时,被 MSVC 标准库自动转换成 `'\r\n'`,以保证跨平台。
94
102
95
103
## 别再写构造函数啦!
96
104
@@ -1739,8 +1747,42 @@ func(temporary(1));
1739
1747
1740
1748
> {{ icon.warn }} 临时变量的生命周期是一行
1741
1749
1750
+ ## ostringstream 格式化字符串
1751
+
1752
+ ``` cpp
1753
+ std::string name = " 你好" ;
1754
+ int answer = 42 ;
1755
+ auto str = std::format(" 你好,{}!答案是 {},十六进制:0x{:02x}\n " , name, answer, answer);
1756
+ ```
1757
+
1758
+ 没有 C++20 之前,要么使用第三方的 ` fmt::format ` ,要么只能使用字符串的 ` + ` 运算符拙劣地拼接:
1759
+
1760
+ ``` cpp
1761
+ auto str = std::string(" 你好," ) + name + " !答案是 " + std::to_string(answer) + " ,十六进制:0x" + std::to_string(answer) + " \n " ;
1762
+ ```
1763
+
1764
+ 这样做效率低下,且不易阅读。而且也无法实现数字按“十六进制”转字符串。
1765
+
1766
+ 可以用 ` std::ostringstream ` ,其用法与 ` std::cout ` 相同。只不过会把结果写入一个字符串(而不是直接输出),可以用 ` .str() ` 取出那个字符串。
1767
+
1768
+ ``` cpp
1769
+ #include < sstream>
1770
+
1771
+ std::ostringstream oss;
1772
+ oss << " 你好," << name << " !答案是 " << answer << " ,十六进制:0x" << std::hex << std::setfill(' 0' ) << std::setw(2 ) << answer << " \n " ;
1773
+ auto str = oss.str();
1774
+ ```
1775
+
1776
+ 利用临时变量语法,可以浓缩写在一行里,做个 format 拙劣的模仿者:
1777
+
1778
+ ``` cpp
1779
+ auto str = (std::ostringstream() << " 你好," << name << " !答案是 " << answer << " ,十六进制:0x" << std::hex << std::setfill(' 0' ) << std::setw(2 ) << answer << " \n " ).str();
1780
+ ```
1781
+
1742
1782
## ADL 机制
1743
1783
1784
+ TODO
1785
+
1744
1786
## shared_from_this
1745
1787
1746
1788
## requires 语法检测是否存在指定成员函数
@@ -1749,6 +1791,35 @@ func(temporary(1));
1749
1791
1750
1792
## 成员函数针对 this 的移动重载
1751
1793
1794
+ ## 位域(bit-field)
1795
+
1796
+ 在互联网编程和各种与硬盘、序列化打交道的场景中,常常需要按位拆分单个字节。
1797
+
1798
+ C 语言有专门照顾此类工作的语法糖:位域。
1799
+
1800
+ 位域是一种特殊的结构体成员,可以对位进行分组,方便读取。例如,我们想要从一个字节中读取三个状态位:
1801
+
1802
+ ``` cpp
1803
+ struct Flag {
1804
+ uint8_t a : 4; // 低 4 位
1805
+ uint8_t b : 4; // 高 4 位
1806
+ };
1807
+
1808
+ sizeof(Flag); // 1 字节大小(共 8 位)
1809
+
1810
+ Flag f = std::bit_cast<Flag >(0x21);
1811
+ f.a; // 0x1
1812
+ f.b; // 0x2
1813
+ ```
1814
+
1815
+ 以上的代码等价于:
1816
+
1817
+ ```cpp
1818
+ uint8_t f = 0x21;
1819
+ int a = f & 0xF; // 0x1
1820
+ int b = f >> 4; // 0x2
1821
+ ```
1822
+
1752
1823
<!-- ## vector + unordered_map = LRU cache -->
1753
1824
<!-- -->
1754
1825
<!-- ## Lambda 捕获 unique_ptr 导致 function 报错怎么办 -->
0 commit comments