标准库中的string类(上)——“C++”

2023-12-20 21:43:59

各位CSDN的uu们好呀,好久没有更新小雅兰的C++专栏的知识啦,接下来一段时间,小雅兰就又会开始更新C++这方面的知识点啦,以及期末复习的一些知识点,下面,让我们进入西嘎嘎string的世界吧!!!


首先,在学习西嘎嘎的过程中,我们需要学会去看文档!!!

西嘎嘎官方文档cppreference.com

由于这个文档比较乱,所以一般用这个:cplusplus.com - The C++ Resources Network


string类的常用接口说明


string类的常用接口说明

string类对象的常见构造

https://cplusplus.com/reference/string/string/string/?

函数名称功能说明
string() (重点)构造空的string类对象,即空字符串
string(const char* s) (重点) 用C-string来构造string类对象
string(const string&s) (重点) 拷贝构造函数
string(size_t n, char c) string类对象中包含n个字符c
int main()
{
	string s1;//构造空的string类对象s1
	string s2("hello world");//用C格式字符串构造string类对象s2
	string s3 = s2;//拷贝构造s3
	string s4(s2);//拷贝构造s4
}

?如果是想要把这些内容打印出来的话,就直接cout就可以了,因为库函数中已经重载了opeator<<!!!

#include<iostream>
#include<string>
using namespace std;
int main()
{
	string s1;//构造空的string类对象s1
	string s2("hello world");//用C格式字符串构造string类对象s2
	string s3 = s2;//拷贝构造s3
	string s4(s2);//拷贝构造s4
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	return 0;
}

这些就是最常见的,其余的只需要了解一下就可以了,需要的时候直接查文档!?

?string (const string& str, size_t pos, size_t len = npos);

substring constructor
Copies the portion of str that begins at the character position pos and spans len characters (or until the end of str, if either str is too short or if len is string::npos).?

str:Another?string?object, whose value is either copied or acquired.

pos:Position of the first character in str that is copied to the object as a substring.
If this is greater than str's length, it throws out_of_range.
Note: The first character in str is denoted by a value of 0 (not 1).

len:Length of the substring to be copied (if the string is shorter, as many characters as possible are copied).
A value of string::npos indicates all characters until the end of str.

n:Number of characters to copy.

int main()
{
	string s1;//构造空的string类对象s1
	string s2("hello world");//用C格式字符串构造string类对象s2
	string s3 = s2;//拷贝构造s3
	string s4(s2);//拷贝构造s4
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	string s5(s2, 0, 5);
	cout << s5 << endl;
	return 0;
}

?

?

static const size_t npos = -1//整型的最大值
int main()
{
	string s1;//构造空的string类对象s1
	string s2("hello world");//用C格式字符串构造string类对象s2
	string s3 = s2;//拷贝构造s3
	string s4(s2);//拷贝构造s4
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	string s5(s2, 0, 5);
	cout << s5 << endl;
	//下面这两种写法都是从字符串1的位置,取到结束
	string s6(s2, 1);
	string s7(s2, 1, 100);
	cout << s6 << endl;
	cout << s7 << endl;
	return 0;
}

?

string (const char* s, size_t n);

from buffer

Copies the first?n?characters from the array of characters pointed by?s.

意思是从这个第n个字符开始拷贝,拷贝到目标字符串中!

int main()
{
?? ?string s1;//构造空的string类对象s1
?? ?string s2("hello world");//用C格式字符串构造string类对象s2
?? ?string s3 = s2;//拷贝构造s3
?? ?string s4(s2);//拷贝构造s4
?? ?cout << s1 << endl;
?? ?cout << s2 << endl;
?? ?cout << s3 << endl;
?? ?cout << s4 << endl;
?? ?string s5(s2, 0, 5);
?? ?cout << s5 << endl;
?? ?//下面这两种写法都是从字符串1的位置,取到结束
?? ?string s6(s2, 1);
?? ?string s7(s2, 1, 100);
?? ?cout << s6 << endl;
?? ?cout << s7 << endl;
?? ?string s8(s2, 5);
?? ?cout << s8 << endl;
?? ?return 0;
}?

?可是,最后的打印结果为什么会是这样的呢?怎么会是打印 world呢?难道不应该是打印hello吗?

原来是用错了!它自动匹配到了上一个函数:string (const string& str, size_t pos, size_t len = npos);?

所以:string s8(s2, 5); 这句代码的意思是:从s2的第五个字符开始拷贝,一直拷贝到最后,直到后面再也没有内容!

