C++中的string类及常用接口说明

1.string类的介绍

Cplusplus中对于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)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作

总结如下:

  1. string是表示字符串的字符串类
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
  4. 不能操作多字节或者变长字符的序列。

string不是STL容器,string是basic_string类模板的一个实例,string是一个模板类。它使用char来实例basic_string, string集成的操作函数与STL容器中的操作函数大部分很相似, 因为sting本身也是用顺序表来实现的(与vector容器类似)。所以用C++标准程序库中的string来代替C中的char*(C++中还是可以用char*, 这是为了与C保持兼容),是因为它和C中的char*比较起来,不必担心内存是否足够、字符串长度等等,而且作为一个类出现,他集成的操作函数足以完成我们大多数情况下的需要。我们也可以把string看成是C++的基本数据类型。使用string类时,必须包含头文件(#include < string >)以及using namespace std;

2.string类的常用接口说明

2.1常见构造

函数名称功能说明
string()构造空的string类对象 ,即空的字符串
string(const char *s)用C-string来构造string类对象
string(size_t n,char c)string类对象中包含n个字符c
string(const string&s)拷贝构造函数
string(const string&s,size_t n)用s中的前n个字符构造新的string类对象
#include<iostream>
#include<string>
using namespace std;
int main()
{
	string s1;//空字符串
	cout << "s1=" << s1 << endl;
	string s2("Hello World");//用C-string构造string类对象
	cout << "s2=" << s2 << endl;
	string s3(10, 'a');//string类对象中包含10个字符a
	cout << "s3=" << s3 << endl;
	string s4(s2);//拷贝构造
	cout << "s4=" << s4 << endl;
	string s5(s2, 5);//用s2中的前5个字符构造s5
	cout << "s5=" << s5 << endl;
	system("pause");
	return 0;
}

在这里插入图片描述

2.2容量操作

函数名称功能说明
size_t size() const返回字符串的有效字符长度
size_t length() const返回字符串的有效字符长度
size_t capacity() const返回字符串空间总大小
bool empty() const检测字符串是否为空串 是返回true,否则返回false
void clean()清空有效字符串
void resize(size_t n,char c)将有效字符的个数改成n个,多出的空间用字符c填充
void resize(size_t n)将有效字符的个数改成n个,多出的空间用0填充
void reserve(size_t res_arg=0)为字符串预留空间
#include<iostream>
#include<string>
using namespace std;
int main()
{
		cout << "string类对象的容量操作" << endl;
		cout << endl;

		string s1("Hello World");
		cout << "s1="<<s1 << endl;
		cout << "s1的有效长度:" << s1.size() << endl;//有效长度
		cout << "s1的容量:" << s1.capacity() << endl;//容量
		s1.clear();//清空s1
		cout << "s1.clear() 清空s1" << endl;
		cout << "s1的有效长度:" << s1.size() << endl;//清空后的大小 容量
		cout << "s1的容量:" << s1.capacity() << endl;
		cout << endl;

		cout << "将s1中的有效字符个数增加到10,多出的位置用a补充" << endl;
		s1.resize(10, 'a');//将s1中的有效字符个数增加到10,多出的位置用a补充
		cout << s1 << endl;
		cout << "s1的有效长度:" << s1.size() << endl;
		cout << "s1的容量:" << s1.capacity() << endl;
		cout << endl;

		cout << "将s1中的有效字符个数增加到15,多处位置用0填充" << endl;
		s1.resize(15);//将s1中的有效字符个数增加到15,多处位置用0填充
		cout << s1 << endl;
		cout << "s1的有效长度:" << s1.size() << endl;
		cout << "s1的容量:" << s1.capacity() << endl;
		cout << endl;

		cout << "将s1中的有效字符数缩减到5" << endl;
		s1.resize(5);//将s1中的有效字符数缩减到5
		cout << s1 << endl;
		cout << "s1的有效长度:" << s1.size() << endl;
		cout << "s1的容量:" << s1.capacity() << endl;
		cout << endl;

		cout << "测试reserve是否会改变string中有效元素个数" << endl;
		s1.reserve(30);    
		cout << "s1的有效长度:" << s1.size() << endl;
		cout << "s1的容量:" << s1.capacity() << endl;
		cout << endl;
		cout<<"测试reserve参数小于string的底层空间大小时,是否会将空间缩小"<<endl;   
		s1.reserve(10);    
		cout << "s1的有效长度:" << s1.size() << endl;
		cout << "s1的容量:" << s1.capacity() << endl;
		system("pause");
		return 0;
}

在这里插入图片描述
其中s1.resize(15)将s1的有效字符增加到15,多处位置用’/0’填充,但不会打印出来aaaaaaaaaa00000,’/0’并不会打印出来,而其size变成了15。

注意:

  • 1.size()与length()方法底层实现原理完全相同,一般情况下基本都是用size()。
  • 2.clear()只是将string中有效字符(size)清空,不改变底层空间(capacity)大小。
  • 3.resize()在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
  • 4.reserve();为string预留空间,不改变有效元素个数,当reserve()的参数小于string的底层空间时,reserve不会改变容量大小。

2.3访问操作

函数名称功能说明
char &operate[ ](size_t pos)返回pos位置的字符,const string类对象调用
const char& operate[ ](size_t pos)const返回pos位置的字符,非const string类对象调用
#include<iostream>
#include<string>
using namespace std;
int main()
{
		cout << "string类对象的访问操作" << endl;
		string s1("Hello World");
		const string s2("Nothing is possible!");
		cout << "s1:" << s1 << endl;
		for (size_t i = 0; i < s1.size(); ++i) {
			cout << s1[i] << " ";
		}
		cout << endl;
		cout << "s2:" <<s2<< endl;
		for (size_t j = 0; j < s2.size(); ++j) {
			cout << s2[j] << " ";
		}
		cout << endl;
		s1[0] = 'h';
		cout << "s1:" << s1 << endl;
		//s2[0] = 'n';代码编译失败,因为const类型对象不能修改
		return 0;
}

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

2.4修改操作

函数名称功能说明
void push_back(char c)在字符串后尾插字符c(尾插)
string& append (const char* s)在字符串后追加一个字符串
string& operator+=(const string& str)在字符串后追加字符串str
string& operator+=(const char* s)在字符串后追加C个数字符串
string& operator+=(char c)在字符串后追加字符c
const char* c_str( )const返回C格式字符串
size_t find (char c, size_t pos = 0)const从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
size_t rfind(char c, size_t pos = npos)从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
string substr(size_t pos = 0, size_t n = npos)const在str中从pos位置开始,截取n个字符,然后将其返回
#include<iostream>
#include<string>
using namespace std;
int main()
{
	string s;
	s.push_back('H');
	cout << "s1后尾插字符H:" << s << endl;
	s.append("ello");
	cout << "s1后追加字符串ello:" << s << endl;
	s += 'W';
	cout << "s1后追加字符W:" << s << endl;
	s += "orld";
	cout << "s1后追加字符串orld:" << s << endl;
	cout << "返回C格式字符串:" << s.c_str() << endl;
	string str("abcdefg");
	cout << "str:" << str << endl;
	size_t pos = 0;
	size_t pos1 = str.find('d', pos);//在str中从pos开始向后找字符d,并返回d在字符串中的位置
	cout << "字符d在字符串str中下标为" << pos1 << "的位置" << endl;
	size_t pos2 = str.size();
	size_t pos3 = str.rfind('e', pos2);
	cout << "字符e在字符串str中下标为" << pos3 << "的位置" << endl;//在str中从pos开始向前找字符e,并返回e在字符串中的位置
	string str2 = (str.substr(pos3, 3));//在str中从pos3位置开始,截取3个字符,然后将其返回
	cout << "在str中从pos3位置开始,截取3个字符:"<<str2 << endl;
	system("pause");
	return 0;
}

在这里插入图片描述

1.在string尾部追加字符时,s.push_back(‘c’) , s.append(1, ‘c’) , s += 'c’三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
2.对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。

2.5string类非成员函数

函数名称重载的函数功能说明
operator+string operator+ (const string& lhs, const string& rhs);   
string operator+ (const string& lhs, const char* rhs);
string operator+ (const char* lhs, const string& rhs);
string operator+ (const string& lhs, char rhs);
string operator+ (char lhs, const string& rhs);
返回字符(串)+字符(串)此函数效率较低
operator>>istream& operator>> (istream& is, string& str);输入运算符重载, 输入字符串
operator<<ostream& operator<< (ostream& os, const string& str);输出运算符重载, 打印字符串
getlineistream& getline (istream& is, string& str, char delim);
istream& getline (istream& is, string& str);
获取一行字符串, char delim, 是结束符标识
relational operatorsbool operator== (const string& lhs, const string& rhs);
bool operator== (const char* lhs, const string& rhs);
bool operator== (const string& lhs, const char* rhs);

bool operator!= (const string& lhs, const string& rhs);
bool operator!= (const char* lhs, const string& rhs);
bool operator!= (const string& lhs, const char* rhs);

bool operator< (const string& lhs, const string& rhs);
bool operator< (const char* lhs, const string& rhs);
bool operator< (const string& lhs, const char* rhs);

bool operator<= (const string& lhs, const string& rhs);
bool operator<= (const char* lhs, const string& rhs);
bool operator<= (const string& lhs, const char* rhs);

bool operator> (const string& lhs, const string& rhs);
bool operator> (const char* lhs, const string& rhs);
bool operator> (const string& lhs, const char* rhs);

bool operator>= (const string& lhs, const string& rhs);
bool operator>= (const char* lhs, const string& rhs);
bool operator>= (const string& lhs, const char* rhs);
比较两个字符串
string和char比较
char
和string比较
string和string比较

3.实现string类及其常用接口

String.h

#pragma once
#include<iostream>
#include<cstring>
#include<string>
class String {
public:
	typedef char* Iterator;
	String();//构造空的string类对象 ,即空的字符串
	String(const char* s);//用C-string来构造string类对象
	String(size_t n, char c);//string类对象中包含n个字符c
	String(const String& s);//拷贝构造函数
	String(const String& s, size_t n);//用s中的前n个字符构造新的string类对象

	String& operator=(const String& s);//s1=s2;
	String& operator=(const char* s);

	~String();
	size_t Size()const; //返回字符串的有效字符长度
	size_t Length()const;//返回字符串的有效字符长度
	size_t Capacity()const;//返回字符串空间总大小
	bool Empty()const;//检测字符串是否为空串 是返回true,否则返回false
	void Clean();//清空有效字符串
	void Resize(size_t n, char c);//将有效字符的个数改成n个,多出的空间用字符c填充
	void Resize(size_t);//将有效字符的个数改成n个,多出的空间用0填充
	void Reserve(size_t newcapacity);//为字符串预留空间

	char& operator[](size_t pos)const;//返回pos位置的字符,非const string类对象调用
	char& operator[](size_t pos);//返回pos位置的字符,const string类对象调用

	void Push_back(char c);
	void Pop_back(char c);
	String& Append(const char* s);
	String& Append(size_t,const char c);
	String& Append(const String& s);

	//返回C格式字符串
	const char* c_str()const;

	// 返回字符c/字符串s在string中第一次出现的位置
	size_t Find(const char c, size_t pos)const;
	size_t Find(const char* s, size_t pos)const;
	size_t Find(const String& s, size_t pos)const;

	size_t Rfind(const char c, size_t pos)const;
	size_t Rfind(const char* s, size_t pos)const;
	size_t Rfind(const String& s, size_t pos)const;

	// 截取string从pos位置开始的n个字符
	String Substr(size_t pos, size_t n);
	
	// 在pos位置上插入字符c/字符串str,并返回该字符的位置
	String& operator+=(const char c);
	String& operator+=(const String& s);
	String& operator+=(const char* s);


private:
	char* _str;
	size_t _size;
	size_t _capacity;
};

String.cpp

#include"teststring.h"
#include<iostream>
#include<string>
#include<cstring>
#include<cassert>
//构造空的string类对象 ,即空的字符串
String::String()
	:_size(0)
	,_capacity(15)
	,_str(new char[_capacity]){

}

//用C-string来构造string类对象
String::String(const char* s)
	:_size(0)
	,_capacity(15)
	,_str(new char[_capacity]){
	if (s == nullptr) {
		assert(false);
	}
	size_t _size = strlen(s);
	_capacity = _size;
	strcpy(_str, s);
}

//string类对象中包含n个字符c
String::String(size_t n, char c)
	:_size(0)
	,_capacity(15)
	,_str(new char[_capacity]) {
	_size = n;
	_capacity = _size;
	memset(_str, c, n);
}

//拷贝构造函数
String::String(const String& s)
	:_size(0)
	, _capacity(15)
	, _str(new char[_capacity]) {
	if (this == &s) {
		return;
	}
	_size = s._size;
	_capacity = s._capacity;
	strncpy(_str, s._str, s._size);
}

//用s中的前n个字符构造新的string类对象
String::String(const String& s, size_t n)
	:_size(0)
	, _capacity(15)
	, _str(new char[_capacity]) {
	_size = n;
	_capacity = _size;
	strncpy(_str, s._str, n);
}
String::~String() {
	if (_str) {
		delete[]_str;
	}
	_str = nullptr;
	_size = 0;
	_capacity = 0;
}

//s1=s2;
String& String::operator=(const String& s) {
	if (this == &s) {
		return;
	}
	char* pstr = new char[s._capacity];
	strcpy(pstr, s._str);
	delete[] _str;
	_size = s._size;
	_capacity = s._capacity;
	_str = pstr;
}

String& String::operator=(const char* s) {
	if (s == nullptr) {
		assert(false);
	}
	_size = strlen(s);
	_capacity = _size;
	strcpy(_str, s);
}

//返回字符串的有效字符长度
size_t String::Size()const {
	return _size;
}

//返回字符串的有效字符长度
size_t String::Length()const {
	return _size;
}

//返回字符串空间总大小
size_t String::Capacity()const {
	return _capacity;
}

//检测字符串是否为空串 是返回true,否则返回false
bool String::Empty()const {
	return 0 == _size;
}

//清空有效字符串
void String::Clean() {
	_size = 0;
	_str[_size] = '\0';
}

//将有效字符的个数改成n个,多出的空间用字符c填充
void String::Resize(size_t n, char c) {
	if (n > _size) {
		if (n > _capacity)
			Reserve(n);
		memset(_str + _size, c, n - _size);
		_size = n;
		_str[n] = '\0';
	}
}

//将有效字符的个数改成n个,多出的空间用0填充
void String::Resize(size_t n) {
	if (n > _size) {
		if (n > _capacity)
			Reserve(n);
		memset(_str + _size, '\0', n - _size);
		_size = n;
		_str[n] = '\0';
	}
}
//为字符串预留空间
void String::Reserve(size_t newcapacity) {
	if (newcapacity > _capacity) {
		char* str = new char[newcapacity];
		strcpy(str, _str);
		delete[] _str;
		_str = str;
		_capacity = newcapacity;
	}
}

//返回pos位置的字符,非const string类对象调用
char& String:: operator[](size_t pos)const {
	assert(pos < _size);
	return _str[pos];
}

//返回pos位置的字符,const string类对象调用
char& String:: operator[](size_t pos) {
	assert(pos < _size);
	return _str[pos];
}

void String::Push_back(char c) {//abcd _size=4
	if (_size == _capacity) {
		Reserve(_capacity * 2);
	}
	_str[_size] = 'c';
	_size++;
	_str[_size] = '\0';
}

//尾删
void String::Pop_back(char c) {
	if (_size)
		--_size;
}

String& String::Append(const char* s) {
	if (s == nullptr) {
		assert(false);
	}
	int size = _size + strlen(s);
	Reserve(size);
	strcat(_str, s);
	_size = size;
	return *this;
}

String& String::Append(size_t n, const char c) {
	while (n--) {
		Push_back(c);
	}
	return *this;
}

String& String::Append(const String& s) {
	int size = _size + s._size;
	Reserve(size);
	strcpy(_str, s._str);
	_size = size;
	return *this;
}

//返回C格式字符串
const char* String::c_str()const {
	return _str;	
}

// 返回字符c/字符串s在string中第一次出现的位置
size_t String::Find(const char c, size_t pos)const {
	if (pos < 0 || pos >= _size) {
		return -1;
	}
	char* ptr = strchr(_str + pos, c);
	if (ptr) {
		return ptr - _str;
	}
	else {
		return -1;
	}
}
size_t String::Find(const char* s, size_t pos)const {
	if (s == nullptr) {
		assert(false);
	}
	if (pos < 0 || pos >= _size) {
		return -1;
	}
	char* ptr = strstr(_str + pos, s);
	if (ptr) {
		return ptr - _str;
	}
	else {
		return -1;
	}
}
size_t String::Find(const String& s, size_t pos)const {
	if (pos < 0 || pos >= _size) {
		return -1;
	}
	char* ptr = strstr(_str + pos, s._str);
	if (ptr) {
		return ptr - _str;
	}
	else {
		return -1;
	}
}

size_t String::Rfind(const char c, size_t pos)const {
	char* ptr = nullptr;
	strncpy(ptr, _str, pos);
	char* m = nullptr;
	if (ptr) {
		m = strchr(ptr, c);
	}
	if (m) {
			return m - ptr;
	}
	else {
		return -1;
	}
}
size_t String::Rfind(const char* s, size_t pos)const {
	if (s == nullptr) {
		assert(false);
	}
	char* ptr = nullptr;
	strncpy(ptr, _str, pos);
	char* m = nullptr;
	if (ptr) {
		m = strstr(ptr, s);
	}
	if (m) {
		return m - ptr;
	}
	else{
		return -1;
	}
}
size_t String::Rfind(const String& s, size_t pos)const {
	char* ptr = new char[pos + 1];
	ptr[pos] = 0;
    strncpy(ptr, _str, pos);
	char* m = nullptr;
	if (ptr) {
		m = strstr(ptr, _str);
	}
	if (m) {
		return m - ptr;
		delete[] ptr;
	}
	else {
		return -1;
		delete[] ptr;
	}
}

// 截取string从pos位置开始的n个字符
String String::Substr(size_t pos, size_t n) {
	String str;
	if (pos > _size)
		return str;
	if (pos + n > _size)
		n = _size - pos;//不能超出_str;
	str.Reserve(n);
	str._size = n;
	strncpy(str._str,_str+pos,n);
	return str;
}

String& String::operator+=(const char c) {
	Push_back(c);
	return *this;
}

String& String::operator+=(const String& s) {
	int size = _size + s._size;
	Reserve(size);
	strncpy(_str + _size, s._str, s._size);
	_size = size;
	return *this;

}
String& String::operator+=(const char* s) {
	if (s == nullptr) {
		assert(false);
	}
	int size = strlen(s) + _size;
	Reserve(size);
	strcpy(_str + _size, s);
	_size = size;
	return *this;

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值