C++入门 string类(第一章):string类对象的构造,string类对象的访问即遍历,string类对象的增与删

🚀标准库中的string类

  1. 字符串是表示字符序列的类
  2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
  3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信息,请参阅basic_string)。
  4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
  5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

总结:
6. string是表示字符串的字符串类
7. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
8. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>string;
9. 不能操作多字节或者变长字符的序列。在使用string类时,必须包含#include头文件以及using namespace std;

🚀1.string类对象的构造

库里string类对象的构造方法:
在这里插入图片描述

string类对象有多种构造方式,但常用的只有几种。

⚡️1.1 无参构造

在这里插入图片描述

string()是string的无参构造

int main()
{
	string s1;
}

该构造函数构造空的string类对象,即空字符串。

⚡️1.2 拷贝构造

在这里插入图片描述

string(const string&s) 是string的拷贝构造

int main()
{
	string s1;
	string s2(s1); //传入string类对象
}

该构造会拷贝一个与实参一致的string类

⚡️ 1.3 C-string构造

在这里插入图片描述

string(const char* s) 支持传入C语言的字符串来构造string类对象,一般有两种形式,

int main()
{
	//第一种形式
	string s1("Hello world");

	//第二种形式
	const char temp[] = "Hello world";
	string s2(temp);
}

当然可以用 “ = ”来构造,

int main()
{
	string s1 = "Hello world";
}

这里存在隐式类型转换,即将常量字符串“Hello world”隐式转换为string类临时对象,进行拷贝构造,

在这里插入图片描述

再来看一段构造,为何它能成立?

const string& s1 = "Hello world";

“Hello world”是常量字符串,具有有常性,相应的隐式类型转换的临时对象类型为const string ,对这个临时对象其别名,必须要用const修饰

⚡️ 1.4 子字符串构造

string (const string& str, size_t pos, size_t len = npos);
子字符串构造允许构造一个string类对象的部分内容:str为被拷贝对象pos为开始拷贝的下标len为拷贝的长度

其中npos为缺省参数,是整形最大值,一定大于后面的长度,不写len时,会默认拷贝pos下标后的所有内容。

int main()
{
	string s1("Hello world");
	string s2(s1, 0, 6);
	string s3(s1, 6);
	cout << "s2 = " << s2 << endl;//s2 = Hello
	cout << "s3 = " << s3 << endl;//s3 = world
}

🚀2.string类对象的访问即遍历

⚡️ 2.1 operator[]访问类对象及遍历

在这里插入图片描述
string库中对[ ]进行了重载,使得类对象可以像数组一样访问类的成员,甚至对其做修改,

int main()
{
	string s1("Hello world");
	//访问s1的第一个字符
	s1[0];
	//修改s1的第一个字符
	s1[0] = 'a';
}

让我们深层的为什么operator[]能做到修改,

//string的[]符号重载
char& operator[](size_t i)
{
	assert(i < _size);
	return _str[i];
}

可以看到其返回的是引用,返回的是成员本身,所以可以对其修改。除此之外,返回引用也可以减少拷贝,减少消耗

对于[]符号,string还重载返回类型为 const char&,当string类对象被const修饰时,[ ]符号就不能修改
在这里插入图片描述

int main()
{
	const string s1("Hello world");
	s1[0] = 'a';//报错,调用const char& operator[],不能对const对象进行修改
}

由此,这里就有了第一种遍历string的方式

string s1("hello world");
	
	// 遍历方式1:下标+[]
	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";
	}

⚡️ 2.2 迭代器iterator遍历string

⚡️ 2.2.1 begin与end

在这里插入图片描述
利用迭代器遍历string,要用到string的成员函数:begin,end。

这两个函数返回的类型就是迭代器iterator,仅在遍历功能下,迭代器类型就类似于指针类型begin函数返回的迭代器指向string的第一个成员,end函数返回的迭代器指向string的最后一个成员的下一位。

在这里插入图片描述

iterator begin();
const_iterator begin() const;

begin函数返回的迭代器指向string的第一个成员

在这里插入图片描述

iterator end();
const_iterator end() const;

end函数返回的迭代器指向string的最后一个成员的下一位

由此就有了第二种遍历的方式:

int main()
{
	string s1("Hello world");
	string::iterator it1 = s1.begin();
	while (it1 != s1.end())
	{
		*it1 += 3;

		cout << *it1 << " ";
		++it1;
	}
	cout << endl;
}

