【C++进阶之路】手把手教你使用string类的接口

前言

在C语言中是没有字符串类型的,但是我们会经常对字符串进行操作,因此到了C++就提出了string类,用于对字符串进行操作,下面我们来了解一下。

基本认识

  • 字符串是表示字符序列
  • 因为string类实现的比STL早,所以不在容器里。
  • string类的使用跟容器,都基本是通过调用接口实现的。
  • string类是basic_string模板的实例化,操作的数据类型为char

string在底层实际是:basic_string模板类的别名——
typedef basic_string<char, char_traits, allocator>string;

  • string类只能操作单个字符,不能对多个字符一块操作。

基本使用

库里面的类——那就要包含头文件

#include<string>

要使用库里的类:

  1. 展开命名空间
using namespace::std;
  1. 或者指定作用域
std::string A;

一.构造函数

默认构造函数

函数:

string()

功能:初始化为空字符串,后面跟上一定长度的0或者说为\0

例:

#include<iostream>
#include<string>
using namespace::std;
int main()
{
    
    
	string A;
	return 0;
}

打开监视窗口,看初始化后的结果:
在这里插入图片描述

  • 给我们显示的只是一个空字符串。
  • 那实际上呢?
    在这里插入图片描述
  • 其实是一个数组,空间是16个字节,前4个元素初始化为0——\0

拷贝构造函数

函数:

string(const string&s)
//这里的const将权限缩到最小,所以既可以传string又可以传const string

功能:拷贝构造。
举例:

#include<iostream>
#include<string>
using namespace::std;
int main()
{
    
    
	string A;
	string B(A);
	string C = A;
	//这里也是拷贝构造,因为是用一个已经初始化的对象初始化另一个正在初始化的对象。
	return 0;
}

其它构造函数

①string(const char* s)

函数:

string(const char* s) 

功能:用一个字符串初始化一个string类。

例:

#include<iostream>
#include<string>
using namespace::std;
int main()
{
    
    
	string B("hello world");
	return 0;
}

②string(size_t n, char c)

函数:

string(size_t n, char c)

功能:将string类初始化为n个c字符。

例:

#include<iostream>
#include<string>
using namespace::std;
int main()
{
    
    
	string B(6,'x');
	cout << B << endl;
	return 0;
}

执行结果:
在这里插入图片描述

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

函数:

string (const string& str, size_t pos, size_t len = npos)
static const size_t npos = -1;//-1就等于FFFFFFFF

功能:将一个string类的内容从第pos个位置开始,到npos长度的字符拷贝到另一个string类中。

例:

#include<iostream>
#include<string>
using namespace::std;
int main()
{
    
    
	string B("hello world");
	string A(B, 0, 5);
	//这里的0按照数组的下标进行计算的。
	//5是包括从0位置开始的5个元素。
	cout << A << endl;
	return 0;
}

二.容量接口

①size与length

  • 说明:size与length都是求string类的有效字符。

有效字符就是求除了\0的字符。

举例:

#include<iostream>
#include<string>
using namespace::std;
int main()
{
    
    
	string A("hello");
	cout << A.size() << endl;
	cout << A.length() << endl;
	return 0;
}

补充:size的设计是为了迎合容器,因为只有字符串才叫长度,其它的都叫size。

②max_size

函数:

size_t max_size() const;

功能:字符串能够达到的最大长度。
例:

#include <iostream>
#include <string>
int main()
{
    
    
	string A;
	cout<<A.max_size()<<endl;
	return 0;
}

在这里插入图片描述

③capacity

  • 功能:求字符类当前有效字符的最大容量。

举例:

#include<iostream>
#include<string>
using namespace::std;
int main()
{
    
    
	string A("hello");
	cout << A.capacity() << endl;
	return 0;
}

执行结果:
在这里插入图片描述
在这里插入图片描述

  • 可我们明明开了16个字节,但是这里却说开辟了15个字节,为什么呢?

  • 因为:我们并没有算\0以及之后的空间,只算了能够存储有效字符的空间

那如果我们这样写呢?

#include<iostream>
#include<string>
using namespace::std;
int main()
{
    
    
	string A("hel\0lo\0");
	cout << A.capacity() << endl;
	return 0;
}

结果:
在这里插入图片描述

识别出来的字符串是这样的:
在这里插入图片描述

  • 因此:string类只识别到第一个\0为止,之后的不做考虑。

那如果我们存20个字节,那么string类会对我们的空间进行扩容吗?

例:

#include<iostream>
#include<string>
using namespace::std;
int main()
{
    
    
	string A("hello");
	int prev_capacity = A.capacity();
	cout << prev_capacity << endl;
	for (int i = 0; i < 4; i++)
	{
    
    
 		while (A.size() != prev_capacity)
		{
    
    
			A += 'x';
		}
		A += 'x';
		cout << A.capacity() << endl;
		prev_capacity = A.capacity();
	}
	return 0;
}

执行结果:
在这里插入图片描述
我们可以看出——这里是会扩容的,而且第一次扩容是2倍扩容(算上\0),之后的扩容接近1.5倍扩容。(VS2019)
我们再换到Linux平台上进行测试:
在这里插入图片描述

  • 不难看出,这里的扩容是以两倍进行扩容的

