c++基础语法命令(C程序员刷leetcode)

本文档详细介绍了C++的基础语法,包括输入输出、基础类型、容器如vector、string的操作,以及关联容器map的基本使用。还涵盖了常用数据结构如链表、栈、队列和优先队列,并提供了通用函数如排序和比较的操作说明。通过这个速查指南,开发者可以快速查找和理解C++编程中的关键概念和操作。

平时编码都用C,但是C刷算法效率太低,记录一些过程常用的c++基础语法;

一、C与C++语法糖差异简述(刷题相关部分)

首先快速过一下C与C++算法题相关的整体语法差别。

序号特性C语言C++(用于刷题)优势和影响
1哲学强调过程和手工管理强调抽象和资源利用C++更高效,代码更短
2输入输出scanf, printfcin, coutC++更简单安全,无需记格式符
3字符串char str[100]string变革提升。自动管理内存,支持动态大小和便捷操作
4动态数组int* arr = malloc(n*sizeof(int))vector<int>变革提升。自动管理内存,自带大小、扩容、插入删除等操作
5数据结构需自己实现哈希、堆、树等直接使用 unordered_map, priority_queue 等降维打击。省去大量实现时间,直接应用经典数据结构
6函数传参传指针 (int*)传引用 (int&)语法更简洁,免去取地址&的困扰,更安全
7内存管理手动 malloc/free基本不用自己管理极大减少内存泄漏和越界错误

核心思想:在算法刷题相内容中,C++的强大不在于复杂的面向对象特性,而在于其标准模板库(STL)。你的主要学习目标就是从C的“一切自己动手”转变为“熟练调用STL”。
总结典型C++算法工具箱:1)vector动态数组,万能容器;2)string字符串处理;3)unordered_map快速查找和映射;4)unordered_set去重和存在性检查;5)priority_queue堆相关操作;6)stack/queue,DFS/BFS算法;6)pair简单键值对;

二、C++输入输出优化—格式自转化

ACM类型题目经常需要构造输入输出,需要掌握相关语法。先看基础差异简述:

序号操作C语言C++说明
1头文件#include <stdio.h>#include <iostream>
2输入一个变量scanf("%d", &a);cin >> a;C++无需指定类型%d,也无需取地址&
3输入多个变量scanf("%d %f", &a, &b);cin >> a >> b;C++更简洁
4输出printf("a=%d", a);cout << "a=" << a;C++使用流操作符<<,无需记格式符
5输出换行printf("\n");cout << endl;endl 功能等同于 \n 并刷新缓冲区
6优缺点快,但需小心格式符与参数匹配慢,但使用安全方便刷题层面,速度差异可忽略,安全和简便更重要

1. 基础输入cin—类型自转换/跳前空白符/中止条件/状态记录

读取输入cin机制:1)自动类型推导与转换;2)跳过前导空白符,包括空格、tab、换行(重要);3)读取的终止条件,遇到 空白符&类型不匹配&文件结束EOF;4)有记录流状态,健壮输入时用cin.fail()和cin.clear()。

// 1)自动类型推导与转换
int i; double d; char c;
cin >> i >> d >> c; // 输入: "10 3.14 A"
	// i被推导为int,读取10 d被推导为double,读取3.14 c被推导为char,读取'A'
// 2) 跳过前导空白符
int a, b; // 输入: "    10    20\n"
cin >> a >> b;
	// a成功读取10,b成功读取20。所有前导和中间的空格、换行都被跳过了。
// 4) 有记录流状态
int number; cin >> number;
if (cin.fail()) { // 输入失败,比如用户输入了字母
    cout << "Invalid input! Please enter a number." << endl;
    cin.clear(); // 重置流状态,这是关键!
    cin.ignore(10000, '\n'); // 清空输入缓冲区中的错误数据,直到换行符
    // 然后可以重新尝试读取
} else { // 输入成功,处理number }

2. 基础输出cout—精度控制/输出宽度与对齐/进制/其他用法

cout的默认输出格式往往不符合要求(如小数位数、对齐等),必须通过输出操纵符来精确控制。1)控制浮点数精度 setprecision(n)/fixed/scientific;2)控制输出宽度与对齐setw(n)/left/right/internal;3)控制进制(整数)dec/hex/oct/showbase; 4)其他典型用法boolalpha /showpoint/setfill(char)

