STL-string

温馨提示:如有问题可在此C++网址查询

1.为什么学习string?

string相对C语言字符串有哪些优势?

  C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。OOP:面向对象编程。

2.标准库里的string类

2.1. string类

1. STL的string类是C++标准库中用于处理单字节字符串的一种数据类型。

2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

3. string在底层实际是:basic_string模板类的别名,typedef basic_string string;

4. 不能操作多字节(如Unicode字符)或者变长字符的序列。(STL string类内部使用了char类型来表示每个字符,而char类型只能表示8位的字符。对于多字节字符,例如中文字符,一个字符可能占用多个字节,因此无法直接使用STL string类来正确处理这些字符。)

在使用string类时,必须包含#include<string>头文件以及using namespace std;

2.2.string类常见接口介绍

1.string类对象的常见构造

构造函数名称功能说明
string()(重点)构造空的string类对象
string(const char* s)(重点)用C-string来构造string类对象
string(size_t n,char c)string类对象中包含n个字符c
string(const string& str)(重点)拷贝构造
string(const string& str , size_t pos , size_t len=npos)选取拷贝构造

npos:maximum value for size_t它表示字符串中无效的或未找到的位置。具体来说,它是一个特殊的std::string::size_type类型的常量,其值被定义为-1。它通常用于表示字符串操作中的失败或错误状态,或者用于指示未找到某个特定子串或字符

 void test_string1()
 {
	 string s1;//*构造
	 string s2("hello");//*构造
	 string s3("hello", 2);
	 string s4(s2);//*拷贝构造
	 string s5(s2,1, 2);
	 string s6(s2, 1);
	 string s7(10,'a');
	 s1 = s7;//*赋值

	 cout << s1 << endl;
	 cout << s2 << endl;
	 cout << s3 << endl;
	 cout << s4 << endl;
	 cout << s5 << endl;
	 cout << s6<< endl;
	 cout << s7 << endl;
 }

2.string类对象的容量操作

函数名称功能说明

size(重点)

返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小

empty(重点)

检测字符串释放为空串,是返回true,否则返回false
clear(重点)

清空有效字符

reserve(重点)为字符串预留空间
resize(重点)将有效字符的字数改为n个,多出的空间用字符C填充
#include<iostream>
#include<string>
using namespace std;

// size/clear/resize
void Teststring1()
{
	// 注意:string类对象支持直接用cin和cout进行输入和输出
	string s("hello, bit!!!");
	cout << s.size() << endl;
	cout << s.length() << endl;
	cout << s.capacity() << endl;
	cout << s << endl;

	// 将s中的字符串清空,注意清空时只是将size清0,不改变底层空间的大小
	s.clear();
	cout << s.size() << endl;
	cout << s.capacity() << endl;
	// 将s中有效字符个数增加到10个,多出位置用'a'进行填充
	// “aaaaaaaaaa”
	s.resize(10, 'a');
	cout << s.size() << endl;
	cout << s.capacity() << endl;
	// 将s中有效字符个数增加到15个,多出位置用缺省值'\0'进行填充
	// "aaaaaaaaaa\0\0\0\0\0"
	// 注意此时s中有效字符个数已经增加到15个
	s.resize(15);
	cout << s.size() << endl;
	cout << s.capacity() << endl;
	cout << s << endl;
	//将S中有效字符个数缩小到5个
	s.resize(5);
	cout << s.size() << endl;
	cout << s.capacity() << endl;
	cout<< s << endl;
}
void Teststring2()
{
	string s;
	s.reserve(100);
	cout << s.size() << endl;
	cout << s.capacity() << endl;
	// 测试reserve参数小于string的底层空间大小时,是否会将空间缩小 //结果没有将空间缩小
	s.reserve(50);
	cout << s.size() << endl;
	cout << s.capacity() << endl;
}
// 利用reserve提高插入数据的效率,避免增容带来的开销
//================================================================================
void TestPushBack()
{
	string s;
	size_t sz = s.capacity();
	cout << "making s grow:"<<sz<<endl;
	for (int i = 0; i < 100; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << endl;
		}
	}
}

void TestPushBackReserve()
{
	string s;
	s.reserve(100);
	size_t sz = s.capacity();

	cout << "making s grow:"<<sz<<endl;
	for (int i = 0; i < 200; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << endl;
		}
	}
}

1. size()函数返回的是字符串对象当前包含的字符数目,也就是字符的实际长度。(size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()。与其他容器保持一致)

2.capacity()函数返回的是字符对象当前分配的内存容量,也就是字符串可以容纳的最大字符数

扩充:字符串在自动扩充时第一次一般是(n+m)(原有内存+增加后空间,例:15+16=31),之后一般是1.5倍增加。例如:TestPushBack()。也有可能是直接1.5倍到最后。例如TestPushBackReserve()。一般会多开一个给\0。

3. clear()只是将string中有效字符清空,不改变底层空间大小