④empty

函数:

bool empty() const;
//说明:加了const,所以使用empty是不会对string类进行修改的。

功能:检测string是否为空,为空返回真,其余情况返回假。

例:

#include<iostream>
#include<string>
using namespace::std;
int main()
{
    
    
	string A("\0");
	if (A.empty())
	{
    
    
		printf("YES\n");
	}
	else
	{
    
    
		printf("NO\n");
	}
	return 0;
}

结果:
在这里插入图片描述

⑤clear

函数:

void clear();

功能:减少string中的字符,使之成为空字符串,也就是字符串的长度为0。

例:

#include<iostream>
#include<string>
using namespace::std;
int main()
{
    
    
	string A("hello world");
	A.clear();
	if (A.empty())
	{
    
    
		printf("YES\n");
	}
	else
	{
    
    
		printf("NO\n");
	}
	return 0;
}

结果:
在这里插入图片描述

⑥reserve

函数:

void reserve (size_t n = 0);

功能:为字符串预留n空间,当n大于capacity时进行扩容,其余情况按照原先的capacity。
结果:使string的capacity大于等于n。

  • 当n小于capacity时,这是一个不具约束力的请求,因此容器的执行操作是依据实际编译器进行的优化并且留下一个capacity大于等于n的结果。
  • 一般来说,编译器觉得字符串的空间远小于capacity时可能会进行缩容。
#include <iostream>
#include <string>
int main()
{
    
    
	string A("hello world");
	A.reserve(20);
	cout <<A<< endl;
	return 0;
}

执行前:capacity——15
在这里插入图片描述
执行后:capacity——31
在这里插入图片描述

⑦resize

函数:

void resize (size_t n);
void resize (size_t n, char c);
//这两个是函数重载

功能:

  • 当n小于size时,会将多于n的字符全部删除,对于少的则不做处理。
  • 当n大于size时,如果没有第二个参数,会将大于size的部分填充为\0,如果有第二个参数,则会将大于size的部分填充为第二个参数的值。

例1:小于size

#include <iostream>
#include <string>
int main()
{
    
    
	string A("hello world");
	A.resize(1,'x');//这里的x其实没啥用
	cout << A << endl;
	return 0;
}

结果:
在这里插入图片描述
例2:大于size

#include <iostream>
#include <string>
int main()
{
    
    
	string A("hello world");
	A.resize(20,'x');
	cout << A << endl;
	return 0;
}

结果:
在这里插入图片描述

三.修改接口

①+=

函数:

string& operator+= (const string& str);
string& operator+= (const char* s);
string& operator+= (char c);

功能:+=一个字符串/字符/string类

例:

#include <iostream>
#include <string>

int main()
{
    
    
	string A;
	A += "hello";
	A += ' ';
	string B("world");
	A += B;
	cout << A << endl;
	return 0;
}

运行结果:
在这里插入图片描述

②[]

函数:

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

功能:访问字符串下标位置的字符。
例:

#include <iostream>
#include <string>
int main()
{
    
    
	string A("hello");
	char a = A[0];
	cout << a << endl;
	return 0;
}

结果:
在这里插入图片描述

说明:[ ]越界会进行报错(assert)而at越界则会进行抛异常。

③push_back

函数

void push_back (char c);

功能:再string末尾后追加一个字符
例:

#include <iostream>
#include <string>
int main()
{
    
    
	string A("hello");
	A.push_back('x');
	cout << A << endl;
	return 0;
}

结果:
在这里插入图片描述

④append

函数:

string& append (const string& str);

string& append (const string& str, size_t subpos, size_t sublen);

string& append (const char* s);
	
string& append (const char* s, size_t n);

string& append (size_t n, char c);

功能:在指定string后面追加 n个字符/(前n个字符的)字符串/string(从subpos位置到sublen位置)。

例:

#include <iostream>
#include <string>
int main()
{
    
    
	string A("hello world");
	string B(" hello");
	A.append(B,0,6);
	cout << A << endl;
	A.append(B);
	cout << A << endl;
	A.append(" hello", 0, 6);
	cout << A << endl;
	A.append(6, 'x');
	cout << A << endl;
	return 0;
}

结果:
在这里插入图片描述

⑤c_str

函数:

const char* c_str() const;

功能:返回一个字符串,类型是const char *。
例:

#include <iostream>
#include <string>
int main()
{
    
    
	string A("hello");
	const char* a = A.c_str();
	cout << a << endl;
	return 0;
}

结果:
在这里插入图片描述

⑥ find

函数:

size_t find (const string& str, size_t pos = 0) const;
	
size_t find (const char* s, size_t pos = 0) const;

size_t find (const char* s, size_t pos, size_t n) const;

size_t find (char c, size_t pos = 0) const;
//pos是要查找string的下标,n是要在指定字符串中查找的长度。
//size_t,如果成功返回一个匹配成功的下标,如果失败返回-1(转换为无符号整形)。

