STL简介
什么是STL
STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其他一些组件的集合。这里的“容器”和算法的集合指的是世界上很多聪明人很多年的杰作。STL的目的是标准化组件,这样就不用重新开发,可以使用现成的组件。STL现在是C++的一部分,因此不用安装额外的库文件。
STL的版本
原始版本:Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。 HP版本–所有STL实现版本的始祖。
P.J.版本:由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低,
符号命名比较怪异。
RW版本:由Rouge Wage公司开发,继承自HP版本,被C+ + Builder 采用,不能公开或修改,可读性一般。
SGI版本:由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版 本。被GCC(Linux)采用,可移植性好,
可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。
STL的六大组件
空间配置器:allocator
容器:string
,vector
,list
,deque
,map
,set
,multimap
.mutilset
配接器:stack
,queue
,priority_queue
仿函数:greater
,less
算法:find
,swap
,reverse
,sort
,merge
迭代器:iterator
,const_iterator
,reverse_iterator
,const_reverse_iterator
string
概念:string是C++、java、VB等编程语言中的字符串,字符串是一个特殊的对象,属于引用类型。 在java、C#中,String类对象创建后,字符串一旦初始化就不能更改,因为string类中所有字符串都是常量,数据是无法更改,由于string对象的不可变,所以可以共享。对String类的任何改变,都是返回一个新的String类对象。 C++标准库中string类以类型的形式对字符串进行封装,且包含了字符序列的处理操作
string类的常见接口
1.构造函数
函数名称 | 功能简述 |
---|---|
string() | 构造空的string类对象 |
string(const char* s) | 用C-string来构造string对象 |
string(size_t n,char c) | string类对象中包含n个字符c |
string(const string&s) | 拷贝构造 |
string(const string&s,size_t n) | 将从s中第n位起的字符够造成一个新的string类对象 |
void TestString()
{
string s1;
string s2("hello");
string s3(10, 'd');
string s4(s2);
string s5(s2, 1);
cout << "s1=" << s1 << endl;
cout << "s2=" << s2 << endl;
cout << "s3=" << s3 << endl;
cout << "s4=" << s4 << endl;
cout << "s5=" << s5 << endl;
}
输出
s1=
s2=hello
s3=dddddddddd
s4=hello
s5=ello
2.容量操作
函数名称 | 功能简述 |
---|---|
size_t size() const | 返回字符串有效字符长度 |
size_t length() const | 返回字符串有效字符长度 |
size_t caoacity() const | 返回空间总大小 |
bool empty() const | 判断字符串是否为空,是返回true ,否返回false |
void clear() | 清空字符串 |
void resize(size_t n,char c) | 将有效字符的个数改成n个,多余的空间用字符c 进行填充 |
void resize(size_t n) | 将有效字符的个数改成n个,多余的空间用0 进行填充 |
void reserve(size_t res_arg=0) | 为字符串预留空间 |
void TestString1()
{
string s1("abcdef");
cout << "s1.size()=" << s1.size() << endl;
cout << "s1.length()=" << s1.length() << endl;
cout << "s1.capacity()=" << s1.capacity() << endl;
cout << "s1.empty()=" << s1.empty() << endl;
s1.clear();
cout << "s1.clear()=" << s1 << endl;
cout << "s1.capacity()=" << s1.capacity() << endl;
string s2("hello");
cout << "s2=" << s2 << endl;
s2.resize(50, 'a');
cout << "s2.resize(50,'a')=" << s2 << endl;
cout << "s2.capacity()=" << s2.capacity() << endl;
s2.resize(3, 'b');
cout << "s2.resize(3,'b')=" << s2 << endl;
cout << "s2.capacity()=" << s2.capacity() << endl;
string s3("hehe");
s3.reserve(100);
cout << "s3.size()=" << s3.size() << endl;
cout << "s3.capacity()=" << s3.capacity() << endl;
string s4("abcd");
s4.reserve(2);
cout << "s4.size()=" << s4.size() << endl;
cout << "s4.capacity()=" << s4.capacity() << endl;
}
输出
s1.size()=6
s1.length()=6
s1.capacity()=15
s1.empty()=0
s1.clear()=
s1.capacity()=15
说明clear()只会清空字符串,而不是删除字符串
s2=hello
s2.resize(50,'a')=helloaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
s2.capacity()=63
说明resize(n,'c')当n大于当前的capacity会自动增容,多余的空间用'c'进行填充
s2.resize(3,'b')=hel
s2.capacity()=63
说明resize(n,'c')当n小于当前的capacity,capacity不变,多余的空间用'c'进行填充
s3.size()=4
s3.capacity()=111
s4.size()=4
s4.capacity()=15
说明reserve(n)之后,size()和length()的大小不变,只是capacity不够时会自动增容
3.访问操作
函数名称 | 功能简述 |
---|---|
char& operator[] (size_t pos) | 返回pos位置的字符 const string类对象调用 |
const char& operator[] (size_t pos) const | 返回pos位置的字符,非const string类对象调用 |
void TestString2()
{
string s1("abcdef");
const string s2("ABCDEF");
cout << "s1=" << s1 << endl;
cout << "s1[2]=" << s1[2] << endl;
for (size_t i = 0;i < s1.size();++i)
{
cout << s1[i] << endl;
}
s1[0] = 'h';
cout << "执行s1[0] = 'h'后" << endl;
cout << "s1=" << s1 << endl;
cout << "s2=" << s2 << endl;
cout << "s2[2]=" << s2[2] << endl;
//s2[0] = 'H';会报错const类型不可被修改
}
输出
s1=abcdef
s1[2]=c
a
b
c
d
e
f
执行s1[0] = 'h'后
s1=hbcdef
s2=ABCDEF
s2[2]=C
4.修改操作
函数名称 | 功能简述 |
---|---|
void push_back(char c) | 在字符串最后尾插字符c |
string& append(const string* s) | 在字符串最后追加一个字符串 |
string& operator+=(const string& str) | 在字符串最后追加字符串str |
string& operator+=(char c) | 在字符串最后追加字符c |
const char* c_str()const | 返回C格式字符串 |
size_t find(char c,size_t pos=0)const | 从字符串第pos 个位置开始往后找字符c ,返回c 在字符串中的位置,若不存在返回-1 |
size_t rfind(char c,size_t pos =npos) | 从字符串第pos 个位置开始往前找字符c ,返回c 在字符串中的位置,若不存在返回-1 |
string substr(size_t pos=0,size_t n=npos) const | 在字符串中从pos 位置开始,截取n 个字符,然后将其返回 |
void TestString3()
{
string s1("a");
s1.push_back('b');
cout << "执行s1.push_back('b')后" << endl;
cout << s1 << endl;
s1 = s1.append("cd");
cout << "执行s1 = s1.append(cd)后" << endl;
cout << s1 << endl;
string s2("e");
s1 += s2;
cout << "执行s1 += s2;s2=e后" << endl;
cout << s1 << endl;
s1 += "fh";
cout << "执行s1 += fh;后" << endl;
cout << s1 << endl;
s1 += 'j';
cout << "执行s1 += 'j';后" << endl;
cout << s1 << endl;
int num1 = s1.find('c', 0);
cout << num1 << endl;
int num2 = s1.rfind('c', 5);
cout << num2 << endl;
int num3 = s1.find('z', 0);
cout << num3 << endl;
string s3 = s1.substr(0, 3);
cout << s3 << endl;
string s4 = s1.substr(7, 3);
cout << s4 << endl;
cout << s1.c_str() << endl;//相当于将s1打印一遍
}
输出
执行s1.push_back('b')后
ab
执行s1 = s1.append(cd)后
abcd
执行s1 += s2;s2=e后
abcde
执行s1 += fh;后
abcdefh
执行s1 += 'j';后
abcdefhj
2
2
-1
abc
j
abcdefhj
void TestString4()
{
//取文件后缀
string s1("file.cpp");
size_t pos = s1.find('.');//直接就可以得到'.'的位置
string s2 = s1.substr(pos, s1.size() - pos);
cout << s2 << endl;
//取域名
string s3("http://www.cplusplus.com/reference/string/string/append/");
cout << s3 << endl;
string s4("https://baike.baidu.com/item/%E8%BF%AD%E4%BB%A3%E5%99%A8/3803342?fr=aladdin");
cout << s4 << endl;
size_t start = s4.find("://");
start += 3;
size_t finish = s4.find('/', start);
cout << s4.substr(start, finish - start) << endl;
}
输出
.cpp
http://www.cplusplus.com/reference/string/string/append/
https://baike.baidu.com/item/%E8%BF%AD%E4%BB%A3%E5%99%A8/3803342?fr=aladdin
baike.baidu.com
5.非成员函数
函数名称 | 功能简述 |
---|---|
operator+ | 加法运算符重载 |
operator>> | 输入运算符重载 |
operator<< | 输出运算符重载 |
getline | 获取一行字符串 |
relational operators | 大小比较 |
void TestString5()
{
string s1("ab");
string s2("cde");
cout << s1 + s2 << endl;
string s3;
getline(cin, s3);
cout << s3 << endl;
cout << (s1 < s2)<< endl;//比较的是size
cout << (s1 > s2) << endl;
cout << (s1 == s2) << endl;
cout << (s1 >= s2) << endl;
}
输出
abcde
ee
ee
1
0
0
0
深拷贝
class String
{
public:
/*String()
:_str(new char[1])
{
_str[0] = '\0';
}
String( char* str)
:_str(new char[strlen(str) + 1])
{
strcpy(_str, str);
}*/
//可以将这两合并成一个全缺省参数的函数
String(const char* str = "")
:_str(new char[strlen(str) + 1])
{
strcpy(_str, str);
}
String(const String& s)
:_str(new char[strlen(s._str) + 1])
{
strcpy(_str, s._str);
}
~String()
{
if (_str)
{
printf("~String()\n");
delete[] _str;
_str = nullptr;
}
}
String operator=(const String& s)
{
if (this != &s)//写了这个才可以实现自己给自己赋值
{
//不管哪个长都把旧的给释放掉
delete[] _str;
_str = new char[strlen(s._str) + 1];
strcpy(_str, s._str);
return *this;
}
}
char& operator[](size_t index)
{
return _str[index];
}
const char* c_str()
{
return _str;
}
private:
char* _str;
};
迭代器
迭代器是能够用来遍历STL容器中元素的一种对象,也可以理解成一个复杂的指针,它还提供一些基本操作符:*、++、==、!=、=。具有遍历各种复杂数据结构的能力,但是它的底层机构取决于其所遍历的数据结构,因此,每种容器都会提供属于自己的迭代器。
typedef char* Iterator;
Iterator Begin() const
{
return _str;
}
Iterator End() const
{
return _str + _size;
}
typedef char* Const_Iterator;
Const_Iterator Const_Begin() const
{
return _str;
}
Const_Iterator Const_End() const
{
return _str + _size;
}
范围:左闭右开[)
void Iterator()
{
string s1("abcdef");
string::iterator it1 = s1.begin();
while (it1 != s1.end())
{
cout << *it1 << endl;
++it1;
}
}
迭代器的第一个位置指向s1的第一个位置
迭代器最后一个位置指向s1最后一个位置的下一个位置