4.resize()函数用于改变字符串对象的大小。它接受一个参数,指定所需的新大小。如果新大小小于当前大小,字符串将被截断,缩短为指定大小;如果新大小大于当前大小,字符串将被扩展,并在末尾填充默认值0。

resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用默认值0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的 元素空间。

注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大 小,如果是将元素个数减少,底层空间总大小不变

5.reserve()函数用于预留字符串对象的内存空间,而不涉及字符串的大小。它接受一个参数,指定预留空间的大小。如果预留空间大于当前容量,字符串的容量将增加以容纳指定的大小;如果预留空间小于或等于当前容量,不会执行任何操作。reserve()函数主要用于避免频繁的内存重新分配操作,以提高性能。reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserver不会改变容量大小。

===============================手动分割===================================

3.string类对象的访问及遍历操作

函数名称

功能说明

operator[](重点)返回pos位置的字符,const string 类对象调用
beginbegin返回容器的迭代器,指向容器的第一个元素
endend函数返回容器的迭代器,指向容器中的最后一个元素的下一个位置。返回的迭代器实际上是一个越界位置
rebeginrebegin返回逆向迭代器,指向容器的最后一个元素
rendrend函数返回容器的逆向迭代器,指向容器中的第一个元素的前一个位置。
for范围C++11支持更简洁的for的新遍历方式
1.访问:直接使用[]进行访问
 void Teststring6()
 {
	 string s1("hello");
	 const string s2("Hello");
	 cout << s1 << s2 << endl;
	 cout << s1[0] << s2[0] << endl;
	 s1[0] = 'H';
	 cout << s1 << endl;
 }

注意:s2是const,只能读不能写

2.遍历的三种方式:
 void Teststring7()
 {
	 string s("hello");
	 //3种方式(既可以遍历也可以改写)
	 //1.for+[]
	 for (size_t i = 0; i < s.size(); i++)
		 cout << s[i] << endl;

	 //2.迭代器
	 //正向
	 string::iterator it = s.begin();
	 while (it != s.end())
	 {
		 cout << *it << endl;
		 ++it;
	 }
	 //逆向
	 string::reverse_iterator rit = s.rbegin();
	 while (rit != s.rend())
	 {
		cout << *rit << endl;
		++rit;
	 }
		 
	 //3.范围for
	 for (auto ch : s)
	 {
		 cout << ch << endl;
	 }
 }

4.string类对象的修改操作

函数名称功能说明
push_back在字符串后面插字符c
append在字符传后追加一个字符串
operator+=(重点)在字符串后追加字符串str
c_str(重点)

返回C格式字符串

find+npos(重点)从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在atr中从pos位置开始,截取n个字符,然后将其返回
erase删除起止位置之间的内容
 void Teststring8()
 {
	 string str;
	 str.push_back(' ');//插入一个空格
	 str.append("hello");//插入一个字符“hello”
	 str += 'b';
	 str += "it";
	 cout << str << endl;
	 cout << str.c_str()<<endl;//以C语言的方式打印字符串

	 //获取file的后缀
	 string file("string.cpp");
	 size_t pos = file.rfind('.');
	 string suffix(file.substr(pos, file.size() - pos));
	 cout << suffix << endl;

	 //npos是string中的一个静态成员变量
	 //static const size_t npos =-1;

	 //取出url中的域名
	 string url("http://www.cplusplus.com/reference/string/string/find");
	 cout << url << endl;
	 size_t start = url.find("://");//判断是否找到
	 if (start == string::npos)
	 {
		 cout << "invalid url" <<endl;
		 return;
	 }
	 start += 3;
	 size_t finish = url.find('/', start);
	 string address = url.substr(start, finish - start);
	 cout << address<<endl;

	 //删除url的协议前缀
	 pos = url.find("://");
	 url.erase(0, pos + 3);
	 cout << url << endl;
 }

常见的插入:+=。+=相对比较简单,且+=适用性更广一些。

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, World!";
    
    const char* cstr = str.c_str();
    
    std::cout << cstr << std::endl;  // 输出:Hello, World!
    
    return 0;
}

c_str() 的作用是将 std::string 对象中的字符串内容以 C 风格的字符串(以空字符 '\0' 结尾的字符数组)的形式返回。返回的字符指针指向的是 std::string 对象内部的字符数组的首地址。作用:1.与C语言函数进行交互。2.获取字符串的指针。

5.string类非成员函数

函数功能说明
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>>(重点)输入运算符重载
operator<<(重点)输出运算符重载
getline(重点)获取一行字符串
relational operators(重点)大小比较

  到这里就接近尾声了,感谢您能阅读完整篇文章的(说实话挺长的),希望您能从中学到string的知识,并对您的学习产生帮助。好,那这次的文章就到此结束了,如有问题和不懂的欢迎评论和私信我。

  好,我就是头发尚存的猿小二,猿小二就是我,即便是平凡,日子也成了诗。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

头发尚存的猿小二

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值