功能:在string类的指定pos下标位置开始,向后查找目标【string/字符串(指定查找前n个)/字符】——的字符c位置,并返回其位置。
注意:查找的是(字符串,string里面的)字符。
例:

#include <iostream>
#include <string>
int main()
{
    
    
	string A("hello world");
	string B("world");
	cout << A.find(B, 0)<<endl;
	cout << A.find("world", 0) <<endl;
	cout << A.find("world", 0, 5) <<endl;
	cout << A.find('w', 0) <<endl;
	return 0;
}

结果:
在这里插入图片描述

⑦rfind

函数:


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

size_t rfind (const char* s, size_t pos = npos) const;

size_t rfind (const char* s, size_t pos, size_t n) const;

size_t rfind (char c, size_t pos = npos) const;
原理:同find

功能:在string类的指定pos下标位置开始,向前查找目标【string/字符串(指定查找前n个)/字符】——的字符c位置,并返回其位置。

例:

#include <iostream>
#include <string>
int main()
{
    
    
	string A("hello world");
	string B("world");
	cout << A.rfind(B, 5)<<endl;
	cout << A.rfind("world", 10) <<endl;
	cout << A.rfind("world", 10, 5) <<endl;
	cout << A.rfind('w', 10) <<endl;
	return 0;
}

结果:
在这里插入图片描述

⑧find_first_of

函数


size_t find_first_of (const string& str, size_t pos = 0) const;
	
size_t find_first_of (const char* s, size_t pos = 0) const;

size_t find_first_of (const char* s, size_t pos, size_t n) const;

size_t find_first_of (char c, size_t pos = 0) const;

功能:在string类中的pos位置开始查找,与字符串的前n个位置相关的任何一个字符。
例:

#include<iostream>
#include<string>
using namespace std;
int main()
{
    
    
	string str("hello world");
	size_t pos = str.find_first_of("wo", 0, 1);
	//在hello world 中的下标的0位置开始找,找与“wo”的前1个字符相同的字符。
	//即在hello world 中找w。
	cout << pos << endl;
	return 0;
}

四.迭代器——iterator

基本概念

迭代器的作用是用来访问容器(用来保存元素的数据结构)中的元素,所以使用迭代器,我们就可以访问容器中里面的元素。

①begin与end

函数:

      reverse_iterator rbegin();
const_reverse_iterator rbegin() const;

功能:获取string的开头位置。

函数:

 iterator end();
 const_iterator end() const;

功能:获取string最后一个有效字符的位置的下一个位置通常为\0。

例:

#include <iostream>
#include <string>
int main()
{
    
    
	string A("hello world");
	string::iterator it = A.begin();
	//当A是const修饰的类时,我们就要用string::const_iterator迭代器
	while (it != A.end())
	{
    
    
		cout << *it << " " ;
		it++;
	}
	return 0;
}

结果:
在这里插入图片描述

②rbegin和rend

函数:

      reverse_iterator rbegin();
const_reverse_iterator rbegin() const;

功能:获取最后一个有效字符的位置的。
函数:

      reverse_iterator rend();
const_reverse_iterator rend() const;

功能:获取第一个字符的位置的前一个位置。

例:

#include <iostream>
#include <string>
int main()
{
    
    
	string A("hello world");
	string::reverse_iterator it = A.rbegin();
	while (it != A.rend())
	{
    
    
		cout << *it << " " ;
		it++;
	}
	return 0;
}

说明:这里的rbegin + 1是倒着加1
结果:
在这里插入图片描述
其余内容请看文档

五、非成员函数

①getline

函数


istream& getline (istream& is, string& str, char delim);

istream& getline (istream& is, string& str);

功能
通过流,对字符串进行输入/输出,输入/输出遇到delim终止字符结束,如果不写,默认是\n。这就解决了我们输入遇到空格的问题。

对于scanf读取一行可以

scanf("%[^\n]",str);//意为读取到\n结束。

对于gets

gets(str);

②stoi——字符串转化系列

说明:这个系列就介绍这一个,其它的可自行了解。

函数:

int stoi (const string&  str, size_t* idx = 0, int base = 10);
int stoi (const wstring& str, size_t* idx = 0, int base = 10);

功能:
将string 的前idx个数字字符以base进制(默认为10进制)转换为整形。
例:


#include <iostream>   // std::cout
#include <string>     // std::string, std::stoi

int main()
{
    
    
	std::string str_dec = "2001, A Space Odyssey";
	std::string str_hex = "40c3";
	std::string str_bin = "-10010110001";
	std::string str_auto = "0x7f";

	std::string::size_type sz;   // alias of size_t

	int i_dec = std::stoi(str_dec, &sz);
	int i_hex = std::stoi(str_hex, nullptr, 16);
	//不使用第二个参数传入空指针即可。
	int i_bin = std::stoi(str_bin, nullptr, 2);
	int i_auto = std::stoi(str_auto, nullptr, 0);
	std::cout << str_dec << ": " << i_dec << "\n";
	std::cout << str_hex << ": " << i_hex << '\n';
	std::cout << str_bin << ": " << i_bin << '\n';
	std::cout << str_auto << ": " << i_auto << '\n';
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Shun_Hua/article/details/130859705
今日推荐