// 1) 控制浮点数精度
	// 默认模式:setprecision(n) 表示有效数字为n位
	cout << setprecision(3) << 3.14159; // 输出 3.14 (3位有效数字)
	cout << setprecision(3) << 123.456; // 输出 123 (3位有效数字)
	// 固定小数模式:fixed 与 setprecision(n) 结合,表示小数点后保留n位。
	cout << fixed << setprecision(2);
	cout << 3.14159 << endl; // 输出 3.14
	cout << 100.0 << endl;   // 输出 100.00 (会补零)
	// 取消固定模式:用 defaultfloat 或 cout.unsetf(ios::fixed) 恢复默认
// 2)控制输出宽度与对齐
	cout << setw(5) << 123 << setw(5) << 456 << endl;
	// 输出: "  123  456" (每个数字占5个字符宽度,默认右对齐)
	cout << left << setw(5) << 123 << setw(5) << 456 << endl;
	// 输出: "123  456  " (每个数字占5个字符宽度,左对齐)
// 3) 控制进制(整数)
	cout << showbase; // 显示前缀
	cout << hex << 15 << " "; // 输出 0xf
	cout << oct << 15 << " "; // 输出 017
	cout << dec << 15 << endl; // 输出 15
// 4) 其他典型用法
    bool b = true;
    cout << "默认输出: " << b << endl;          // 输出: 1
    cout << boolalpha << "true/false模式: " << b << endl; // 输出: true
    cout << noboolalpha << "恢复1/0模式: " << b << endl;  // 输出: 1
	double num = 10.0;
    cout << "默认输出: " << num << endl;        // 输出: 10
    cout << showpoint << "显示小数点: " << num << endl;  // 输出: 10.0000
    cout << noshowpoint << "恢复默认: " << num << endl;   // 输出: 10
	int num = 123;
    cout << "默认输出: " << num << endl;                    // 输出: 123
    cout << "设置宽度5: " << setw(5) << num << endl;        // 输出:   123(前面2个空格)
    cout << setfill('*') << "星号填充: " << setw(5) << num << endl; // 输出: **123
    cout << setfill('0') << "零填充: " << setw(5) << num << endl;   // 输出: 00123

3. 读取整行getline

    string line;
    // 读取一整行,直到遇到换行符
    getline(cin, line); // 输入:This is a whole line.
    cout << "You entered: " << line << endl; // 输出:You entered: This is a whole line.
}

4. ACM算法题模式 处理常见格式

ACM类算法题输入输出都需要自己构建。ACM输入处理典型法则:1)、while (cin >> a >> b) - 处理到文件结束;2)、先读n,再for循环 - 处理已知组数;3)cin.ignore() - 数字后接getline时必须用;4)while (cin >> n && n != 0) - 处理有结束标志的输入;5)边读边处理 - 不要存储所有数据再处理。

// 1)简单多组数据(最常见)
	// 题目描述:计算两个整数A+B的和。每行输入两个数(空格隔开),输入包含多组测试数据。
	while (cin >> a >> b) { // 循环读取,直到文件结束
        cout << a + b << endl;
    }
// 2)先告知数据组数
	// 题目描述:计算A+B。第一行输入整数N,表示有N组测试数据。
	3
	1 2
	3 4
	5 6
	int n;
    cin >> n; // 先读组数
    while (n--) { // 循环n次
        int a, b;
        cin >> a >> b;
        cout << a + b << endl;
    }
// 3) 每行数据数量不固定
	// 题目描述:每行第一个数M表示该行后面有多少个数字,求每行数字的和。
	3 1 2 3
	2 10 20
	4 5 5 5 5
    int m;
    while (cin >> m) { // 先读每行的第一个数
        int sum = 0, num;
        for (int i = 0; i < m; i++) {
            cin >> num; // 读后面的m个数
            sum += num;
        }
        cout << sum << endl;
    }
