前言:
本章节主要是笔者在学习c++中的批量处理的任务,核心的笔记学习内容包括最常见的循环,数组,以及更为重要的vector向量的内容,以及其存储中的栈,堆等知识点。
1.for循环
注意点:
1.continue :结束当前循环,执行下一次循环。
2.break: 跳出整个for循环,结束。
3.嵌套for,尽量不超过三层
1.基础for循环的使用
cpp
#include<iostream>
using namespace std;
auto length{ 10 };
int main(int argc,char *argv[],char *env[]) {
//continue 和 break
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
continue;
}
cout << i << " ";
if (i > 50) {
break;
}
}
}
/*
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51
*/
2.嵌套for循环的使用
cpp
#include<iostream>
using namespace std;
int main(int argc,char *argv[],char *env[]) {
//嵌套for,尽量不超过三层
cout << "" << endl;
for (int i = 0; i < 3; i++) {
for (size_t j = 0; j < 3; j++)
{
cout << "第" << i << "行" << ",第" << j <<"列"<< " ";
}
cout << endl;
}
}
/*
第0行,第0列 第0行,第1列 第0行,第2列
第1行,第0列 第1行,第1列 第1行,第2列
第2行,第0列 第2行,第1列 第2行,第2列
*/
3.无限for循环 == while
cpp
#include<iostream>
using namespace std;
int main(int argc,char *argv[],char *env[]) {
//无限循环
int index = 0;
for (;;) {
if (index > 10)break;
cout << "index:" << index << endl;
++index;
}
}
/*
index:0
index:1
index:2
index:3
index:4
index:5
index:6
index:7
index:8
index:9
index:10
*/
2.while循环
1.基础样式
注意点:
1.while(条件) {条件必须做更改/break}否则就会无限循环。
cpp
#include<iostream>
#include<cstdlib>
using namespace std;
int main() {
int index{ 0 };
while (index++ < 10) {
cout << index << " ";
}
cout << endl;
index = 0;
while (++index < 10) {
cout << index << " ";
}
cout << endl;
}
/*
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9
*/
2.经典案例
知识点:
1.
cin.rdbuf()->in_avail():检查缓冲区是否有未读取的有效内容2./执行系统命令:system需传入C风格字符串(const char*),c_str()将string转成const char*。
cppstring arg; // 存储ls的参数(如test) /*检查输入缓冲区是否有剩余内容(判断ls是否带参数) cin.rdbuf()->in_avail():返回输入缓冲区中可读取的字符数 >1的原因:若仅输入ls+回车,缓冲区只剩换行符(字符数=1);若带参数(如ls test),缓冲区字符数>1 */ if (cin.rdbuf()->in_avail() > 1) { cin >> arg; // 读取缓冲区中的参数(如test) execcmd += " " + arg; // 拼接命令:dir + 空格 + 参数 → "dir test" } // 执行系统命令:system需传入C风格字符串(const char*),c_str()将string转成const char* system(execcmd.c_str());
cpp
// 引入输入输出流库:支持cout(输出)、cin(输入)、cerr(错误输出)
#include<iostream>
// 引入字符串类库:支持std::string类型(处理命令字符串)
#include<string>
// 启用标准命名空间:避免每次写std::cout、std::string等前缀
using namespace std;
int main() {
/*
1.实现一个在windows上支持ls命令的shell
2.cin 用来接受用户输入
3.使用system 调用dir命令模拟ls
4.支持ls不传参数和传递参数
5.用户输入exit/quit退出
*/
{
// 循环退出标志:初始为false
bool is_exit{ false };
// ========== 核心:while循环实现Shell持续运行 ==========
// 循环条件:!is_exit → 只要is_exit是false,循环就一直执行
while (!is_exit) {
string cmd; // 存储用户输入的核心命令(如ls、exit)
string execcmd; //存储最终要执行的系统命令(如dir、dir test)
// 输出Shell提示符,模拟Linux的"$"或Windows的">"
cout << "xshell>>";
cin >> cmd;
if (cmd == "ls") {
// Windows下无ls,用dir模拟,先初始化执行命令为dir
execcmd = "dir";
//存储ls的参数
string arg;
// cin.rdbuf()->in_avail():返回输入缓冲区中可读取的字符数
//>1的原因:若仅输入ls+回车,缓冲区只剩换行符(字符数=1);
//若带参数(如ls test),缓冲区字符数>1
if (cin.rdbuf()->in_avail() > 1) {
//缓冲区有内容
cin >> arg;
execcmd += " " + arg; // 拼接命令:dir + 空格 + 参数 → "dir test"
}
// 执行系统命令:system需传入C风格字符串(const char*)
//c_str()将string转成const char*
system(execcmd.c_str());
// ========== 分支2:处理退出命令 ==========
}else if (cmd == "exit" || cmd == "quit") {
is_exit = true;
continue;
}
// ========== 分支3:处理不支持的命令 ==========
else {
cerr << "命令" << cmd << "不支持" << endl;
}
}
}
return 0;
}
3.array数组
基本概念:
1.数组定义了一块连续的地址空间,下标指向首元素的地址。
2.数组的数据类型决定了其占内存的大小。
数组的分类和特性:
类型 存储位置 生命周期 核心注意点 栈区数组 栈区 作用域结束自动释放 大小编译期确定、不宜过大 堆区数组 堆区 手动 delete[]释放易内存泄漏 / 堆损坏、大小运行时定 std::vector对象在栈、数据在堆 作用域结束自动释放(含堆数据) 复制默认深拷贝、传参用引用 / 指针
1.栈区数组:作用域生效时分配空间,出作用域后自动释放。
2.堆区数组:堆区内存由程序员通过
new[]手动分配,语言层面不会自动释放 ;如果不主动delete[],会造成内存泄漏。3.vector容器:vector 对象本身(控制块)若为局部变量,存储在栈区;内部元素的存储区在堆区。
特性 栈区数组 堆区数组 vector 容器 内存管理 自动 手动 自动 大小灵活性 编译期固定 运行时动态 运行时动态 安全性 越界无检查 越界无检查 有边界检查 跨作用域复用 不可 可(需传指针) 可(传引用) 性能 极快 较慢 接近堆数组
1.栈区数组
栈区空间大小申请:
1.通过中括号中数值控制。
2.数组大小设置仅支持constexpr编译时常量,不支持运行时常量和变量**(说白了就是设置的时候就已经设置好其大小了)**。
空间大小的计算:
sizeof(arr)
注意:数组一旦经过函数传递,就拿不到实际空间,会转化为指针。
优点:不用考虑其空间释放问题(只要出了作用域就释放)。
缺点:没有办法将栈区的空间直接移到另外一个函数/作用域中使用。
如果非要使用就只能复制,其存储成本很高
int arr[10];
string strs[10];
char str[10];
cpp
#include <iostream>
using namespace std;
int main() {
//栈区数组{括号内的区域},不同栈区的数组名称可以一样。
{ //数组类型 变量名[数组数量] 初始化值
//其中 arr1 存储的是数组首个元素的地址
int arr1[4]{ 0 };
//c++11的for遍历
for (int a : arr1)
cout << "a:" << a <<" ";
cout << endl;
arr1[0] = 99; //下标从0开始
arr1[2] = 88;
for (int a : arr1)
cout << "a:" << a << " ";
cout << endl;
//每个int是4个字节,这里四个int
cout << "sizeof(arr1) = " << sizeof(arr1) << endl; //sizeof(arr1) = 16
//如果没有初始化,值不确定
int arr2[4];
//c++11的for遍历
for (int a : arr2)
cout << "a:" << a << " ";
cout << endl;
//栈区数组的空间只能用编译时常量
//c++11前的
const int csize = 5;
//c++11后我们可以定义时直接明确,编译时常量
constexpr int cesize1 = 6;
int arr3[csize];
int arr4[cesize1];
cout << "sizeof(arr3):" << sizeof(arr3) << endl;
cout << "sizeof(arr4):" << sizeof(arr4) << endl;
//数组的初始化方法:
int arr5[5] = { 1,2,3,4,5 };
int arr6[] = { 1,2,3,4,5,6,7,8 };
cout << "sizeof(arr6) = " << sizeof(arr6) << endl;
//数组是地址连续的空间 变量中的arr1和第一个元素arr1[0]值是相同的
cout << "arr1 =" << (long long) arr1 << endl; //地址存储的首地址arr1 = 112732140792
cout << "&arr1[0] = " <<(long long) & arr1[0] << endl;
cout << "&arr1[1] = " <<(long long) &arr1[1] << endl;
cout << "&arr1[2] = " <<(long long) &arr1[2] << endl;
cout << "&arr1[3] = " <<(long long) &arr1[3] << endl;
//数组变量名本身存储的是首元素的地址,此处的加减是对元素数量进行改变,得到的还是地址
cout << "arr1+2 = " << (long long)(arr1 + 2) << endl;
cout << "arr1+3 = " << (long long)(arr1 + 3) << endl;
//将上述的地址进行取值(不常用,认识就好)
cout << "*(arr1+2) = " << *(arr1 + 2) << endl; //88
/*
arr1 =112732140792
&arr1[0] = 112732140792
&arr1[1] = 112732140796
&arr1[2] = 112732140800
&arr1[3] = 112732140804
*/
}
}
*2.堆区数组
(看得懂历史代码即可,常用开发慎用)
cpp
#include <iostream>
using namespace std;
int main() {
// 1. 运行时确定数组大小(堆区数组的核心优势:动态大小)
int arrSize;
cout << "请输入堆区数组的长度:";
cin >> arrSize;
// 2. 分配堆区数组:用new[]在堆上创建arrSize个int的空间
int* heapArray = new int[arrSize]; // 指针本身存在栈区,指向的内容在堆区
// 3. 初始化堆区数组的元素
for (int i = 0; i < arrSize; ++i) {
heapArray[i] = 10 * (i + 1); // 赋值为10、20、30...
}
// 4. 使用堆区数组:遍历输出
cout << "堆区数组的内容:";
for (int i = 0; i < arrSize; ++i) {
cout << heapArray[i] << " ";
}
cout << endl;
// 5. 手动释放堆内存(必须做!否则内存泄漏)
delete[] heapArray; // 注意:new[]分配的数组,必须用delete[]释放
heapArray = nullptr; // 置空指针,避免后续误用"悬空指针"
return 0;
}
⭐3.vector数组
本质:
1.连续的内存空间存储,支持下标访问元素。
2.动态扩容:当元素容量超过当前容量,会自动分配更大的内存,并拷贝原数据。
简单使用框架:
cpp// 必须包含的头文件 #include <vector> // 推荐:使用std命名空间(入门阶段简化代码) using namespace std; // 定义一个存储int类型的vector vector<int> vec;
1.vector的初始化
| 初始化方式 | 代码示例 | 说明 |
|---|---|---|
| 空初始化 | vector<int> vec; |
创建空 vector,后续手动添加元素 |
| 指定大小 + 默认值 | vector<int> vec(5); |
创建 5 个元素,每个元素默认值为 0 |
| 指定大小 + 自定义初始值 | vector<int> vec(5, 10); |
创建 5 个元素,每个元素值为 10 |
| 列表初始化(C++11+) | vector<int> vec{1,2,3,4,5}; |
直接初始化元素(推荐简洁写法) |
| 拷贝初始化 | vector<int> vec2(vec1); |
用已有 vector 拷贝一份新的 |
| 数组转 vector | int arr[]={1,2,3}; vector<int> vec(arr, arr+3); |
从普通数组初始化 |
cpp
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 1. 空初始化
vector<int> vec1;
cout << "vec1大小:" << vec1.size() << endl; // 输出:0
// 2. 指定大小(默认值0)
vector<int> vec2(5);
cout << "vec2[0]:" << vec2[0] << endl; // 输出:0
// 3. 指定大小+自定义值
vector<int> vec3(5, 10);
cout << "vec3[2]:" << vec3[2] << endl; // 输出:10
// 4. 列表初始化
vector<int> vec4{ 1,2,3,4,5 };
cout << "vec4[3]:" << vec4[3] << endl; // 输出:4
// 5. 拷贝初始化
vector<int> vec5(vec4);
cout << "vec5[4]:" << vec5[4] << endl; // 输出:5
// 6. 数组转vector
int arr[] = { 6,7,8 };
vector<int> vec6(arr, arr + 3);
cout << "vec6[1]:" << vec6[1] << endl; // 输出:7
return 0;
}
2.vector的查询
本质:查询有四种常用的查询方式
1.下标访问法(高效但无越界检查)
cppvector<int> vec{10,20,30,40}; // 访问第0个元素(vector下标从0开始,和数组一致) cout << vec[0] << endl; // 输出:10 // 访问第2个元素 cout << vec[2] << endl; // 输出:30 // 注意:下标越界不会报错(运行时崩溃),新手慎用! // vec[100]; // 越界,程序直接崩溃(无提示)2.at()方法(带越界检查)
cppvector<int> vec{10,20,30,40}; cout << vec.at(1) << endl; // 输出:20 // 越界时会抛出异常(有明确提示),便于调试 // vec.at(100); // 抛出out_of_range异常,程序不会直接崩溃3.front()/back() (访问首尾元素)
cppvector<int> vec{10,20,30,40}; cout << "首元素:" << vec.front() << endl; // 输出:10 cout << "尾元素:" << vec.back() << endl; // 输出:404.迭代器的使用(遍历专用)
cppvector<int> vec{1,2,3}; // 普通迭代器遍历 for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) { cout << *it << " "; // 输出:1 2 3 } cout << endl; // C++11+ 范围for(简化版,推荐) for (int num : vec) { cout << num << " "; // 输出:1 2 3 }
3.vector的增加
1.push_back() 尾部添加
cppvector<int> vec; // 空vector vec.push_back(10); // 尾部加10 → [10] vec.push_back(20); // 尾部加20 → [10,20] vec.push_back(30); // 尾部加30 → [10,20,30] cout << vec.back() << endl; // 输出:302.emplace_back() 高效尾部加
本质:和
push_back()功能一样,但直接在 vector 尾部构造元素,避免拷贝,效率更高
cppvector<int> vec; vec.emplace_back(100); // 尾部加100 → [100] vec.emplace_back(200); // 尾部加200 → [100,200] cout << vec[1] << endl; // 输出:2003.insert() 指定位置加
本质:
insert()需要结合迭代器 指定插入位置,语法:vec.insert(插入位置迭代器, 插入值)。
cppvector<int> vec{1,2,3,4}; // 1. 在第2个位置(下标1)插入99 vec.insert(vec.begin() + 1, 99); // 结果:[1,99,2,3,4] // 2. 在开头插入88 vec.insert(vec.begin(), 88); // 结果:[88,1,99,2,3,4] // 3. 在末尾插入77(等价于push_back) vec.insert(vec.end(), 77); // 结果:[88,1,99,2,3,4,77] // 4. 插入多个相同值:在开头插入2个66 vec.insert(vec.begin(), 2, 66); // 结果:[66,66,88,1,99,2,3,4,77] // 遍历输出验证 for (int num : vec) { cout << num << " "; } // 输出:66 66 88 1 99 2 3 4 77
4.vector的删除
1.pop_back() 尾部删除元素
cppvector<int> vec{10,20,30,40}; vec.pop_back(); // 删除尾部的40 → [10,20,30] vec.pop_back(); // 删除尾部的30 → [10,20] cout << vec.back() << endl; // 输出:202.erase() 指定位置删除/范围删除
cppvector<int> vec{1,2,3,4,5,6}; // 1. 删除指定位置元素(删除下标2的元素3) vec.erase(vec.begin() + 2); // 结果:[1,2,4,5,6] // 2. 删除范围元素(删除下标1到3的元素:2,4,5) // 注意:区间是[begin, end),左闭右开 vec.erase(vec.begin() + 1, vec.begin() + 4); // 结果:[1,6] // 遍历输出 for (int num : vec) { cout << num << " "; // 输出:1 6 }3.clear() 清空所有元素
clear()只清空元素,不释放内存,如需释放内存可结合 swap
cppvector<int> vec{1,2,3}; vec.clear(); cout << "清空后大小:" << vec.size() << endl; // 输出:0 vector<int>().swap(vec); // 清空并释放内存
5.vector的修改
本质:先访问,再赋值
cppvector<int> vec{10,20,30,40}; // 1. 下标修改 vec[1] = 200; // 把第1个元素改为200 → [10,200,30,40] // 2. at()修改(带越界检查) vec.at(2) = 300; // 把第2个元素改为300 → [10,200,300,40] // 3. 迭代器修改 vector<int>::iterator it = vec.begin() + 3; *it = 400; // 把第3个元素改为400 → [10,200,300,400] // 遍历验证 for (int num : vec) { cout << num << " "; // 输出:10 200 300 400 }
6.vector 常用属性/方法
| 方法 | 作用 | 示例 |
|---|---|---|
| size() | 返回当前元素个数 | vec.size() |
| capacity() | 返回当前容量(已分配的内存能存多少元素) | vec.capacity() |
| empty() | 判断是否为空(空返回 true) | vec.empty() |
| reserve(n) | 预留 n 个元素的容量(避免频繁扩容) | vec.reserve(100) |
| resize(n) | 调整元素个数为 n(多删少补,补默认值) | vec.resize(5) |
| swap(vec2) | 交换两个 vector 的内容 | vec.swap(vec2) |
关键区别:size vs capacity
size():实际存储的元素个数;
capacity():底层内存能容纳的元素个数(≥size);当
size() == capacity()时,再添加元素会触发扩容(重新分配内存 + 拷贝数据,效率低)。
实例:
cpp
//resize和capacity区别 + 预留容量
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vec;
// 初始状态:size=0,capacity=0
cout << "初始:size=" << vec.size() << ", capacity=" << vec.capacity() << endl;
// 添加元素,触发扩容
vec.push_back(1);
cout << "加1个元素:size=" << vec.size() << ", capacity=" << vec.capacity() << endl; // size=1, capacity=1
vec.push_back(2);
cout << "加2个元素:size=" << vec.size() << ", capacity=" << vec.capacity() << endl; // size=2, capacity=2
vec.push_back(3);
cout << "加3个元素:size=" << vec.size() << ", capacity=" << vec.capacity() << endl; // size=3, capacity=4(扩容为2倍)
// 提前预留容量,避免扩容
vec.reserve(10);
cout << "reserve(10)后:size=" << vec.size() << ", capacity=" << vec.capacity() << endl; // size=3, capacity=10
return 0;
}
7.vector的迭代器的遍历
1.普通迭代器(可读可写)
cppvector<int> vec{1,2,3}; for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) { *it *= 2; // 每个元素乘2 cout << *it << " "; // 输出:2 4 6 }2.const迭代器(只读)
cppvector<int> vec{1,2,3}; for (vector<int>::const_iterator it = vec.cbegin(); it != vec.cend(); ++it) { cout << *it << " "; // 输出:1 2 3 // *it = 10; // 报错:const迭代器不可修改 }3.反向迭代器(从后面遍历)
cppvector<int> vec{1,2,3}; for (vector<int>::reverse_iterator it = vec.rbegin(); it != vec.rend(); ++it) { cout << *it << " "; // 输出:3 2 1 }
4.Base16编码转换案例
cpp
#include <iostream>
#include <vector>
#include <string>
using namespace std;
// 编码表
static const string base16_enc_tab{ "0123456789ABCDEF" };
int main() {
// 编码操作
string teststr = "测试用于base16的字符串";
cout << "ori:\t" << teststr << endl;
string base16str; // base16编码后字符串
for (unsigned char c : teststr) { // 用unsigned char避免符号位问题
// 取高位四位(用unsigned char确保无符号移位)
unsigned char h = c >> 4;
// 取低位四位
unsigned char l = c & 0x0F; // 0b00001111等价于0x0F,更通用
base16str += base16_enc_tab[h];
base16str += base16_enc_tab[l];
}
cout << "Base16Incode:\t" << base16str << endl;
string ostr; // base16解码后数据
// 解码表(修复逗号,补充足够元素覆盖ASCII范围)
const vector<int> base16_dec_tab{ // 用int避免char溢出
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 0-9
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 10-19
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 20-29
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 30-39
-1,-1,-1,-1,-1,-1,-1,-1, // 40-47
0,1,2,3,4,5,6,7,8,9, // 48-57 ('0'-'9')
-1,-1,-1,-1,-1,-1,-1, // 58-64
10,11,12,13,14,15, // 65-70 ('A'-'F')
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 71-80(补充更多元素,避免越界)
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
};
for (size_t i = 0; i < base16str.size(); i += 2) { // 用size_t匹配字符串长度类型
// 获取高位和低位字符
unsigned char ch = base16str[i];
unsigned char cl = base16str[i + 1];
// 从解码表获取对应数值(确保下标不越界)
if (ch >= base16_dec_tab.size() || cl >= base16_dec_tab.size()) {
cout << "解码错误:非法字符" << endl;
return 1;
}
int h_val = base16_dec_tab[ch];
int l_val = base16_dec_tab[cl];
if (h_val == -1 || l_val == -1) {
cout << "解码错误:非法Base16字符" << endl;
return 1;
}
// 合并高低位(转为unsigned char避免符号问题)
unsigned char orig_char = (static_cast<unsigned char>(h_val) << 4) | static_cast<unsigned char>(l_val);
ostr += orig_char;
}
cout << "Base16Decode:\t" << ostr << endl;
}

5.基础案例
需求:

cpp
/*
简易缓存数据库搭建(思路)
1.用户输入处理(getline)
2.两个vector分别存放key和value
3.具备插入,查找,删除数据的具体操作。
*/
#include <iostream>
#include <vector>
#include <string>
#include <sstream> // 用于拆分用户输入的指令
using namespace std;
int main() {
// 定义两个vector存key和value
vector<string> keys;
vector<string> values;
string input; //存放用户输入的整行指令
cout << "简易缓存数据库(输入指令:插入/查找/删除 key [value],输入exit退出)" << endl;
while (true) {
cout << "请输入指令" << endl;
getline(cin, input);
if (input == "exit") {
cout << "程序结束" << endl;
break;
}
//stringstream 拆分输入的内容
stringstream ss(input);
string op, key, value;
ss >> op >> key;
if (op == "插入") {
ss >> value;
keys.push_back(key);
values.push_back(value);
cout << "插入成功:key=" << key << ",value=" << value << endl;
}
else if (op == "查找") {
bool found = false;
for (int i = 0; i < keys.size(); i++) {
if (keys[i] == key) {
cout << "找到数据:key=" << key << ",value=" << values[i] << endl;
found = true;
break;
}
}
if (!found) cout << "未找到key:" << key << endl;
}
else if (op == "删除") {
bool deleted = false;
for (int i = 0; i < keys.size(); i++) {
if (keys[i] == key) {
keys.erase(keys.begin() + i);
values.erase(values.begin() + i);
cout << "删除成功:key=" << key << endl;
deleted = true;
break;
}
}
if (!deleted) cout << "未找到要删除的key:" << key << endl;
}
else {
cout << "无效指令,请输入:插入/查找/删除 key [value]" << endl;
}
}
return 0;
}

总结:
笔者在学习c++的基础数据类型所整理的笔记,其中涉及到基础for循环,while循环,以及array三种不同的存储方式的数组,其中标记⭐的为重点掌握的知识,最后也配备了一个基础的案例,最基础实现简易缓存数据库。