注意:

  1. 因为每种容器都有自己的迭代器,因此在iterator前要限定作用域string::
  2. string::iterator可以替换为auto,让编译器自己推断类型,我们自己就可以不用那么累的写出具体的类型。
⚡️ 2.2.2 rbegin与rend

在这里插入图片描述

reverse_iterator rbegin();
const_reverse_iterator rbegin() const;

rbegin迭代器指向string的最后一个成员

在这里插入图片描述

reverse_iterator rend();
const_reverse_iterator rend() const;

rend迭代器指向string的第一个成员的前一位

通过rbegin与rend遍历string

int main()
{
	string s1("Hello world");
	string::reverse_iterator it1 = s1.rbegin();
	while (it1 != s1.rend())
	{
		*it1 -= 1;

		cout << *it1 << " ";
		++it1;
	}
	cout << endl;
}
⚡️ 2.2.3 const_iterator

无论是begin与end,rbegin与rend都有一个返回值const_iterator的重载,

iterator 可读可写
const_iterator 可读不可写

⚡️ 2.4 范围for遍历

遍历方式3: 范围for

	// 底层角度,他就是迭代器
	string s1("hello world");
	for (auto& e : s1)
	{
		e++;
		cout << e << " ";
	}

注意:范围for从底层角度,从编译器运行角度就是迭代器。
在这里插入图片描述
可以从反汇编角度看到调用了begin和end。

🚀3.string类对象的增与删

string类对象的增与删对应的函数有非常多,但只有几个常用,

⚡️3.1 增

⚡️3.1.1 push_back

在这里插入图片描述

push_back用于追加一个字符->尾插

int main()
{
	string s1("hello world");
	s1.push_back('!');
}
⚡️3.1.2 append

在这里插入图片描述

append多用于追加C语言的字符串红框是用的最多的

string& append (const char* s);//追加C语言的字符串
int main()
{
	
	string s1("hello world");
	s1.append("!!!!!");
}
⚡️3.1.3 operator+=(用得最多)

在这里插入图片描述

+=符号重载可以追加 字符/c语言字符串/string类对象

int main()
{
	string s1("hello world");
	string s2("??");
	s1 += '!';//追加字符
	s1 += "!!";//追加c语言字符串
	s1 += s2;//string类对象
}
⚡️3.1.4 insert

在这里插入图片描述
insert可以在pos位置后插入一个字符/c语言字符串/string类对象慎用,效率不高->O(n)

常用的:
string& insert (size_t pos, const string& str);//插入string类对象
string& insert (size_t pos, const char* s);//插入c语言字符串
string& insert (size_t pos, size_t n, char c);//插入c字符
	//头插字符串
	string s2("hello world");
	s2.insert(0, "xxxx");
	cout << s2 << endl;

	//头插字符
	char ch = 'y';
	s2.insert(0, 1, ch);
	cout << s2 << endl;

	//用迭代器头插字符
	s2.insert(s2.begin(), 'y');
	cout << s2 << endl;

	//用迭代器头插string类对象
	s2.insert(s2.begin(), s1.begin(), s1.end());
	cout << s2 << endl;
⚡️3.1.5 replace

在这里插入图片描述

replace替换pos位置的字符为 c语言字符串/string类对象,与insert不同的是一个是插入一个是替换。并且效率不高,慎用,和insert类似,要挪动数据

常用的:
//替换为string类对象
string& replace (size_t pos,  size_t len,  const string& str);
//替换为c语言字符串
string& replace (size_t pos,  size_t len,  const char* s);

⚡️3.2 删

⚡️3.2.1 pop_back

在这里插入图片描述
pop_back用于删除最后一个字符->尾删

int main()
{
	string s1("hello world");
	s1.pop_back();
}
⚡️3.2.2 erase

在这里插入图片描述
erase对范围的内容进行删除,慎用,因为效率不高,常用的有:

常用的:
string& erase (size_t pos = 0, size_t len = npos);
iterator erase (iterator first, iterator last);
int main()
{
	//string& erase (size_t pos = 0, size_t len = npos);
	string s1("hello world");
	//1.删除从下标0开始往后的6个字符
	s1.erase(0, 6);
	//2.可以传入迭代器
	auto begin = s1.begin();auto end = s1.end();
	s1.erase(begin, end);
	//不传第二个参数直接,删完
	s1.erase(0);
}
  • 26
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值