// 4)复杂混合输入(数字+字符串)
	// 题目描述:每组数据包含一个数字和一个字符串,数字表示重复次数。
	3 hello
	2 world
	1 test
    int n;
    string s;
    while (cin >> n >> s) { // 先读数字,再读字符串
        for (int i = 0; i < n; i++) {
            cout << s;
        }
        cout << endl;
    }

三、C++数据类型优化—更智能动态大小数据结构

1. 字符串string代替char[]—动态大小、便捷方法、运算符操作

string是一个智能的、会自动扩容的字符数组,可以用=直接赋值,用+拼接,用!=比较;先比C语法 忘记strcpy, strcat, strcmp:直接用=, +, ==。忘记手动内存管理。多用成员函数。

序号特性C语言 (char[])C++ (string)优势
1内存管理手动分配固定大小自动动态管理无需担心缓冲区溢出
2长度获取strlen() 遍历计算.size() 直接获取O(1) 时间复杂度
3赋值操作strcpy()= 直接赋值语法直观简单
4拼接操作strcat()+ 或 +=极其方便
5比较操作strcmp()==, !=, < 等像比较数字一样自然

1)初始化与访问:string可随时用=进行赋值。字符可用下标访问(C语法)。遍历也可用c++的迭代器遍历。

// 初始化
string s1; // 初始化一个空串
string s2 = "Hello"; // C风格字符串初始化
string s3("hello world"); // 初始化子串
string s4(5, 'A'); // 用多个相同字符初始化 "AAAAA"
string s5 = s2; // 用另一个string初始化(拷贝)
string s6(s2, 1, 3); // 用子串初始化 (从位置1开始,取3个字符)"ell" 
// 访问字符
string s = "Hello";
cout << s[0] << endl; // 'H' (不检查越界,速度快)
cout << "第一个字符: " << s.front() << endl; // 'H'
cout << "最后一个字符: " << s.back() << endl;  // 'o'
// 遍历字串
for (int i = 0; i < s.size(); i++) {cout << s[i] << " ";} // 下标遍历 (最像C语言)
for (auto it = s.begin(); it != s.end(); it++) {cout << *it << " ";} // 迭代器遍历 (C++风格)
for (char c : s) {cout << c << " ";}	// 范围for循环 (C++11,最简洁)

2)长度与子串读取、字串位置查找:empty判空、length\size长度、substr子串、find字串位置查找。

string s="ABAB";
cout << str.length() << str.size(); // 两个都输出4
cout << s.substr(2) <<endl ; //输出AB
cout << s.substr(0,2) <<endl ; //同上
cout << s.substr(1,2) <<endl ; //输出BA

string s = "Hello World Hello";
// 查找第一次出现的位置
size_t pos = s.find("Hello"); // 返回 0
pos = s.find("World");        // 返回 6
// 从指定位置开始查找
pos = s.find("Hello", 1);     // 返回 12 (从位置1开始找)
// 查找最后一次出现的位置
pos = s.rfind("Hello");       // 返回 12
// 如果找不到,返回 string::npos
if (s.find("Java") == string::npos) {
    cout << "找不到子串" << endl;
}

3)字符串编辑可用运算符+、+=、==操作;insert插入、replace替换、append追加;

