一、STL 概述
STL——C++标准模板库,定义了常用的数据结构和算法。提供三种类型的组件:容器、迭代器和算法。
- 容器分为顺序和关联两种:
- 顺序容器:vector 、list、deque、string等是一系列元素的有序集合
- 关联容器:set、multiset、map、multimap包含查找元素的键值。
-
迭代器用于遍历容器。
-
算法库包含四类:排序、不可变序、变序和数值算法。
遍历vector向量并统计其中元素之和的程序示例:
#include <vector>
#include <iostream>
#include <algorithm>
#include <numeric> //accumulate算法需要
using namespace std;
int main()
{
vector<int> v;
int i;
for (i = 0; i < 10; i ++)
v.push_back(i);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
cout << *it <<" ";
cout<<endl;
cout<<accumulate(v.begin(),v.end(),0) <<endl;
return 0;
}
二、vector向量容器
vector可以像数组一样随机访问元素,而且有内存自动管理功能,对元素的插入删除可动态调整所占内存。有三种创建方式:
- 不指定元素个数:
vector<int> v;
- 创建时指定容器大小,下标0~9,每个元素的值初始为0.0
vector<double> v(10);
- 创建有n个元素的vector,每个元素有指定的初始值
vector<double> v(10, 8.6);
基本函数
-
begin():返回首元素位置的迭代器
-
end():返回最后一个元素的下一个位置的迭代器
-
size():返回向量的大小,即元素个数
-
empty():返回向量是否为空
-
push_back(): 在尾部追加元素
-
insert(): 在任意位置前插入一个新元素,就是占位于这个位置,原来此位置及以后的元素后移一位
-
erase(): 删除vector中迭代器所指的一个元素或一段区间中的所有元素
-
clear():一次性删除vector中的所有元素
-
reverse():将向量中某段迭代器区间元素反向排列
-
sort():要求使用随机访问迭代器排序,默认按升序排。可自定义比较函数定义排序规则。
#include <vector>
#include <iostream>
#include <algorithm>
#include <numeric> //accumulate算法需要
using namespace std;
//自定义比较函数使降序排序
bool cmp(const int &a, const int &b)
{
if (a != b) return a > b;
return a > b;
}
//使用迭代器访问元素,迭代器的类型要与遍历的vector对象的元素类型一致
void Print(vector<int> v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
cout << *it <<" ";
cout<<endl;
}
int main()
{
vector<int> v;
int i;
for (i = 0; i < 10; i ++)
v.push_back(i);
cout <<"初始时vector元素"<<endl;
Print(v);
v[6] = 12; //使用下标赋值
cout << v[6]<<endl; //使用下标访问元素
v.insert(v.begin(), 11); //在最前面插入11
v.insert(v.end(), 13); //末尾追加13,效果同v.push_back(13)
v.insert(v.begin() + 2, 16); //在第二个位置插入16,即v[2] = 16
cout <<"插入后vector元素"<<endl;
Print(v);
v.erase(v.begin() + 2); //删除v[2]
v.erase(v.begin() + 1, v.begin() + 4); //删除v[1] ~ v[3]共3个元素
cout <<"删除后vector元素"<<endl;
Print(v);
sort(v.begin(), v.end());
cout <<"排序后vector元素"<<endl;
Print(v);
sort(v.begin(), v.end(), cmp);
cout <<"降序排序后vector元素"<<endl;
Print(v);
reverse(v.begin(), v.end());
cout <<"反向排列后vector元素"<<endl;
Print(v);
cout << v.size() <<endl; //输出向量大小
v.clear(); //清空向量
cout << v.empty() <<endl; //输出向量是否为空
return 0;
}
auto关键字
auto是C++11新引入的类型说明符,让编译器分析表达式所属的类型,用于从初始化表达式中推断出变量的数据类型。所以auto定义的变量必须要有初始值。有以下好处:
- 可靠性:如果表达式的类型发生更改(包括函数返回值发生更改的情况),它也能工作。
- 性能:确保将不会进行转换。
- 方便:不必担心类型名称拼写困难和拼写有误。
- 效率高:代码会变得更高效。
// auto a; // 错误,没有初始化表达式,无法推断出a的类型
// auto int a = 10; // 错误,auto不能与其他类型组合连用
// 1. 自动帮助推导类型
auto a = 10;
auto c = 'A';
auto s("hello");
// 2. 类型冗长
map<int, map<int,int> > map_;
map<int, map<int,int>>::const_iterator itr1 = map_.begin();
const auto itr2 = map_.begin();
auto ptr = []()
{
std::cout << "hello world" << std::endl;
};
return 0;
};
// 3. 使用模板技术时,如果某个变量的类型依赖于模板参数, 不使用auto将很难确定变量的类型(使用auto后,将由编译器自动进行确定)。
template <class T, class U>
void Multiply(T t, U u) //函数和模板参数不能被声明为auto
{
auto v = t * u;
}
//4. 不能用于类型转换或其他一些操作,如sizeof和typeid
int value = 123;
auto x2 = (auto)value; // 不能用 auto 转换
auto x3 = static_cast<auto>(value); // 错误同上
//5. 定义在一个auto序列的变量必须始终能被推导成同一类型
auto x1 = 5, x2 = 5.0, x3='r'; //错误
三、string基本字符系列容器
string可理解为字符串类,其对象的元素是字符。提供了增删改查比较等多种函数。
-
赋值两种形式: 直接给字符串;赋字符指针
-
尾部追加字符/字符串: 用“+”或者s.append()。注意字符串要用“”。
-
inset():将一个字符插入到迭代器位置之前
-
erase():删除迭代器所指的元素或一个区间中所有元素
-
length():返回字符串长度
-
empty():返回字符串是否为空
-
replace():替换string对象中的字符
-
find():查找字符串中的第一个字符元素或子串,返回下标值或最大整数值,以下测试出的是64位
-
compare():字符串比较,若比对方大返回1,小返回-1,相等返回0
-
reverse():反向排序string对象,需加头文件algorithm
string对象也可作为vector的元素,类似于字符串数组。
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
int main()
{
//创建字符串对象,直接赋值并输出字符串长度
string s;
s = "hello, STL";
cout <<"hello, STL的长度为:" << s.length()<<endl;
//使用字符指针赋给字符串对象
char ch[100];
scanf("%s", ch); //scanf输入速度比cin快得多,但不支持string对象
s = ch; //整个字符数组赋给string对象
cout <<"输入的字符串为:" << s << endl;
s = s + '1'; //直接用‘+’在尾部添加字符
s = s + "+-"; //尾部追加字符串要用 ""
s.append("***"); //尾部追加字符串
cout <<"追加后的字符串为:" << s << endl;
string::iterator it; //定义迭代器
it = s.begin();
s.insert(it + 1, '?'); //将'?'插入到s[1]
cout <<"插入‘?’后的字符串为:" << s << endl;
cout <<"首字符比‘a’大:" << s[0] - 'a' << endl;
s.erase(it + 2); //删除s[2]
s.erase(it, it + 4); //删除s[0] ~ s[3]共4个元素
cout <<"删除后字符串为:" << s<< endl;
s = ""; //清空
cout <<"字符串是否为空"<<s.empty()<<endl;
s = "abc123456";
s.replace(3,3,"good"); //从第3个开始,将连续的3个字符替换为good
cout <<"替换后字符串为:" << s<< endl;
cout <<"字符串中第一个o的位置" <<s.find('o')<<endl;
cout <<"字符串中good的位置" <<s.find("good")<<endl;
cout <<"字符串中dog的位置,找不到则返回最大正整数值" <<s.find("dog")<<endl;
//字符串比较,比对方大则返回1,小返回-1,相等返回0
cout <<"与bcd比较:" <<s.compare("bcd")<<endl;
cout <<"与自己比较:" <<s.compare("abcgood456")<<endl;
cout <<"与aaaaa比较:" <<s.compare("aaaaa")<<endl;
s = "1234567";
reverse(s.begin(), s.end());
cout <<"翻转后的字符串为:"<<s <<endl;
vector<string> v;
v.push_back("yeah");
v.push_back("nope");
v.push_back("great");
cout << v[2] <<endl;
cout << v[1][0] <<endl;
cout << v[0].length()<<endl;
return 0;
}
-
string 类型的数字化处理
分离读入的数字的每位时,若用取余法效率较低,而且对于大数字也只能作为字符串处理输入。 -
string 对象与字符数组互操作
string s;
char ss[100];
scanf("%s", ss); //空格作为终止符不会被读入
s = ss;
printf(s.c_str()); //用 printf 输出字符串对象要用 c_str() 方法
cout<<endl;
printf("%s", ss);
-
string 对象与 sscanf 函数
C语言中 sscanf 用于将一个字符串按需要的方式分离出子串
string s1, s2, s3;
char sa[100], sb[100], sc[100];
sscanf("abc 123 pc", "%s %s %s", sa, sb, sc);
s1 = sa;
s2 = sb;
s3 = sc;
cout<<s1 <<" "<<s2<<" "<<s3<<endl;
int a, b, c;
sscanf("1 2 3", "%d %d %d", &a, &b, &c);
cout<<a <<" "<<b<<" "<<c<<endl;
sscanf("4,5$6", "%d,%d$%d", &a, &b, &c);
cout<<a <<" "<<b<<" "<<c<<endl;
- string 对象与数值相互转换
#include <iostream>
#include <algorithm>
#include <string>
#include <sstream>
using namespace std;
//将数值转化为string
string convertToString(double x)
{
ostringstream o;
if (o << x)
return o.str();
return "conversion error";
}
//将string转换为数值
double convertFromString(const string &s)
{
istringstream i(s);
double x;
if (i >> x)
return x;
return 0; //若出错
}
int main()
{
//将数值转化为string的C方法
char b[10];
string a;
sprintf(b, "%d", 1975);
a = b;
cout<< a <<endl;
//将数值转化为string的C++方法
string cc = convertToString(1976);
cout << cc<< endl;
//将string转换为数值的C++方法
string dd = "2006";
int p = convertFromString(dd) + 2;
cout << p <<endl;
return 0;
}
实际上就是
ostringstream o;
int x = 123;
o << x;
cout<<o.str()<<endl;
istringstream i("456");
i >> x;
cout<<x<<endl;
//输出123 456
网友评论