目录
目录
一、字符串 string
1.字符串相关的头文件
#include <cstring>
#include <string>
#include <cctype> 用于 isalpha, tolower 等函数
2.字符串的定义
(1)基本的定义方法
-------------------------------------字符串------------------------------------------------
string s; // 初始化一个空字符串
string s = "hello world"; // 用 "hello world" 初始化 s
string s("hello world"); // 作用同上
-------------------------------------字符数组-----------------------------------------------
char s[] = "ROBOT"; //C风格字符数组
char s[6] = {'R', 'O', 'B', 'O', 'T'}; //指定长度的字符串,多余的字符自动被赋为结束字符'\0'
(2)炸爽的定义方法
-------------------------------------字符串-------------------------------------------------
string s1;
string s = s1; // 初始化s2,并用s1初始化
string s(s1); // 作用同上
string s(n,'a'); // 初始化s为:n个a
string s(s1, pos); // 从 s1 的下标 pos 开始的字符拷贝
string s(s1, pos, len); // 从 s1 的下标 pos 开始的 len 个字符的拷贝
string s(beg,end) //以区间beg;end(不包含end)内的字符作为字符串s的初值
3.字符串的输入
-------------------------------------字符串------------------------------------------------
string s;//对于C++风格字符串
cin >> S; //遇到空格自动终止
getline(cin,s1); //可读入包含空格的字符串
-------------------------------------字符数组-----------------------------------------------
char s[n];
cin.getline(s, n); //可读入包含空格的字符串,可读入的长度为 n-1
cin.getline(s, n, '\n'); //加了限制条件,以'\n'结束输入
for(int i = 0; i<n; i++) //用循环输入
{
cin >> s[i];
}
4.字符串的常用操作
(1)长度 获得字符串长度
-------------------------------------字符串------------------------------------------------
string s = "Hello"
str.size(); //输出结果为5
str.length(); //一样
-------------------------------------字符数组-----------------------------------------------
char s[] = "Hello";
strlen(str); //输出结果为5
(2)删除 字符串中的字符/子串
s.erase(pos, n); //以字符串中下标为pos的字符开始删除(包括自己),向后删除n个
s.erase(pos); //删除字符串中下标为pos以后的所有字符(包括自己)
s.erase(s.begin()+n1,s.end()-n2); //左闭右开,删除字符串中
//s.begin()+n1 到 s.end()+n2 间的子串,注意这里必须用begin和end!
(3)插入 字符/子串到字符串中
\\以下都是旧字符串经过插入操作后得到新字符串
string s2= s1.insert(pos,‘x’);//在s1的第pos个位置插入字符串‘x’
string s2 = s1.insert(pos,n,‘x’);//在str1中第pos个位置插入n个字符‘x’
s1.insert(++s1.begin(),2,‘a’); //通过此操作可以在循环中实现不断的在一个等间隔的位置
//里添加相同的字符串,每次都是先s1.begin()迭代加一,再插入,反复循环
string s2= s1.insert(pos,str1);//在字符串s1第pos个位置插入s1
string s2= s1.insert(pos,“word”,n);//在s1的第pos个位置插入字符串’word’中的n个字符
string s3= s2.insert(pos2,s1,pos1,n);//在s2的第pos2个位置插入s1的从pos1开始的n个字符
(4)替换 字符串中的字符
s1.replace (pos, len, "s1"); //从第pos个位置开始后面的len个字符被替换成了"s1"这个字符串
例子:
//例1
string str("Hello World!");
str.replace(6, 5, "C++");
cout << str; // 输出: Hello C++
//例2
string str("Hello World!");
string new_str("C++");
str.replace(str.begin()+6, str.begin()+11, new_str.begin(), new_str.end());
cout << str; // 输出: Hello C++!
(5)转换 字符串和字符数组
//字符串转换为字符数组
char s2 = s1.c_str();
(6)查找 所需字符串
int index = s1.find("xxx", pos); //从s1的pos位置开始寻找"xxx"字符串,
//返回第一次找到的所需字符串中的第一个字符的位置
例子:
string s1 = "Tom And Jerry, Hello World, Tom !";
// 从 0 位置开始 ( 包括 0 位置 ) , 统计第一次出现 Tom 字符串的位置
int index = s1.find("Tom", 0);
// index: 0
(7)提取 某个子字符串
s1.substr(pos, len); //返回s1中pos这个位置后开始len长度的子字符串(包含pos自己)
例子:
string str = "Hello, World!";
// 提取从位置 7 开始的 5 个字符
string substr1 = str.substr(7, 5); // "World"
// 从位置 2 开始到字符串末尾
string substr2 = str.substr(2); // "llo, World!"
(8)转化 字符
常用:
tolower(c) // 若c是大写字母,转换为小写输出,否则原样输出
toupper(c) // 类似上面的
isalnum(c) // 当是字母或数字时为真
isalpha(c) // 当是字母时为真
isdigit(c) // 当是数字是为真
islower(c) // 当是小写字母时为真
isupper(c) // 当是大写字母时为真
isspace(c) // 当是空白(空格、回车、换行、制表符等)时为真
ispunct(c) // 当是标点符号时为真(即c不是 控制字符、数字、字母、可打印空白 中的一种)
不常用:
isxdigit(c) // 当是16进制数字是为真
isprint(c) // 当时可打印字符时为真(即c是空格或具有可见形式)
isgraph(c) // 当不是空格但可打印时为真
iscntrl(c) // 当是控制字符时为真
(9)比较 字符/字符串
//字符串的下标对应的字符可以直接和字符作比较
s[i] == 'abc'
(10)遍历 字符串
string s = "13456";
for (char i : s) {
cout << i << " ";
}
string str1="12345";
for(int i = 0; i<s.size();i++)
{
cout<<s[i]<<" ";
}
(11)排序 字符串中的字符
sort函数不传入第三个函数参数,默认为升序排列
使用对象:数组、字符串、向量
// 方式一、使用数组
int a[10] = {9, 6, 3, 8, 5, 2, 7, 4, 1, 0};
sort(a, a + 10); // 10为元素个数
for (int i = 0; i < 10; i++) cout << a[i] << ' '; // 输出排序后数组
cout << endl;
// 方式二、使用 vector
vector<int> arr = {9, 6, 3, 8, 5, 2, 7, 4, 1, 0};
sort(arr.begin(), arr.end()); // 10为元素个数
for (int i = 0; i < 10; i++) cout << arr[i] << ' '; // 输出排序后数组
sort函数传入第三个参数,可改变排序方式
降序排列:
// 方式一、使用数组
int a[10] = {9, 6, 3, 8, 5, 2, 7, 4, 1, 0};
sort(a, a + 10, greater<int>()); // 10为元素个数
for (int i = 0; i < 10; i++) cout << a[i] << ' '; // 输出排序后数组
cout << endl; // 输出 9 8 7 6 5 4 3 2 1 0
// 方式二、使用 vector
vector<int> arr = {9, 6, 3, 8, 5, 2, 7, 4, 1, 0};
sort(arr.begin(), arr.end(), greater<int>());
for (int i = 0; i < 10; i++) cout << arr[i] << ' '; // 输出排序后数组
sort函数还有其他拓展,之后再补充
二、向量 vector
1. 向量相关头文件
#include<vector>
2. 向量的定义
/* 初始化vector对象的方法 */
vector<T> v1 ; //v1是一个空的vector,它潜在的元素是T类型的,执行默认初始化
vector<T> v2(v1) ; //v2中包含v1中所有元素的副本
vector<T> V2 = V1; //与上等价
vector<T> v3(n, val) ; //声明一个初始大小为n且初始值都为val的向量
vector<T> v4(n) ; //v4包含了n个重复地执行了值初始化的对象
vector<T> v5{a,b,c,...} //v5包含了初始值个数的元素,每个元素给赋予对应的初值
vector<T> v5 = {a,b,c,...} //与上等价
vector<T> v6(v5.begin(), v5.begin()+3); //将v5向量中从第0个到第2个(共3个)作为向量v6的初始值
vector<pair<T1, T2>> v7 // 构造一个把2个元素合成1对来看的向量
例:
vector<int> v1;
vector<father> v2;
vector<string> v3;
vector<vector<int> >; //注意空格。这里相当于二维数组int a[n][n];
e.g vector< vector<int> > b(10, vector<int>(5)); //创建一个10*5的int型二维向量
vector<int> v5 = { 1,2,3,4,5 };//列表初始化,注意使用的是花括号
vector<string> v6 = { "hi","my","name","is","lee" };
vector<int> v7(5, -1); //初始化为-1,-1,-1,-1,-1。第一个参数是数目,第二个参数是要初始化的值
vector<string> v8(3, "hi");
vector<int> v9(10); //默认初始化为0
vector<int> v10(4); //默认初始化为空字符串
/* 直接使用数组来初始化向量 */
int n[] = {1, 2, 3, 4, 5} ;
vector<int> v11(n, n+5) ; //将数组n的前5个元素作为向量a的初值
vector<int> v11(&n[1], &n[4]) ;//将n[1] - n[4]范围内的元素作为向量v11的初值
3. 向量的基本操作(与数组大体类似)
---- 基本操作 ----
v.size() //返回向量v中的元素个数
v.empty() //若v中不包含任何元素,返回真;否则返回假
v.push_back(t) //向v的尾端添加一个值为t的元素
v.emplace_back(t) // 在v的尾端构造一个值为t的元素
v.front() //访问v的第一个元素
v.back() //访问v的最后一个元素
v[n] //返回v中第n个位置上元素的应用
v1 = v2 ; //将v2中的元素拷贝替换v1中的元素
v1 = {a,b,c,...} //用列表中元素拷贝替换v1中的元素
==、!=、>、>=、<、<= //惯有含义,以字典顺序进行比较 ;
---- 添加或删除元素的操作 ----
push_back() //把传送为参数的对象添加到vector的尾部
pop_back() //删除vector尾最后一个元素
erase() //删除一个或多个元素
--v.erase(v.begin()) ; //将起始位置的元素删除
--v.erase(v.begin(), v.begin()+3) ;//将(v.begin(), v.begin()+3)之间的3个元素删除
--v.erase(v.begin() + 3); //删除第4个元素
clear() //清除所有元素
insert() //插入一个或多个对象
--v.insert(v.begin(), 1000); //将1000插入到向量v的起始位置前
--v.insert(v.begin() + 1,9); //在第二个位置插入新元素
--v.insert(v.begin(), 3, 1000) ; //位置0开始,连续插入3个1000
--v.insert(v.begin() + 1, 7,8); //位置1开始,连续插入7个8
--vector<int> a(5, 1) ;
vector<int> b(10) ;
b.insert(b.begin(), a.begin(), a.end());
//将a.begin(), a.end()之间的全部元素插入到b.begin()前
---- 交换 ----
v2.swap(v1) ; //v1向量与v2向量进行交换
参考链接:
C++ 向量(vector)_c++ vector-优快云博客
三、字典 map
1. map相关头文件
#include <map>
2. map的定义
map<int, string> ID_Name = {
{ 2015, "Jim" },
{ 2016, "Tom" },
{ 2017, "Bob" } };
例:
// map默认从小到大排序
int main() {
map<int, string> ID_Name = {
{ 2019, "Jim" },
{ 2016, "Tom" },
{ 2017, "Bob" } };
for (const auto& pair : ID_Name) {
cout << pair.first << ": " << pair.second << endl;
}
return 0;
}
-------------------------------------------------------------------------------------------
// 使用 greater<int> 使 map 按键从大到小排序
int main() {
map<int, string, greater<int>> ID_Name;
ID_Name[1] = "Alice";
ID_Name[3] = "Bob";
ID_Name[2] = "Charlie";
for (const auto& pair : ID_Name) {
cout << pair.first << ": " << pair.second << endl;
}
return 0;
}
3. map的基本操作
(1)插入与替换
使用[ ]进行单个插入
map<int, string> ID_Name;
// 如果已经存在键值2015,则会作赋值修改操作,如果没有则插入
ID_Name[2015] = "Tom";
使用insert或emplace进行单个和多个插入
// insert() 不会覆盖已有的键值对,若键已存在则插入失败
// insert() 可以通过 std::pair 或初始化列表插入键值对
ID_Name.insert(std::make_pair(3, "Charlie")); // 插入键值对 (3, "Charlie")
ID_Name.insert({4, "Dave"}); // 插入键值对 (4, "Dave")
// 插入多个键值对
ID_Name.insert({
{4, "Dave"},
{5, "Eve"},
{6, "Frank"}
});
// 如果数据已经存在于另一个 map 或 vector 中,可以使用 insert() 的范围插入,将一个范围的元素插入到当前的 map 中
map<int, string> additional_ID_Name = {
{7, "Grace"},
{8, "Heidi"}
};
ID_Name.insert(additional_ID_Name.begin(), additional_ID_Name.end());
// emplace() 可以直接构造键值对
ID_Name.emplace(5, "Eve"); // 插入键值对 (5, "Eve")
(2)取值
map<int, string> ID_Name;
cout<<ID_Name[2016].c_str()<<endl;
//使用[]取值,若ID_Name中没有关键字2016,不会报错,但打印为空
cout<<ID_Name.at(2016)<<endl;
//使用at取值,若ID_Name中没有关键字2016,该语句会报错
(3)容量查询
ID_Name.size()
// size() 函数返回 map 中存储的键值对的数量
ID_Name.empty()
// empty() 函数返回一个布尔值,指示 map 是否为空。如果 map 中没有元素则返回 true,否则返回 false
(4)删除元素
ID_Name.erase(2); // 删除键为 2 的元素
auto start = ID_Name.find(1);
auto end = ID_Name.find(3);
ID_Name.erase(start, end); // 删除从键 1 开始到键 3 之前的所有元素
ID_Name.clear(); // 清空 map
(5)查找元素
map<int, string> ID_Name = {{1, "Alice"}, {2, "Bob"}, {3, "Charlie"}};
auto it = ID_Name.find(2);
// 不能直接打印,因为 find() 返回的是一个迭代器,而不是具体的值
if (it != ID_Name.end()) {
cout << "Found: " << it->first << " => " << it->second << endl;
} else {
cout << "Key not found." << endl;
}
参考链接:
四、数据类型转换
int n1 = atoi(s2); // 将 字符数组 转化为 整型
int n2 = stoi(s1); // 将 字符串 转化为 整形
string n3 = to_string(s3) // 将 整型 转化为 字符串
s.c_str() //将 字符串 转化为 字符数组
//将 整型 转化为 bool类型,再将 bool类型 转化为 整型
//bool类型的变量值只有两个,1为真0为假,强转过程中非0的值都被bool类型变量认为是真
int a;
cin>>a;
bool b = a;
int c = b;
例:
string s1 = "12345";
char s2[] = "12345";
int s3 = 12345;
int n1 = atoi(s2); // 将 字符数组 转化为 整型
int n2 = stoi(s1); // 将 字符串 转化为 整型
string n3 = to_string(s3); // 将 整型 转化为 字符串
cout << n1 << endl;
cout << n2 << endl;
cout << n3 << endl;
五、数学计算的常用函数
(1)相关头文件
#include <cmath>
#include <algorithm>
(2)计算次幂
pow(base, exponent)
例:(注意一定要定义为浮点数)
double base = 2.0;
double exponent = 3.0;
double result = pow(base, exponent);
(3)最大值 和 最小值
max(a,b);
min(a,b);
(4)四舍五入
round(c) //c=3.14 round(c)=3
六、C++的输入、输出和遍历
(1)输入
1. 向量的输入
// 常规输入:和数组一样
// pair时的输入
vector<pair<int, int>> polynomial; // 用于存储多项式的系数和指数对
int coeff, exp;
// 输入多项式的系数和指数
while (cin >> coeff >> exp) {
polynomial.emplace_back(coeff, exp);
// 此处也可以用polynomial.push_back({coeff, exp});
}
(2)输出
1. setw()
setw()用来设置字段宽度,即指定输出内容所占用的最小宽度。如果实际输出的内容小于指定宽度,则会使用填充字符填充
cout << setw(width) << value;
e.g
cout << setw(5) << 42 << endl; // 输出:` 42` (3个空格 + 数字42)
cout << setw(3) << "Hi" << endl; // 输出:` Hi` (1个空格 + 字符串Hi)
cout << setw(2) << 12345 << endl; // 输出:`12345` (内容超出宽度,不截断)
-
参数:
-
width:字段宽度(最小宽度)。如果内容的长度小于
width
,则用填充字符填充,默认的填充字符是空格;如果大于width
,则直接输出内容。
-
-
特点:
-
默认右对齐
-
它只对紧跟其后的一次输出操作生效。
-
如果实际输出的内容长度超过
width
,setw
不会截断内容,而是直接输出完整内容
-
2. setw() 和 setfill()
setfill()用于设置填充字符,当内容长度不足setw指定的宽度时,用指定的字符填充
cout << setfill(ch);
e.g.
cout << setfill('*') << setw(5) << 42 << endl; // 输出:`***42`
cout << setfill('0') << setw(6) << 123 << endl; // 输出:`000123`
// 修改填充字符
cout << setfill('#') << setw(7) << "Hi" << endl; // 输出:`#####Hi`
-
参数:
-
ch
:填充的字符(默认为空格' '
)
-
-
特点:
-
默认右对齐,所以从左边开始补
-
它会持续生效,直到被重新设置
-
3. setw() 和 left 和 right
cout << setw(10) << right << 42 << endl; // 默认右对齐:` 42`
cout << setw(10) << left << 42 << endl; // 左对齐:`42 `
4. fixed和 setprecision()
- 用于控制浮点数的输出格式
fixed
:使用固定小数点格式setprecision(n)
:控制浮点数小数位数
double pi = 3.14159265358979;
cout << fixed << setprecision(2) << pi << endl; // 输出:`3.14`
cout << fixed << setprecision(5) << pi << endl; // 输出:`3.14159`
5. hex、oct、dec
int num = 255;
cout << hex << num << endl; // 输出:`ff` (十六进制)
cout << oct << num << endl; // 输出:`377` (八进制)
cout << dec << num << endl; // 输出:`255` (十进制)
6. 二进制输出
#include <iostream>
#include <bitset> // 包含 bitset 类
using namespace std;
int main() {
int num = 42; // 例子数字
// 输出数字的二进制表示
cout << bitset<32>(num) << endl; // 输出 32 位的二进制表示
return 0;
}
7. 向量输出
(1)常规输出
和数组一样
(2)pair时的输出
for (const auto& term : derivative) {
cout << term.first << " " << term.second << " ";
}
for (size_t i = 0; i < result.size(); ++i) {
cout << result[i].first << " " << result[i].second;
}
for (auto i = 0; i < result.size(); ++i) {
cout << result[i].first << " " << result[i].second;
}
(3)遍历
1. 例子:pair向量遍历求导,两种遍历方法
for (const auto& term : polynomial) {
derivative.emplace_back(result.first, result.second);
}
for (auto i = 0; i < result.size(); i++) {
derivative.emplace_back(result[i].first, result[i].second);
}
七、小技巧与例题
(1)取模 %
转换进制
使用bool类型定义的数组标记已经识别过的字母
题目:
代码:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
// 循环处理多组测试数据
while (getline(cin, str))
{
// 假设输入的字符串不为空,因为空字符串不需要处理
// 使用一个标记数组来记录每个字母是否出现过
bool visited[26] = {false}; // 初始化所有字母为未访问
// 处理字符串并输出非重复字母
for (int i = 0; i < str.length(); ++i)
{
// 如果当前字母未被访问过
if (!visited[str[i] - 'a']) // 括号里面的是bool数组里的false,其实就是if(!false)也即if(true),然后执行if里的语句将其标记为true,这样之后再判断的时候若被标记后不为true就不输出了
{
// 标记该字母为已访问
visited[str[i] - 'a'] = true;
// 输出该字母
cout << str[i];
}
}
// 输出换行符,以便分隔每组测试数据的输出
cout << endl;
}
return 0;
}
......待更新
考试寄了;
一点经验教训:以后再也不用数组了,之后学习怎么用vector,因为数组不能删东西;字符串的拼接;冒泡排序;以及学习如何在c++中实现跟python一样的字典的功能