// 运算符+、+=
string s1 = "Hello";
string s2 = "World";
string s3 = s1 + " " + s2; // "Hello World"
s1 += " ";    // s1变为 "Hello "
s1 += s2;     // s1变为 "Hello World"
// 比较相关运算符
string s1 = "apple";
string s2 = "banana";
if (s1 == s2) cout << "相等" << endl;
if (s1 != s2) cout << "不相等" << endl;
if (s1 < s2)  cout << "apple < banana" << endl; // 按字典序比较
// 插入特定字符
string s1("Limitless"), s2("00");
s1.insert(2, "123");  //在下标 2 处插入字符串"123",s1 = "Li123mitless"
s1.insert(3, s2);  //在下标 2 处插入 s2 , s1 = "Li10023mitless"
s1.insert(3, 5, 'X');  //在下标 3 处插入 5 个 'X',s1 = "Li1XXXXX0023mitless"
// 字串替换
string s1("Real Steel");
s1.replace(1, 3, "123456", 2, 4);  //用 "123456" 的子串(2,4) 替换 s1 的子串(1,3) 输出 R3456 Steel
string s2("Harry Potter");
s2.replace(2, 3, 5, '0');  //用 5 个 '0' 替换子串(2,3) 输出 HaOOOOO Potter
int n = s2.find("OOOOO");  //查找子串 "00000" 的位置,n=2
s2.replace(n, 5, "XXX");  //将子串(n,5)替换为"XXX" 输出 HaXXX Potter
// 追加
string s1("123"), s2("abc");
s1.append(s2);  // s1 = "123abc"
s1.append(s2, 1, 2);  // s1 = "123abcbc"
s1.append(3, 'K');  // s1 = "123abcbcKKK"
s1.append("ABCDE", 2, 3);  // s1 = "123abcbcKKKCDE",添加 "ABCDE" 的子串(2, 3)

2. 容器vector替代 动态数组 —智能的、会自动扩容

vector是一个智能的、会自动扩容的数组。

序号特性C语言 (malloc/free)C++ (vector)优势
1内存管理手动分配和释放自动管理无需担心内存泄漏
2大小获取需自己维护变量.size() 直接获取简单可靠
3扩容操作手动 realloc.push_back() 自动扩容极其方便
4越界检查无,容易段错误.at() 提供安全检查更安全
5拷贝赋值手动 memcpy= 直接拷贝语法直观

1)初始化 元素访问与遍历。元素访问可用下标或at方法。遍历C++可用迭代器;

// 初始化
vector<int> v = {10, 20, 30, 40, 50}; // C的初始化方式
vector <int> v1; // int类型构造器,默认为空
vector <int> v2(v1); // v1的副本,也可用vector <int> v2=v1;
vector <int> v3(n); // 有n个元素,默认初值0
vector <int> v4(n, i); // 有n个元素,初值为i
vector<vector<int>> dp(m, vector<int>(n)); // 初始化一个二位数组大小[m][n]
// 访问元素
vector<int> v = {10, 20, 30, 40, 50};
cout << v[0] << endl; // 方法1: 下标访问(不检查越界,速度快)10
cout << "第一个元素: " << v.front() << endl; // 10
cout << "最后一个元素: " << v.back() << endl;  // 50
cout << v.at(2) << endl; // 方法2: at()访问(检查越界,更安全) 30
	// v.at(10)会抛出std::out_of_range异常
// 遍历
for(int i = 0; i < 5; i++) { cout<< v[i] <<" ";} // 下标遍历
for(auto it=obj.begin();it!=obj.end();it++) { cout<<*it<<" ";} //迭代器遍历
for (int num : v) {cout << num << " ";} // 范围for循环(C++11,最简洁)

2)常用操作:size元素个数、empty判空、push_back尾部加元素、pop_back删尾部元素、clear 清空、insert指定位置插入、erase指定位置删除;sort排序reverse反转元素

vector<int>obj(10, 1);//创建一个向量存储容器 int, 初始里面有10个1
obj.push_back(5); // 在尾部新增一个成员,值为5
int size = obj.size(); // 取元素个数,11个
obj.pop_back(); // 去掉尾部元素
obj.clear(); // 清空obj

vector<int> v = {1, 3, 4};
v.insert(v.begin() + 1, 2); // 在第二个元素位置前插入2 v: [1, 2, 3, 4]
vector<int> v = {1, 2, 3, 4, 5};
v.erase(v.begin() + 2); // 删除第三个元素(3) v: [1, 2, 4, 5]
v.erase(v.begin()); // 删除第一个元素
v.erase(v.end() - 1); // 删除最后一个元素

sort(obj.begin(),obj.end()); // 默认排序,从小到大排序
// 注意begin是第一个元素(包含),end是最后元素下一个位置(不包含); 
bool cmp(int a,int b) { return a > b;} 
sort(obj.begin(),obj.end()),cmp); // 从大到小(指定条件排序)
sort(obj.begin(),obj.end(),less<int>()); // 升序
sort(obj.begin(),obj.end(),greater<int>()). // 降序

