What & How & Why

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录前一修订版
后一修订版
前一修订版
cs:programming:cpp:courses:cpp_basic_deep:chpt_3 [2024/04/17 23:51] – [多维数组的初始化] codingharecs:programming:cpp:courses:cpp_basic_deep:chpt_3 [2024/04/18 04:55] (当前版本) – [string 的使用方法] codinghare
行 305: 行 305:
 int a[][4] = {1,2,3,4}; // int[1][4] int a[][4] = {1,2,3,4}; // int[1][4]
 </code> </code>
-===多维数组的引和遍历===+===多维数组的遍历=== 
 +  * 多维数组遍历需要多重循环 
 +<code cpp> 
 +int x [3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}; 
 + 
 +//range for 
 +//注意所有外层的 auto 都需要以用的方式将数组类型传递给内层循环 
 +//否则,内层循环只会得到一个指向外层数组的指针 
 +//内层循环中 range for 需要使用数组的头指针作为起点,头指针 + 内层数组的长度作为终点进行循环 
 +//如果传入的是指针,长度信息丢失,那么将无法进行循环 
 +for (auto &row : x) 
 +
 +    for (auto col : row) 
 +    { 
 +        std::cout << col << " "; 
 +    } 
 +    std::cout << std::endl; 
 +
 + 
 +//while loop 
 +//注意 std::size() 的参数不同 
 +//遍历的顺序:x[0][0-3], x[1][1-3], x[2][1-3]。 
 +//推荐行优先遍历,可以减少 cache miss。 
 +size_t outter = 0; 
 +while (outter < std::size(x)) 
 +
 +    size_t inner = 0; 
 +    while (inner < std::size(x[inner])) 
 +    { 
 +        std::cout << x[outter][inner] <<" "; 
 +        inner++; 
 +    } 
 +    outter++; 
 +    std::cout << std::endl;  
 +
 +//纯指针遍历 
 +//与之前相同,cbegin 和 cend 需要数组而不是指针,因此内循环需要解引用 
 +auto OutterP = std::cbegin(x); 
 +while (OutterP != std::cend(x)) 
 +
 +    auto InnerP = std::cbegin(*OutterP); 
 +    { 
 +        while(InnerP != std::cend(*OutterP)) 
 +        { 
 +            std::cout << *InnerP << " "; 
 +            InnerP++; 
 +        } 
 +        std::cout << std::endl; 
 +    } 
 +    OutterP++; 
 +
 +</code> 
 + 
 +===多维数组与指针=== 
 +  * 多维数组也可以转化为指针,但只有最高维会进行转换 
 +    * 对于外围数组,如果指针要有意义,其指向的单位一定是外围数组的元素 
 +    * 比如下面的例子,外围数组有3个元素,如果移动指针 ''x+1'',则移动的单位实际上是一个包含 4 个 int 的数组 
 +<code cpp> 
 +int x[3][4]; 
 +// ptr int(*)[4] 
 +auto ptr = x; 
 +//ptr2 int(*)[4][5] 
 +int y[3][4][5]; 
 +auto ptr2 = y; 
 +</code> 
 +==使用类型别名声明多维数组的指针== 
 +<code cpp> 
 +using A2 = Int[4][5]; 
 +int x[3][4][5]; 
 +A2* ptr = x; //x 指向 int[4][5] 
 +</code> 
 +注意类型别名会改变维度的优先级: 
 +<code cpp> 
 +using A = int[4]; 
 +//如果这里使用 A 定义数组,那么结果会是 [4][3] 而不是 [3][4] 
 +A z2[3]; //等价与 int z2[4][3]; 
 +</code> 
 +====Vector==== 
 +  * 标准库提供的序列容器(类模板) 
 +  * 可复制,可动态更改个数 
 +<code cpp> 
 +//使用需要包含头文件 vector 
 +#include <vector> 
 +//类型是 vector<int> 
 +std::vector<int> x = {1,2,3}; 
 +//可复制 
 +std::vector<int> y; 
 +y = x; 
 +</code> 
 +===Vector 的初始化=== 
 +  * 默认初始化为 0 个元素 
 +  * 支持各种初始化 
 +<code cpp> 
 +//聚合初始化,x 的元素为 1,2,3 
 +//使用 brace 
 +std::vector<int> x = {1,2,3}; 
 + 
 +//init with default element count 
 +//使用panthesis 
 +//y 是 3个元素的 vector,每个元素都被默认初始化为 0 
 +std::vector<int> y(3); 
 +//count + value 
 +//z 中有 3 个元素 都是 1 
 +std::vector<int> z(3,1); 
 +</code> 
 +===Vector 的常用成员函数=== 
 +<code cpp> 
 +//计算 vector 的大小 
 +x.size(); 
 +// 查看 vector 是否为空 
 +x.empty(); 
 +// 添加元素(运行期) 
 +x.push_back(4); 
 +// 删除元素 
 +x.pop_back(); 
 +// index 访问 
 +x[2]; //无安全保证 
 +x.at(2); //越界访问会抛出异常 
 + 
 +//成员 begin & end,指向第一个元素和最后一个元素 
 +auto beg = x.begin(); 
 +auto e = x.end(); 
 +</code> 
 +===Vector 的遍历=== 
 +<code cpp> 
 +//成员函数 + 迭代器(类指针) 
 +//注意 begin / end 的结果不再是指针,是 iterator 
 +auto vBeg = x.begin(); 
 +auto vEnd = x.end(); 
 +while(vBeg != vEnd) 
 +
 +    std::cout << *vBeg << " "; 
 +    vBeg++; 
 +
 +//range for 
 +for (auto elem : x) 
 +    { 
 +         std::cout << elem << " "; 
 +    } 
 +</code> 
 +===迭代器=== 
 +  * std 容器中,通常使用迭代器模拟代替指针 
 +  * 迭代器可以: 
 +    * 解引用 
 +    * 下标访问会产生 *(x + index) 的行为 
 +    * 可以移动,相减(必须指向同一个 vector) 
 +==Vector 的比较== 
 +  * 位数相同且元素相同,则相等 
 +  * 如果一长一短,短 vector 与长 vector 对应位置内容相同,则长的较大 
 +  * 否则按位比较,找到的第一组不相同元素中,较大元素所在的 vector 较大 
 +===Vector 的其他细节=== 
 +  * 改变 vector 元素数量可能会导致迭代器失效 
 +  * Vector 支持多维 
 +<code cpp> 
 +//元素是 Int vector 的 vector 
 +std::vector<std::vector<int>> x; 
 +</code> 
 +  * 支持取地址并调用运算符(''->'') 
 +<code cpp> 
 +std::vector<int>* ptr = &x; 
 +ptr->size(); //equal *(ptr).size() 
 +</code> 
 +  * size() 返回的是 ''size_type'' 
 +====std::string==== 
 +  * 特化自 ''std::basic_string<char>'' 
 +  * 可复制,可改变字符串长度 
 +===string 的使用方法=== 
 +<code cpp> 
 +//需要引入头文件 
 +#include <string> 
 +//初始化 
 +std::string myStr = "helleworld"; 
 + 
 +//使用多次复制目标字符作为初始值 
 +//结果是 'aaa' 
 +std::string myStr2(3, 'a'); 
 +//拷贝初始化 
 +std::string myStr3 = myStr; 
 +std::string myStr4(myStr); 
 + 
 +//比较尺寸size & empty 
 +//比较 == > <,比较规则与 vector 同,按字符为单位比较 
 +//赋值 
 +std::string newStr; 
 +newStr = myStr; 
 +//拼接 
 +newStr = myStr + myStr2; 
 +newStr = myStr + "hellWorld"; 
 +//string + 的重载左边要求对象类型是 std::string,所以 c-string 不能放到加号左边 
 +//error 
 +newStr = "hello" + myStr; 
 +//索引 
 +myStr[0]; 
 +</code> 
 +==转化 std::string 到 c-string== 
 +<code cpp> 
 +//返回指向一个 Null teminated(\0) 的 const char* 指针 
 +myStr.c_str(); 
 +</code>