STL (standard template libaray - 标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架
(),使得可以像函数一样调用这个类对象。STL中的很多算法都可以接受仿函数作为参数,以实现更加灵活的功能。
在 C 语言中,字符串是以 null 结尾的字符数组,需要手动管理内存和处理字符串操作。
string.h头文件提供了一系列库函数,如strlen、strcpy、strcat等,用于对字符串进行操作。但是这些函数的确与字符串是分离的,需要手动管理内存,容易出现越界访问等问题。 而在 C++ 标准库中,提供了std::string类,它封装了字符串的操作,提供了丰富的成员函数和运算符重载,使得字符串的操作更加方便和安全。std::string类封装了字符串数据和长度,隐藏了内存管理的细节,提供了自动扩容、内存管理、异常安全性等功能,大大简化了字符串的操作
总结:
std::string 是 C++ 标准库中的一部分,而 STL(标准模板库)是 C++ 标准库的子集,但是由于它和其他 STL 容器(如 std::vector、std::list)有着相似的使用方式,因此可以将其放在一起学习和使用(出现了.length()和.size()计算长度的原因,一个是自带的,一个是为了与其他容器相配)
typedef basic_string<char, char_traits, allocator> string,是 basic_string 类模板使用字符类型 char 实例化得到的一个类

basic_string<char>

构造函数名称 | 功能说明 |
|---|---|
string() | 构造空的string类对象,即空字符串 |
string(const char* s) | 用 C 风格的字符串(以 null 结尾的字符数组)来构造string类对象 |
string(size_t n, char c) | string类对象中包含n个字符c |
string(const string& s) | 拷贝构造函数 |
#include<iostream>
using namespace std;
int main()
{
string s1;
string s2("abcd");
string s3(5, 'c');
string s4(s2);
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
cout << s4 << endl;
return 0;
}

重载了下标操作符
[],使得可以像访问数组一样使用下标来访问字符串中的单个字符,同时我们要注意返回值是char&,我们也可以进行更改等其他操作。
int main()
{
string s1 = "abcde";//拷贝构造
for (int i = 0; i < s1.size(); ++i)//进行遍历
{
cout << s1[i] << " ";
}
cout << endl;
//进行更改
s1[0] = '1';
cout << s1;
return 0;
}
int main()
{
string s1 = "abcde";//拷贝构造
for (auto e: s1)//只能遍历
{
cout << e << " ";
}
cout << endl;
for (auto& e : s1)//想要改变,加&
{
e = 'a';
cout << e << " ";
}
cout << endl;
return 0;
}
在 C++ 标准库中,
std::string类提供了迭代器,用于遍历字符串中的字符。std::string类的迭代器类型为std::string::iterator,它是随机访问迭代器,支持随机访问操作(还没有正式讲到它,大家现在就把他当指针)
int main()
{
string s1 = "abcde";//拷贝构造
string::iterator it = s1.begin();//迭代器1.大多数的数据结构都有,但是[]不是都有的
//2. 迭代器能跟算法一起用,下面就是结合了reverse的使用
while (it != s1.end())
{
cout << *it << " ";
it++;
}
return 0;
}我们还是更倾向于使用迭代器:
[]不是都有的[]要求物理底层是连续的reverse()(逆置)的使用int main()
{
string s1 = "abcde";//拷贝构造
string::iterator it = s1.begin();
while (it != s1.end())
{
cout << *it << " ";
it++;
}
cout << endl;
reverse(s1.begin(), s1.end());//开始翻转
it = s1.begin();
while (it != s1.end())//再次打印
{
cout << *it << " ";
it++;
}
cout << endl;
list<double> l1;//定义一个链表来说明,迭代器两个特点
l1.push_back(1.1);
l1.push_back(2.2);
l1.push_back(3.3);
list<double>::iterator lit=l1.begin();
while (lit != l1.end())
{
cout << *lit << " ";
lit++;
}
cout << endl;
reverse(l1.begin(), l1.end());
lit = l1.begin();
while (lit != l1.end())
{
cout << *lit << " ";
lit++;
}
cout << endl;
return 0;
}
迭代器是一种数据类型。在C++中,迭代器实际上是一种对象,它被设计用于在容器中进行元素的遍历和访问。迭代器为程序员提供了一种抽象的方式来访问容器中的元素,而不用关心容器的底层实现细节

迭代器名称 | 功能说明 |
|---|---|
begin() | 返回一个指向字符串中第一个字符的迭代器 |
end() | 返回一个指向字符串最后一个字符下一个位置的迭代器 |
rbegin() | 反向开始,返回一个指向字符串最后一个字符的迭代器 |
rend() | 反向开始,返回一个指向字符串中第一个元素之前的位置的迭代器 |
std::string类提供了多种类型的迭代器,包括正向迭代器(iterator)、常量正向迭代器(const_iterator)、反向迭代器(reverse_iterator)和常量反向迭代器(const_reverse_iterator)
std::string::iterator 类型是用于遍历可修改字符串的迭代器,可以通过 begin() 和 end() 方法获取范围std::string::const_iterator 类型是用于遍历不可修改字符串的迭代器,可以通过 begin() 和 end() 方法获取范围。std::string::reverse_iterator 类型是用于以反向顺序遍历可修改字符串的迭代器,可以通过 rbegin() 和 rend() 方法获取范围std::string::const_reverse_iterator 类型是用于以反向顺序遍历不可修改字符串的迭代器,可以通过 crbegin() 和 crend() 方法获取范围反向用的少点

begin()返回指向容器中第一个元素的迭代器 这是一个重载:
iterator begin(); 用于非常量对象,它返回一个迭代器,可以用于修改容器中的元素(可读可写)。const_iterator begin() const; 用于常量对象,它返回一个常量迭代器,用于指向容器中的元素,不允许修改容器中的元素(只读)int main()
{
string s = "abcde";
const string cs = "abc";
string::iterator it = s.begin();//会去找最适合的,string::const_iterator it = s.begin();可以
//还是,权限不能放大,只能缩小
string::const_iterator cit = cs.begin();//用string::iterator cit = cs.begin();会报错
return 0;
}
end()用于返回指向容器中最后一个元素之后位置的迭代器 也是两个重载,与begin()一样


rbegin函数返回一个反向迭代器,指向容器中最后一个元素。反向迭代器允许从容器的末尾向前遍历容器中的元素。rend函数返回一个反向迭代器,指向容器中第一个元素之前的位置。通常用于标记反向遍历的结束位置。 这两个也都有重载两个:反向和常量反向
所以也能看到:后面四个虽然是c11新加的东西,但是没人用

函数名称 | 功能说明 |
|---|---|
size()(重点) | 返回字符串有效字符长度 |
length() | 返回字符串有效字符长度 |
capacity () | 返回当前分给字符串空间总大小 |
empty() (重点) | 检测字符串释放为空串,是返回true,否则返回false |
clear() (重点) | 清空有效字符 |
reserve() (重点) | 为字符串预留空间(不同版本具体实现不同,没有硬性规定) |
resize (重点) | 将有效字符的个数该成n个,多出的空间用字符c填充 |
二者作用其实完全相同: 返回字符串有效字符长度 为什么有两个也是历史原因了.这里推荐大家经常用size(),好与后面联系起来
int main()
{
string s1("abcde");
cout << s1.size() << endl;
cout << s1.length() << endl;
return 0;
}
capacity()是 C++ 中std::string类的一个成员函数,用于返回当前字符串对象分配的存储空间大小(即容量)。字符串对象的容量指的是在不重新分配内存的情况下,字符串可以存储的最大字符数
size_t capacity() const noexcept;capacity() 返回的是字符串对象分配的总空间,而不是当前字符串的实际长度。capacity() 返回的值可能会大于 size() 返回的值,因为 size() 表示实际存储的字符数,而 capacity() 表示分配的总空间int main()
{
string s1("abcde");
cout << s1.size() << endl;
cout << s1.capacity() << endl;
return 0;
}
void reserve(size_t n);n 个字符的存储空间,即提前分配足够的空间,但并不改变字符串的实际大小。如果 n 大于当前容量,reserve 可能导致内存重新分配,否则,它只是更新容量而无需重新分配内存reserve 不影响字符串的实际大小,即 size() 的值不会改变。n 大于当前容量,reserve 可能会导致重新分配内存,但并不会初始化新分配的部分void resize(size_t n, char c = char());或者void resize (size_t n);n,并根据需要插入或删除字符,使得字符串的实际大小等于 n。如果 n 小于当前大小,多余的字符将被删除;如果 n 大于当前大小,字符串将被扩展,并使用字符 c 填充新增的部分; 要是不写就是null characters(\0)resize 会修改字符串的实际大小,即 size() 的值会变为 n。(可以缩小,同时也删除了)n 大于当前大小,新增的部分将用字符 c 填充;要是不写就是null characters(\0)
int main()
{
string s1("abcde");
s1.resize(10);
cout << s1.capacity() << endl;
cout << s1 << endl;
s1.resize(3);
cout << s1.capacity() << endl;
cout << s1 << endl;
return 0;
}

string& operator+=(const string& str);str 进行连接,即将 str 的内容附加到当前字符串的末尾int main()
{
string s1("abcde");
s1 += "111";
cout << s1 << endl;
return 0;
}

前者是,在
pos这个下标前插入str字符串 后者是,在pos下标前插入n个c
int main()
{
string s1 = "abc";
cout << s1 << endl;
s1.insert(0, "111");//0前面不就相当于头插嘛
cout << s1 << endl;
s1.insert(0, 2, 'x');
cout << s1 << endl;
return 0;
}

删除从下标
pos处开始算起的len个字符
int main()
{
string s1 = "abc";
cout << s1 << endl;
s1.insert(0, "111");//0前面不就相当于头插嘛
cout << s1 << endl;
s1.insert(0, 2, 'x');
cout << s1 << endl;
s1.erase(0, 5);//从0处,删除5个
cout << s1 << endl;
return 0;
}

npos是 C++ 中std::string类的一个静态成员变量,表示无效或不存在的位置。通常用于标识字符串查找等操作未找到匹配项的情况。npos的类型是size_t,它是一个无符号整数类型


find 用于返回 一个字符或一个字符数组或一个string对象 在 string 中首次出现的位置(返回下标),如果找不到就返回 npos
整体跟
find类似。从后往前找,找到一个字符或一个字符数组或一个string对象最后一次出现的位置,如果找不到就返回 npos

从
pos处开始截取len长度(默认的话,截取到最后)
int main()
{
string s1("test.c");
//得到文件后缀
size_t pos1 = s1.find('.');
if (pos1 != string::npos)
{
string ret1 = s1.substr(pos1);
cout << ret1 << endl;
}
//如果文件名含有 . 怎么办
string s2("te.st.c");
size_t pos2 = s2.rfind('.');
if (pos2 != string::npos)
{
string ret2 = s2.substr(pos2);
cout << ret2 << endl;
}
return 0;
}