reverse(s.begin(), s.end()); // 把s中元素进行反转排序

3. 基本结构 栈stack 和 队列queue,无需自己构造

stack操作:empty判空、push入栈、pop弹出、top取顶、size元素个数

stack<int> s; // 定义栈
s.push(10); // 入栈
while(!s.empty()) { // 判空 
    s.pop(); // 出栈
}
int top = s.top(); // 取顶部
int size = s.size(); // 取元素个数

queue操作:empty判空、size元素个数、push入队、pop出队、front队首、back队尾

queue<int> q; //定义队列
for (int i = 0; i < 10; i++){
	q.push(i);
}
cout << "q中有" << q.size() << "个元素" << endl;
cout << "队头元素为:" << q.front() << endl;
cout << "队尾元素为:" << q.back() << endl;
if (!q.empty()){ // 判空
	q.pop(); // 删除队列首元素
}
return 0;

4. 无序健值对序列unordered_map,哈希表,快速查找和映射

unordered_map是一个自动扩容的、基于哈希表的字典。每一个元素都是键值队pair(两个成员first和second)。

序号特性C语言实现C++ unordered_map优势
1底层实现需要自己实现哈希函数和冲突解决完整的哈希表实现无需造轮子
2插入操作手动处理哈希冲突map[key] = value (O(1))极其简单
3查找操作手动遍历或复杂逻辑map.find(key) (O(1))快速可靠
4内存管理手动分配释放自动管理无内存泄漏风险
// 1)初始化
	// 定义: unordered_map<KeyType, ValueType>
unordered_map<string, int> studentScores;
// 2)插入和更新元素、删除元素
	// 方法1: 使用[]运算符(最常用)
studentScores["Alice"] = 95;   // 插入
studentScores["Bob"] = 88;
studentScores["Alice"] = 100;  // 更新
	// 方法2: 使用insert函数
studentScores.insert({"Charlie", 92});
studentScores.insert(make_pair("David", 85));
	// 通过key删除
studentScores.erase("Bob");
	// 通过迭代器删除
auto it = studentScores.find("Charlie");
if (it != studentScores.end()) {
    studentScores.erase(it);
}
	// 删除所有元素
studentScores.clear();
// 3)访问元素
	// 方法1: 使用[]运算符(如果key不存在,会创建!)
cout << studentScores["Alice"] << endl; // 100
cout << studentScores["Frank"] << endl; // 0(Frank被创建,value=0)
	// 方法2: 使用at()(安全访问,key不存在会抛出异常)
cout << studentScores.at("Alice") << endl; // 100
cout << studentScores.at("Unknown") << endl; // 抛出异常
// 4)查找元素
	// 使用find()函数(返回迭代器)
auto it = studentScores.find("Bob");
if (it != studentScores.end()) { // 找到了
    cout << "Found: " << it->first << " -> " << it->second << endl;
} else {
    cout << "Not found" << endl;
}
	// 检查key是否存在
if (studentScores.count("Alice") > 0) {
    cout << "Key exists" << endl;
}
// 5)遍历元素
for (const auto& pair : studentScores) {	// 范围for循环(最简洁)
    cout << pair.first << ": " << pair.second << endl;
}
for (auto it = studentScores.begin(); it != studentScores.end(); it++) { 	// 迭代器
    cout << it->first << ": " << it->second << endl;
}

5.集合容器unordered_set,不重复无顺,适用快速查重

unordered_set 是一个基于哈希表实现的集合容器,用于存储不重复的元素,元素无序。

unordered_set<int> uniqueNumbers;
// 插入元素
uniqueNumbers.insert(10);
uniqueNumbers.insert(20);
uniqueNumbers.insert(10); // 重复插入,无效
uniqueNumbers.insert(30);
// 查找元素
unordered_set<int> numbers = {10, 20, 30, 40, 50};
	// 方法1: 使用find()(返回迭代器)
