一、STL简介
STL是C++中的标准模板库(Standard Template Library)的缩写。它是C++标准库的一部分,提供了一系列的数据结构和算法模板,包括各种容器、算法、迭代器、仿函数等,用于简化和加速C++程序的开发过程。STL的设计理念是提供通用、高效的数据结构和算法实现,使得开发者可以更加专注于业务逻辑的实现,提高代码的可读性、可维护性和可移植性。
STL在C++中有以下几个主要用处:
-
提供丰富的数据结构:STL包含了各种常用的容器,如动态数组(vector)、双向链表(list)、映射(map)、集合(set)等。这些数据结构可以满足不同的需求,如存储数据、快速查找、有序存储等。
-
实现高效的算法:STL提供了大量的算法模板,包括排序、查找、变换、合并等,这些算法经过了优化和测试,通常具有高效的执行速度和可靠的性能。开发者可以直接使用这些算法,无需自己从头实现,提高了开发效率。
-
提供灵活的迭代器:STL中的迭代器提供了一种统一的访问数据结构元素的方式,包括输入迭代器、输出迭代器、正向迭代器、双向迭代器和随机访问迭代器等。开发者可以根据需要选择合适的迭代器类型进行数据遍历和操作。
-
支持泛型编程:STL是基于模板的,支持泛型编程。这意味着开发者可以编写通用的代码,适用于不同类型的数据结构和数据类型,提高了代码的复用性和通用性。
-
提高代码的可读性和可维护性:STL提供了经过优化和测试的标准化实现,使得代码更加清晰易懂。开发者可以直接使用STL提供的功能模块,避免了重复造轮子的工作,同时也降低了出错的风险,提高了代码的可维护性和可读性。
综上所述,STL在提高开发效率和代码质量等方面具有很大的作用,是C++程序开发中不可或缺的重要工具。
STL六大组件:
网上有句话说:“不懂STL,不要说你会C++”。STL是C++中的优秀作品,有了它的陪伴,许多底层的数据结构以及算法都不需要自己重新造轮子,使我们能够快速地进行开发。
我们的STL系列将从容器string部分开始介绍。
二、string类
标准库类型string表示可变长的字符序列,使用string类型必须首先包含string头文件。作为标准库的一部分,string定义在命名空间std中。
1.定义和初始化string对象
string是一个类,因此,实例化出string类时,会调用该类的构造函数。string对象也可以使用其他方式来初始化。常用的string对象构造方法有以下几种:
string s1;// 调用默认构造函数,s1是一个空字符串
string s2 = s1;// 调用拷贝构造函数
string s3 = "hello world!"; // 使用字符串初始化s3
string s4(10, 's'); // 使用10个's'字符初始化s4
string s5(s3, 6, 3);// 从第七个字符开始,将3个s3字符串中的字符拷贝到s5中
string s6(s3, 3);// 将前3个s3字符串中的字符拷贝到s6中
在构造s5的过程中,可以不传第三个参数,那么编译器将会将第三个参数设为string::npos,而string::npos的值为大约42亿,也就是说,编译器会将s3中的从第七个字符开始,拷贝42亿个字符给s5,但是s3显然没有那么多字符。所以当遇到s3字符串的结尾时,编译器将会停止拷贝。那如果第三个参数传的过大,拷贝长度大于从开始到结尾的长度,那也是遇到字符串末尾然后停止拷贝。
string类中重载了流插入<<、流提取>>操作符,使我们可以像打印、输入int型、char型等内置类型一样打印或输入string型。也重载了内置类型常用的大多数操作符。
2.遍历string对象
string类中重载了'[]'运算符,使我们可以像遍历字符数组一样遍历string对象。
void test1()// string对象的遍历
{
string s1("hello world!");
for (int i = 0; i < s1.size(); i++)
{
cout << s1[i] << ' ';
}
}
int main()
{
test1();
return 0;
}
运行程序,结果如下:
也可以将上面的循环换为范围for循环来遍历string对象,使用起来更加方便。
三、string类成员函数
1.容量
(1)size和length
size_t size() const;
size_t length() const;
string类中有求字符串长度的函数size()和length(),它们的作用相同。调用方法如下:
void test1()
{
string s1("hello world!");
string s2("hellohello world!");
cout << s1.size() <<endl;
cout << s2.length();
}
运行程序,结果如下:
(2)max_size
string类中的max_size()函数用于求字符串的潜在最大长度。
size_t max_size() const;
调用该函数之后,会得到一个非常大的数字。
(3)resize
void resize (size_t n);
void resize (size_t n, char c);
string类中提供了两个调节字符串大小的函数。第一个参数都是一个无符号整形,意思是将字符串大小调整为n。若字符串长度大于n,那么n之后的字符将会丢弃,若字符串的长度小于n,那么第一个函数将会在n之后填充空字符,第二个函数则会使用指定的字符填充。
我们知道,字符串末尾还隐藏了一个‘\0’字符。空字符是不计入长度的。计算字符串长度时,遇到任意空字符就停止计数。打印的时候也是以任意空字符为结尾的。
void test1()
{
string s1("hello\0\0\0\0\0 world! ");
string s2("hellohello world!");
//s1.resize(18);
cout << s1 << 'a' << endl;
cout << s1.size() << endl;
}
运行程序,结果如下:
但是我们将resize函数取消注释,再次运行程序:
发现长度来到了18,也就是说,编译器填充的空字符,是计入长度的。
通过监视窗口我们看到,没有执行resize语句时,s1中字符串只有五个字符,执行之后,后面13个字符都是\0并且计入长度。
(4)capacity
size_t capacity() const;
string类中有计算容量的成员函数,它表示编译器为对象实际分配的内存空间,它可以大于或等于字符串的长度。若容量满时,会自动扩容。
(5)reverse
void reserve (size_t n = 0);
reverse函数使用来修改字符串容量的。给reverse传的参数n是告诉编译器假定字符串的长度为n,然后让编译器重新为对象分配空间。编译器会结合实际字符串长度来分配空间。若n小于实际字符串长度,容量的变化具体看编译器。
(6)clear
void clear();
它的作用为清空字符串。使对象变为长度为0的字符串。
(7)empty
bool empty() const;
它的作用是判断字符串是否为空,并不会改变字符串中的内容。
(8)shrink_to_fit
bool empty() const;
请求字符串减小其容量以适应其大小。
2.元素访问
(1)operator[]
string类中具有运算符重载, 使我们可以像访问数组那样访问string对象中的值。
char& operator[] (size_t pos);
const char& operator[] (size_t pos) const;
(2)at
char& at (size_t pos);
const char& at (size_t pos) const;
返回对字符串中位置pos处的字符的引用。
(3)back
char& back();
const char& back() const;
返回对字符串最后一个字符的引用。此函数不应在空字符串上调用。
(4)front
char& front();
const char& front() const;
返回对字符串第一个字符的引用。此函数不应在空字符串上调用。
3.修改
(1)operator+=
string& operator+= (const string& str);
string& operator+= (const char* s);
string& operator+= (char c);
string具有+=重载函数,使我们可以像内置类型一样使用+=操作符:
void test1()
{
string s1("hello world!");
string s2("hi");
s1 += "sss";
s1 += 'a';
s1 += s2;
cout << s1 << endl;
cout << s1.size() << endl;
}
运行代码,结果如图所示:
有了+=重载操作符重载,我们可以很方便地为字符串后添加字符。
(2)append
string& append (const string& str);
string& append (const string& str, size_t subpos, size_t sublen);
string& append (const char* s);
string& append (const char* s, size_t n);
string& append (size_t n, char c);
template <class InputIterator>
string& append (InputIterator first, InputIterator last);
append也表示向字符串的末尾添加字符串。它重载了许多函数,实现了很多功能。
string& append (const string& str);
表示向一个string对象末尾添加另一个string对象,也就是在一个字符串的末尾添加另一串字符串。
string& append (const string& str, size_t subpos, size_t sublen);
表示向一个string对象末尾添加另一个string对象的一部分,它从subpos位置开始,直到拷贝长度达到sublen时为止或者直到遇到字符串末尾。
string& append (const char* s);
表示向string对象末尾附加一个由指针变量指向的字符串。
string& append (const char* s, size_t n);
表示向string对象末尾附加一个由指针变量指向的字符串的前n个字符。
string& append (size_t n, char c);
表示向string对象末尾附加n个c字符。
(3)push_back
void push_back (char c);
表示向string对象末尾附加1个c字符。
(4)assign
string& assign (const string& str);
string& assign (const string& str, size_t subpos, size_t sublen);
string& assign (const char* s);
string& assign (const char* s, size_t n);
string& assign (size_t n, char c);
assign表示赋值,将当前值清空并赋新值。
string& assign (const string& str);
表示将另一个string对象赋给当前string对象。
string& assign (const string& str, size_t subpos, size_t sublen);
表示将另一个string对象的一部分赋给当前string对象。从subpos开始,到sublen处结束,或遇到字符串尾结束。
string& assign (const char* s);
表示将s指向的字符串赋给当前string对象。
string& assign (const char* s, size_t n);
表示将s指向的字符串的前n个字符赋给当前string对象。
string& assign (size_t n, char c);
表示将n个c字符赋给当前string对象。
(5)insert
string& insert (size_t pos, const string& str);
string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);
string& insert (size_t pos, const char* s);
string& insert (size_t pos, const char* s, size_t n);
string& insert (size_t pos, size_t n, char c);
void insert (iterator p, size_t n, char c);
insert也表示插入,它支持在任意位置插入。不过它的效率不高。
string& insert (size_t pos, const string& str);
表示在下标pos之后插入一个string对象。
string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);
表示在下标pos之后插入一个string对象的一部分,它从subpos处开始,直到拷贝长度达到sublen或者遇到字符串结尾。
string& insert (size_t pos, const char* s);
表示在pos位置插入一个s指向的字符串。
string& insert (size_t pos, const char* s, size_t n);
表示在pos位置插入一个s指向的字符串的前n个字符。
string& insert (size_t pos, size_t n, char c);
表示在pos位置插入n个字符c。
(6)erase
string& erase (size_t pos = 0, size_t len = npos);
erase表示删除,删除从pos位置开始, 直到删除长度达到len或者对象中已经无字符。若不传参数,那么表示全部删除。
(7)replace
string& replace (size_t pos, size_t len, const string& str);
string& replace (size_t pos, size_t len, const string& str,
size_t subpos, size_t sublen);
string& replace (size_t pos, size_t len, const char* s);
string& replace (size_t pos, size_t len, const char* s, size_t n);
string& replace (size_t pos, size_t len, size_t n, char c);
replace表示替换。
string& replace (size_t pos, size_t len, const string& str);
表示从下标pos位置开始,len长度的字符替换为另一个string对象中的字符串。
string& replace (size_t pos, size_t len, const string& str,
size_t subpos, size_t sublen);
表示从下标pos位置开始,len长度的字符替换为另一个string对象中的字符串的一部分,从小标subpos位置开始,拷贝sublen长度的字符串或遇到字符串末尾。
string& replace (size_t pos, size_t len, const char* s);
表示从下标pos位置开始,len长度的字符替换为s指向的字符串。
string& replace (size_t pos, size_t len, const char* s, size_t n);
表示从下标pos位置开始,len长度的字符替换为s指向的字符串的前n个字符。
string& replace (size_t pos, size_t len, size_t n, char c);
表示从下标pos位置开始,len长度的字符替换为n个c字符。
(8)swap
void swap (string& str);
void swap (string& x, string& y);
交换两string对象的值。
void test1()
{
string s1("hello world!");
string s2("abcdefg");
s1.swap(s2);
cout << s1 << endl;
cout << s2 << endl;
}
运行代码,结果如下图所示:
(9)pop_back
void pop_back();
尾部删除一个字符。
(10)getline
istream& getline (istream& is, string& str, char delim);
istream& getline (istream& is, string& str);
从流中提取一行字符串到string对象中,直到遇到delim(界定字符)或换行符。若指定了界定字符,那么当输入界定字符之后,编译器会只保留界定字符之前的字符,将string对象存储的值删除,并添加上新输入的字符。若没有指定界定字符,那么当遇到换行符时,即代表输入结束。
4.字符串操作
(1)c_str
const char* c_str() const;
返回一个字符串指针,指向一块存储着C风格字符串的空间。字符串的末尾附加了一个空字符。
(2)data
const char* data() const;
返回一个字符串指针,指向一块存储着C风格字符串的空间。在C++11之前,该字符串末尾不附加空字符,C++11之后,附加了一个空字符,执行与c_str一样的操作。
(3)copy
size_t copy (char* s, size_t len, size_t pos = 0) const;
从pos位置开始,拷贝len个长度的字符到s指向的空间中。返回拷贝字符的个数。
(4)find
size_t find (const string& str, size_t pos = 0) const;
size_t find (const char* s, size_t pos = 0) const;
size_t find (const char* s, size_t pos, size_type n) const;
size_t find (char c, size_t pos = 0) const;
第一个重载成员函数可以查找子字符串,pos是开始查找的位置。若找到则返回子字符串在字符串中的下标,若找不到则返回nops。
第二个重载成员函数可以查找s指向的字符串。
第三个重载成员函数可以查找s指向的字符串,第三个参数n是查找的长度,若小于被查找的字符串长度,则查找前n个字符组成的字符串。
第四个重载成员函数可以查找指定的字符。
(5)rfind
size_t rfind (const string& str, size_t pos = npos) const;
size_t rfind (const char* s, size_t pos = npos) const;
size_t rfind (const char* s, size_t pos, size_t n) const;
size_t rfind (char c, size_t pos = npos) const;
查找要查找的对象最后一次出现的位置。
(6)find_first_of
size_t find_first_of (const string& str, size_t pos = 0) const;
size_t find_first_of (const char* s, size_t pos = 0) const;
size_t find_first_of (const char* s, size_t pos, size_t n) const;
size_t find_first_of (char c, size_t pos = 0) const;
在string对象中查找一个字符,它同时出现在另一个对象中并且在string对象中是第一个这样的字符。返回该字符的下标。支持查找另一个string对象、指针指向的空间,单个字符。
size_t find_last_of (const string& str, size_t pos = npos) const;
size_t find_last_of (const char* s, size_t pos = npos) const;
size_t find_last_of (const char* s, size_t pos, size_t n) const;
size_t find_last_of (char c, size_t pos = npos) const;
在string对象中查找一个字符,它同时出现在另一个对象中并且在string对象中是最后一个这样的字符。
(7)find_first_not_of
size_t find_first_not_of (const string& str, size_t pos = 0) const;
size_t find_first_not_of (const char* s, size_t pos = 0) const;
size_t find_first_not_of (const char* s, size_t pos, size_t n) const;
size_t find_first_not_of (char c, size_t pos = 0) const;
在string对象中查找一个字符,它在另一个对象中不存在,并且是第一个这样的字符,返回该字符的下标。
(8)find_last_not_of
size_t find_last_not_of (const string& str, size_t pos = npos) const;
size_t find_last_not_of (const char* s, size_t pos = npos) const;
size_t find_last_not_of (const char* s, size_t pos, size_t n) const;
size_t find_last_not_of (char c, size_t pos = npos) const;
在string对象中查找一个字符,它在另一个对象中不存在,并且是最后一个这样的字符,返回该字符的下标。
(9)substr
string substr (size_t pos = 0, size_t len = npos) const;
创建一个子字符串,该子字符串的值为string对象中从pos位置开始,len个长度或到达字符串末尾的字符串的拷贝。
(10)compare
int compare (const string& str) const;
int compare (size_t pos, size_t len, const string& str) const;
int compare (size_t pos, size_t len, const string& str,
size_t subpos, size_t sublen) const;
int compare (const char* s) const;
int compare (size_t pos, size_t len, const char* s) const;
int compare (size_t pos, size_t len, const char* s, size_t n) const;
将字符串的值与参数指定的字符串的值进行比较。
返回值:
- =0,两字符串相等。
- >0,string对象1>string对象2。若遇到第一个字符串与第二个字符串不相等的第一个字符,比较它们的ascii值。
- <0,string对象1<string对象2。
int compare (size_t pos, size_t len, const string& str) const;
将string对象中从pos位置开始,len个长度的字符串与另一个对象比较。
int compare (size_t pos, size_t len, const string& str,
size_t subpos, size_t sublen) const;
将string对象中从pos位置开始,len个长度的字符串与另一个对象中的subpos位置开始,sublen长度的字符串比较。