应该这么写:

int main()
{
	string s1;//构造空的string类对象s1
	string s2("hello world");//用C格式字符串构造string类对象s2
	string s3 = s2;//拷贝构造s3
	string s4(s2);//拷贝构造s4
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	string s5(s2, 0, 5);
	cout << s5 << endl;
	//下面这两种写法都是从字符串1的位置,取到结束
	string s6(s2, 1);
	string s7(s2, 1, 100);
	cout << s6 << endl;
	cout << s7 << endl;
	string s8(s2, 5);
	cout << s8 << endl;
	string s9("hello world", 5);
	cout << s9 << endl;
	return 0;
}


?

string (size_t n, char c);

?fill constructor

Fills the string with?n?consecutive(连续的) copies of character?c.

int main()
{
	string s1;//构造空的string类对象s1
	string s2("hello world");//用C格式字符串构造string类对象s2
	string s3 = s2;//拷贝构造s3
	string s4(s2);//拷贝构造s4
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	string s5(s2, 0, 5);
	cout << s5 << endl;
	//下面这两种写法都是从字符串1的位置,取到结束
	string s6(s2, 1);
	string s7(s2, 1, 100);
	cout << s6 << endl;
	cout << s7 << endl;
	string s8(s2, 5);
	cout << s8 << endl;
	string s9("hello world", 5);
	cout << s9 << endl;
	string s10(10, 'l');
	cout << s10 << endl;
	return 0;
}

?

?string的析构函数:

赋值运算符重载:

int main()
{
	string s1;//构造空的string类对象s1
	string s2("hello world");//用C格式字符串构造string类对象s2
	string s3 = s2;//拷贝构造s3
	string s4(s2);//拷贝构造s4
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	string s5(s2, 0, 5);
	cout << s5 << endl;
	//下面这两种写法都是从字符串1的位置,取到结束
	string s6(s2, 1);
	string s7(s2, 1, 100);
	cout << s6 << endl;
	cout << s7 << endl;
	string s8(s2, 5);
	cout << s8 << endl;
	string s9("hello world", 5);
	cout << s9 << endl;
	string s10(10, 'l');
	cout << s10 << endl;
	cout<<endl;
	s1 = s2;
	cout << s1 << endl;
	s1 = "world";
	cout << s1 << endl;
	s1 = 'l';
	cout << s1 << endl;
	return 0;
}

?

这个赋值支持得很宽泛!因为写了很多重载版本!但是平时用的比较多的是第一种!!!


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

函数名称功能说明
operator[] (重 点)返回pos位置的字符,const string类对象调用
begin+endbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭 代器
rbegin+endbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭 代器
范围forC++11支持更简洁的范围for的新遍历方式

?

?

int main()
{
	string s1("hello world");
	cout << s1.size() << endl;
	cout << s1.length() << endl;
	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";
	}
	cout << endl;
}

int main()
{
?? ?string s1("hello world");
?? ?cout << s1.size() << endl;
?? ?cout << s1.length() << endl;
?? ?for (size_t i = 0; i < s1.size(); i++)
?? ?{
?? ??? ?//cout << s1[i] << " ";
?? ??? ?cout << s1.operator[](i);————底层原理
?? ?}
?? ?cout << endl;
}?

?

[]既可以读,又可以写!!!

int main()
{
	string s1("hello world");
	cout << s1.size() << endl;
	cout << s1.length() << endl;
	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";
		//cout << s1.operator[](i);
	}
	cout << endl;
	s1[0] = 'z';
	cout << s1 << endl;
}

?

?那如果我现在想要把string逆置一下,那就简单了!

int main()
{
	string s1("hello world");
	cout << s1.size() << endl;
	cout << s1.length() << endl;
	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";
		//cout << s1.operator[](i);
	}
	cout << endl;
	s1[0] = 'z';
	cout << s1 << endl;

	//把string逆置一下
	int begin = 0;
	int end = s1.size() - 1;
	while (begin < end)
	{
		char tmp = s1[begin];
		s1[begin] = s1[end];
		s1[end] = tmp;
		begin++;
		end--;
	}
	cout << s1 << endl;
	return 0;
}

?这只是其中一种写法,可是,在西嘎嘎中,写这个交换,其实是没有意义的,因为:库函数中给我们提供了这个接口!!!

?