auto it = numbers.find(30);
if (it != numbers.end()) { cout << "Found: " << *it << endl; 
} else { cout << "Not found" << endl; }
	// 方法2: 使用count()(返回0或1)
if (numbers.count(25) > 0) { cout << "25 exists" << endl;
} else { cout << "25 does not exist" << endl; }
// 删除元素
	// 通过值删除
numbers.erase(30);
	// 通过迭代器删除
auto it = numbers.find(40);
if (it != numbers.end()) {
    numbers.erase(it);
}

6. 优先队列priority_queue,大顶堆,快速访问最大或最小元素

堆(Heap) 是一种特殊的完全二叉树,它满足一个关键性质:每个节点的值都满足与子节点的大小关系。堆顶元素:总是整个堆中最大(大顶堆)或最小(小顶堆)的元素。大顶堆(Max-Heap):每个节点的值都 大于或等于 其子节点的值。小顶堆(Min-Heap):每个节点的值都 小于或等于 其子节点的值。
priority_queue本质上是一个堆,总是能快速访问最大或最小的元素。

priority_queue<int> a; // 默认大顶堆,降序队列
priority_queue <int,vector<int>,greater<int> > c; // 升序队列,小顶堆
for (int i = 0; i < 5; i++) {
    a.push(i);
    c.push(i);
}
while (!a.empty()) {
    cout << a.top() << ' '; // 输出 4 3 2 1 0
    a.pop();
} 
while (!c.empty()) {
    cout << c.top() << ' '; // 输出 0 1 2 3 4
    c.pop();
}

7. 关联容器map,自动排序键值对容器

map是一个自动排序的、基于红黑树的键值对容器。map的,添加一个成员会按照pair的key自动排序。

序号特性C语言实现C++ map优势
1底层实现需要自己选择(数组、链表、二叉搜索树)红黑树(平衡BST)自动保持平衡,性能稳定
2插入操作手动处理,复杂度不定map[key] = value (O(log n))简单高效
3查找操作手动实现,可能 O(n)map.find(key) (O(log n))快速可靠
4排序特性需要手动维护自动按键排序始终有序
5内存管理手动分配释放自动管理无内存泄漏风险

1)初始化 与 访问元素 :自动建立key(要求唯一)与 value的对应

// 1. 空map: map<KeyType, ValueType>
map<int, string> mapStudent; // 定义一个map对象
map<string, int> ageMap = {
        {"Alice", 20},
        {"Bob", 21},
        {"Charlie", 22}
    };
pair<int, string> student(101, "Alice"); // 定义一个pair对象
cout << "ID: " << student.first << endl;    // 101
cout << "Name: " << student.second << endl; // Alice
// 访问元素
map<int, string>::iterator iter = mapStudent.find(2); // 可以用 iter->second 来使用第二个值 
string str = mapStudent[2]; // 不推荐,如果key不存在,会中增加这个key,而value就是缺省值
if (mapStudent.find(2) == mapStudent.end()) { // 找不到
	cout << "not find!" << endl;
}
// 遍历元素
map<string, int> scores = {{"Alice", 95}, {"Bob", 90}, {"Charlie", 88}};
	// 方式1: 迭代器遍历(保证按键排序顺序)
for (auto it = scores.begin(); it != scores.end(); it++) {
    cout << it->first << ": " << it->second << endl;
}
	// 方式2: 范围for循环(C++11,最简洁)
for (const auto& pair : scores) {
    cout << pair.first << ": " << pair.second << endl;
}

2)常用操作可以用运算符=进行新增或更新;insert插入、erase删除、find查找、size元素个数、empty判空、clear清空

map<int, string> mapStudent;
mapStudent[3] = "student_3"; // 直接访问的方式插入元素
mapStudent[3] = "student3"; // 直接访问的对已存在元素更新
mapStudent.insert(pair<int, string>(0, "student0")); // 用insert函數插入pair<int, string>类型
mapStudent.insert(make_pair<int, string>(2,"student2")); 
mapStudent.insert(map<int, string>::value_type(1, "student1"));
mapStudent.insert({21"Bob"}); // C++11方式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值