• string类基本使用


    1️⃣关于string类(标准库)

    1、string是表示字符串的字符串类。
    2、string类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
    3、string类是使用char,string在底层是:basic_string模板类的别名,typedef basic_string string。
    4、string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数。
    5、string类独立于所使用的编码来处理字节:若用来处理多字节或者变长字符(UTF-8等)的序列,string类的所有成员以及它的迭代器,将仍热按照字节来操作,而不是按照实际编码的字 符来操作。

    2️⃣string类常用接口

    string类常见构造

    在这里插入图片描述

    (constructor)函数名称功能
    string()构造空的string类对象,即构造空字符串
    string(const char * s)c_string构造string类对象
    string(const string& str)拷贝构造函数
    string(size_t n,char c)用n个字符c来构造string类对象
    int main()
    {
    	string s1;  //构造空的string类对象s1
    
    	string s2("world");   //用c形式的字符串构造string类对象s2
    	string s3 = "world";
    
    	string s4(s3);  //用s3拷贝构造s4
    
    	string s5(5, 'x'); //用5个字符x来构造s5
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    string类对象的容量操作

    resize

    ⚽️将有效字符的个数该成n个,多出的空间用字符c填充
    在这里插入图片描述

    int main()
    {
    	string s1("resize");
    	s1.resize(15);
    	string s2("resize");
    	s2.resize(15, 'x');
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    reserve

    在这里插入图片描述
    在这里插入图片描述

    🚀用reserve来提高插入数据的效率,避免频繁的增容带来的开销

    void TestReserve()
    {
    	string s;
    	s.reserve(115);
    	size_t sz = s.capacity();
    	
    	cout << "make s grow" << endl;
    	for (int i = 0;i < 115;++i)
    	{
    		s.push_back('x');
    		if (sz != s.capacity())
    		{
    			sz = s.capacity();
    			cout << "capacity changed : " << sz << endl;
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    运行测试:
    在这里插入图片描述

    void Teststring2()
    {
    	string s;
    	// 测试reserve是否会改变string中有效元素个数
    	s.reserve(100);
    	cout << s.size() << endl;
    	cout << s.capacity() << endl;
    	// 测试reserve参数小于string的底层空间大小时,是否会将空间缩小
    	s.reserve(50);
    	cout << s.size() << endl;
    	cout << s.capacity() << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    size/length/capacity

    ⚽️size - 返回字符串中有效字符的长度
    ⚽️length - 返回字符串中有效字符的长度
    ⚽️capacity - 返回当前为该字符串分配的存储空间的大小

    int main()
    {
    	string s("teststring");
    	cout << s.size() << endl;          //有效字符长度
    	cout << s.length() << endl;        //有效字符长度
    	cout << s.capacity() << endl;      //所开空间大小
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    empty

    ⚽️ 检测字符串是否为空串,是则返回true,否则返回false
    在这里插入图片描述

    clear(重点)

    ⚽️ 清空字符串的内容,它变成一个空字符串(长度为0个字符)。在这里插入图片描述

    在这里插入图片描述

    总结一下:

    1. size()与length()方法底层实现原理完全相同,实现size()的目的是与其它容器的接口保持一致,平时用size()会比较多。
    2. clear()只是将字符串中的有效字符清空,并不改变底层空间的大小。
    3. resize在改变元素的个数时,若将元素的个数增多,可能会改变底层容量的大小,若元素个数减少,底层空间大小不改变(一般不会缩空间)。
    4. reserve为string预留空间,不改变有效元素个数,若reserve的参数小于string的底层空间大小时,reserve不会改变容量大小。

    3️⃣string类对象的修改

    operator +=

    ⚽️通过在当前值的末尾添加额外的字符来扩展字符串:
    在这里插入图片描述

    int main()
    {
    	string s1 = "!!!!";
    	string s("pushback");
    	s += " ";
    	s += "追加";
    	s += s1;
    	cout << s << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行测试:
    在这里插入图片描述

    appened

    ⚽️通过在当前值的末尾添加额外的字符来扩展字符串。在这里插入图片描述

    int main()
    {
    	string s1("hello");
    	cout << s1 << endl;
    	s1.append("world");
    	cout << s1 << endl;
    
    	string s2("!!!!!!");
    	s1.append(s2.begin(), s2.end());
    	cout << s1 << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    运行测试:
    在这里插入图片描述

    push_back

    ⚽️将字符c追加到字符串的末尾,使其长度增加1。
    在这里插入图片描述

    void TestPushBack()
    {
    	string s("hell");
    	s.push_back('o');
    	cout << s << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    c_str

    ⚽️ 返回一个指向数组的指针,该数组包含一个以空结束的字符序列(即C-string),表示string对象的当前值。
    在这里插入图片描述

    void TestC_str()
    {
    	string s("frangrance  jeak");
    	cout << s << endl;             //调用 operator<<(cout,s1)
    	cout << s.c_str() << endl;     //调用 operator<<(cout,const char*)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    find

    ⚽️从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置。
    在这里插入图片描述
    ⁉️:如和写一个程序取出网址中的协议名和域名。
    在这里插入图片描述

    //取出url中的域名
    string GetDomain(const string& url)
    {
    	size_t pos = url.find("://");  
    	if (pos != string::npos) 
    	{
    		size_t start = pos + 3;
    		size_t end = url.find('/', start);
    		if (end != string::npos)
    			return url.substr(start, end - start);
    		else
    			return string();
    	}
    	else
    		return string();
    }
    
    //取出url中的协议
    string GetProtocol(const string& url)
    {
    	size_t pos = url.find('://');
    	if (pos != string::npos)
    		return url.substr(0, pos - 0);
    	else
    		return string();
    }
    
    int main()
    {
    	string url1 = "https://cplusplus.com/reference/string/string/?kw=string";
    	string url2 = "https://blog.csdn.net/";
    	cout << GetDomain(url1) << endl;
    	cout << GetDomain(url2) << endl;
    
    	cout << GetProtocol(url1) << endl;
    	cout << GetProtocol(url2) << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    rfind

    ⚽️ 从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置。
    在这里插入图片描述
    ⁉️:取出文件名的后缀

    //要求取出文件名的后缀
    int main()
    {
    	string filename = "test.txt.zip";
    	size_t pos = filename.rfind('.');
    	if (pos != string::npos)
    	{
    		string suff = filename.substr(pos);
    		cout << suff << endl;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    总结一下:
    1、在string尾部追加字符时,push_back / append / += 三种的实现方式基本没有什么区别,一般情况下使用string类的+=比较多,+=既可以连接单个字符,也可以连接字符串。
    2、操作string时,若能够预测到大约需要多少空间可以通过reserve提前开好空间,避免频繁扩容而带来的损耗。

    4️⃣非string类成员函数

    |

    5️⃣string类对象的遍历

    函数名称功能
    operator[]返回特定位置的字符,const string类对象调用
    begin+endbegin获取一个字符串的迭代器 + end获取字符串最后一个位置的下一个位置的迭代器
    rbegin+rendbegin获取一个字符串的迭代器 + end获取字符串最后一个位置的下一个位置的迭代器

    🔵遍历方式1:for + operator[]

    int main()
    {
    	string s("ejfkaj  afkjkajf");
    	for (size_t i = 0;i < s.size();++i)
    	{
    		cout << s[i] << " ";
    	}
    	cout << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    🔵遍历方式2:迭代器
    🚀[begin(),end()) end()返回的不是最后一个数据位置的迭代器,返回是最后一个位置的下一个位置。
    需要注意的是,c++中迭代器一般都是给的[)左闭右开区间。

    // 正向迭代器
    int main()
    {
    	string s("fhajh ahfjh");
    	string::iterator it = s.begin();
    	while (it != s.end())
    	{
    		cout << *it << " ";
    		++it;
    	}
    	cout << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    //反向迭代器
    int main()
    {
    	string s("123fhajh");
    	string::reverse_iterator rit = s.rbegin();
    	while (rit != s.rend())
    	{
    		cout << *rit << " ";
    		++rit;
    	}
    	cout << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    ❗️string,vector等支持[]遍历,但是list,map等容器不支持[]

    🔵遍历方式3:范围for
    🚀 c++11提供范围for,写起来更方便。一次取容器中的数据赋值给e,自动判断结束。

    int main()
    {
    	string s("ejfkaj  afjak");
    	for (auto& e : s)
    	{
    		cout << e << " ";
    	}
    	cout << endl;
    
    	for (auto e : s)
    	{
    		cout << e << " ";
    	}
    	cout << endl;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    基于springboot的应用诊断工具,yyds
    php毕业设计美食菜谱网站
    分享一个制作AI视频的好工具
    CVE-2023-23752:Joomla未授权访问漏洞复现
    Flutter应用框架搭建之屏幕适配
    基于Springboot外卖系统13:实现文件上传下载模块
    基于XC7VX690T FPGA+ZU15EG SOC的6U VPX总线实时信号处理平台(支持4路光纤)
    2.1 关系数据结构及形式化定义
    FW:HP笔记本type-c接口失效
    dc-dc线性降压恒流驱动,40V降压恒流驱动芯片
  • 原文地址:https://blog.csdn.net/qq_61939403/article/details/126255455