int main()
{
?? ?string s1("hello world");
?? ?cout << s1.size() << endl;
?? ?cout << s1.length() << endl;
?? ?for (size_t i = 0; i < s1.size(); i++)
?? ?{
?? ??? ?cout << s1[i] << " ";
?? ??? ?//cout << s1.operator[](i);
?? ?}
?? ?cout << endl;
?? ?s1[0] = 'z';
?? ?cout << s1 << endl;

?? ?//把string逆置一下
?? ?int begin = 0;
?? ?int end = s1.size() - 1;
?? ?while (begin < end)
?? ?{
?? ??? ?/*char tmp = s1[begin];
?? ??? ?s1[begin] = s1[end];
?? ??? ?s1[end] = tmp;*/
?? ??? ?swap(s1[begin], s1[end]);
?? ??? ?begin++;
?? ??? ?end--;
?? ?}
?? ?cout << s1 << endl;
?? ?return 0;
}

?

?

?第二种遍历方式:iterator(迭代器)

string::iterator it = s1.begin();
while (it != s1.end())
{
	cout << *it << " ";
	++it;
}
cout << endl;

也可以修改!

string::iterator it = s1.begin();
while (it != s1.end())
{
	*it += 1;
	cout << *it << " ";
	++it;
}
cout << endl;

?

iterator的用法有点像指针!!!但是只是像指针,而不是就是指针!

vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
vector<int>::iterator vit = v.begin();
while (vit != v.end())
{
	cout << *vit << " ";
	++vit;
}
cout << endl;
list<double> lt;
lt.push_back(1.1);
lt.push_back(2.1);
lt.push_back(3.1);
lt.push_back(4.1);
list<double>::iterator lit = lt.begin();
while (lit != lt.end())
{
	cout << *lit << " ";
	++lit;
}
cout << endl;

?


之前,我们手撕了一个string的逆置,但其实,西嘎嘎的库函数里面就有这个函数!

?

string::iterator it = s1.begin();
while (it != s1.end())
{
?? ?*it += 1;
?? ?cout << *it << " ";
?? ?++it;
}
cout << endl;
reverse(s1.begin(), s1.end());
cout << s1 << endl;

vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
vector<int>::iterator vit = v.begin();
while (vit != v.end())
{
?? ?cout << *vit << " ";
?? ?++vit;
}
cout << endl;
reverse(v.begin(), v.end());
vit = v.begin();
while (vit != v.end())
{
?? ?cout << *vit << " ";
?? ?++vit;
}
cout << endl;


list<double> lt;
lt.push_back(1.1);
lt.push_back(2.1);
lt.push_back(3.1);
lt.push_back(4.1);
list<double>::iterator lit = lt.begin();
while (lit != lt.end())
{
?? ?cout << *lit << " ";
?? ?++lit;
}
cout << endl;
reverse(lt.begin(), lt.end());
lit = lt.begin();
while (lit != lt.end())
{
?? ?cout << *lit << " ";
?? ?++lit;
}
cout << endl;

?

?string、vector、list都逆置过来了!!!

?之前的那个operator[],提供了两个版本:

     char& operator[] (size_t pos);
const char& operator[] (size_t pos) const;

?

第一个可以编译通过,第二个不能编译通过!

?编译器会去找更匹配的!

?

?

int main()
{
	string s1("hello world");
	const string s2("hello world");
	s1[0] = 'x';
	//s2[0] = 'x';
	cout << s2[0] << endl;

	string::const_iterator it = s2.begin();
	while (it != s2.end())
	{
		//*it += 1;
		cout << *it << " ";
		++it;
	}
	cout << endl;
	return 0;
}

?

?for (auto e : s1)
{
?? ?cout << e << " ";
}
cout << endl;

但是实际上,迭代器才是yyds!?


所以,现在我们遍历,就有三种方法:

  • 下标+[]
  • 迭代器
  • 范围for

但是,主流还是迭代器!!!

?

?

void func(const string& s)
{
	string::const_reverse_iterator it = s.rbegin();
	while (it != s.rend())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}
int main()
{
	string s1("hello world");
	string::reverse_iterator it1 = s1.rbegin();
	while (it1 != s1.rend())
	{
		cout << *it1 << " ";
		++it1;
	}
	cout << endl;
	func(s1);
	return 0;
}


?


好啦,小雅兰今天的西嘎嘎string的使用部分就到这里啦,下一篇博客继续string的使用,后续还会写string模拟实现,加油!!!

文章来源:https://blog.csdn.net/weixin_74957752/article/details/135110694
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。