C++——string常用接口

目录

一. string类

二. string类的常用接口说明

1. string类对象的常见构造

2. string类对象的容量操作

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

4. string类对象的修改操作

5. string类非成员函数


一. string类

string类的文档介绍

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

总结:

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

使用string类时,必须包含#include头文件以及using namespace std;

二. string类的常用接口说明

1. string类对象的常见构造

(constructor)函数名称功能说明
string()构造空的string类对象,即空字符串
string(const char* s)用C-string来构造string类对象
string(size_t n, char c)string类对象中包含n个字符c
string(const string& s)拷贝构造函数
void Teststring() {
    //常见构造
    string s1;//构造空的string类对象
	string s2("hello");//用C格式字符串构造
	string s3(s2);//拷贝构造
	string s4 = s3;//拷贝构造
    //常用构造
	string s5("abcdefghijklmnopqrstuvwxyz");//用C格式字符串构造
    //string (const string& str, size_t pos, size_t len = npos);
	string s6(s5, 5, 10);//从s5中的下标为5处开始复制10个字符
    string (const string& str, size_t pos, size_t len = npos);
	string s7(s5, 5);//从s5中的下标为5处开始复制,复制长度为npos个,即直到全部复制到s7中
                     //最长复制一个整形的最大值长度
    
    //string (const char* s, size_t n);
	string s8("213241", 5);//从下标为0开始复制字符串里的5个字符到s8中
    //string (size_t n, char c);
	string s9(2, 'x');//用2个x初始化

	//string s10(s5, 30, 100);//越界抛出异常
    //string (const string& str, size_t pos, size_t len = npos);
	string s11(s5, 4, 200);//长度不够全部只能将全部字符串复制即截止
}

string类型会被其它字符串或字符覆盖

//string类型会被其他的字符串或者字符覆盖
void test3() {
	string s1("hello");
	string s2("xxx");
	s1 = s2;//用s2将s1覆盖
	s1 = "yyy";//用字符串将s1覆盖
	s1 = 'y';//用字符将s1覆盖

	cout << s1 << endl;
}

2. string类对象的容量操作

函数名称功能说明
size返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty检测字符串释放为空串,是返回true,否则返回false
clear清空有效字符
reserve为字符串预留空间
resize将有效字符的个数该成n个,多出的空间用字符c填充
// size/clear/resize
void Teststring1() {
    //注意:string类对象支持直接用cin和cout进行输入和输出
    
    string s("hello world!!!");
    cout << s.length() << endl;//返回字符串长度
	cout << s.size() << endl;//返回字符串长度,常用,因为适用性强
	cout << s.max_size() << endl;//可放入字符串最大的长度
	cout << s.capacity() << endl;//字符串的容量
    cout << s << endl;

    //将s中的字符串清空,注意情况时只是将size清0,不改变底层空间的大小
    s.clear();
    cout << s.size() << endl;
    cout << s.capacity() << endl;

    //无初始化扩容,将s1中有效字符个数增加到100个,多出位置用'x'进行填充
	string s1;
	s1.reserve(100);//扩容不初始化
	s1.resize(100, 'x');//扩容初始化
	cout << s1 << endl;

	//查看在vs下的扩容情况
	size_t sz = s.capacity();
	cout << "capacity:" << " " << sz << endl;
	for (size_t i = 0; i < 1000; ++i) {
		s.push_back('x');
		//不等于说明扩容了
		if (sz != s.capacity()) {
			sz = s.capacity();
			cout << "capacity:" << " " << sz << endl;
		}
	}

    //有初始化扩容
	string s2("hello");
	s2.reserve(100);//只扩容
	s2.resize(100, 'x');//扩容完后面补x
	cout << s2 << endl;

	//在vs下这两个函数不会缩容
	s2.reserve(10);//容量不变
	s2.resize(10);//将s2中有效字符个数缩小到10个size,容量不变,只在s2后打印五个x
	cout << s2 << endl;
}



void Teststring2() {
    string s;
    //测试reserve是否会改变string中有效元素个数
    s.reserve(100);
    cout << s.size() << endl;
    cout << s.capacity() << endl;
    
    //测试reverse参数小于string的底层空间大小时,是否会将空间缩小
    s.reverse(50);
    cout << s.size() << endl;
    cout << s.capacity() << endl;
}



//利用reserve提高插入数据的效率,避免增容带来的开销
void TestPushBack() {
    string s;
    size_t sz = s.capacity();
    cout << "making s grow:\n";
    for(int i = 0; i < 100; ++i) {
        s.push_back('c');
        if(sz != s.capacity()) {
            sz = s.capacity();
            cout << "capacity changed:" << sz << '\n';
        }
    }
}

注意: 

  1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般清空下基本都是用size()。
  2. clear()只是将string中有效字符清空,不改变底层空间大小。
  3. resize(size_t n)与resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
  4. reserve(size_t res_arg = 0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reverser不会改变容量大小。

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

函数名称功能说明
operator[]返回pos位置的字符,const string类对象调用
begin+endbegin获取一个字符的迭代器+end获取最后一个字符下一个位置的迭代器
rbegin+rendbegin获取一个字符的迭代器—+end获取最后一个字符下一个位置的迭代器
范围forc++支持更简洁的范围for的新遍历方式
//字符串的遍历
void test4() {
	
	//第一种方式,下标+[]
	string s1("hello world!");
	//size是字符串容量函数,获取字符串的长度,不包含\0
	for (size_t i = 0; i < s1.size(); ++i) {
		//这里的[]是被string重载过的,注意越界会抛出异常
		//s1.operator[].(i);
		cout << s1[i] << " ";
	}
	cout << endl;

	//第二种方式,迭代器 -------像指针一样的东西或者就是指针
	//为了方便访问像树或者链表的数据结构,还可以访问顺序表类似的数据结构
	string s2("hello");
	string::iterator it = s2.begin();//begin获取第一个字符的迭代器
	//end获取最后一个字符即(\0处)下一个位置的迭代器,begin和end的区间范围是左闭右开
	while (it != s2.end()) {
		cout << *it << " ";
		++it;
	}
	cout << endl;

	//第三种方式,范围for ------原理:编译器替换成迭代器,反汇编查看可知
	string s3("world!");
	for (auto ch : s3) {
		cout << ch << " ";
	}
	cout << endl;
}

//使用迭代器遍历vector
void test5() {
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	vector<int>::iterator vit = v.begin();
	while (vit != v.end()) {
		cout << *vit << " ";
		++vit;
	}
	cout << endl;
}

(1)operator[]重载问题和at的重载问题

//管理以'\0'结尾的动态增长字符数组,关于operator[]重载问题
namespace a {
	class string {
	public:
		//可读可写重载,值修改返回对象,这里返回引用是方便修改字符串中的字符
		char& operator[](size_t pos) {
			
			assert(pos <= _size);
			
			return _str[pos];
		}

		//只读重载,对应const不可修改的类型
		const char& operator[](size_t pos) const {
			
			assert(pos <= _size);
			
			return _str[pos];
		}

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

//operator[]和at的两种重载
void test6() {
	string s1("hello");
	const string s2("hello");
	//s1[6];//越界使用断言一定报错,和数组不同
	//s2[6];同理

	//s1.at(6);//越界抛出异常
	//s2.at(6);//同理

	s1[0] = 'x';
	//s2[0] = 'x';//const修饰不能修改
	s1.at(0) = 'y';//s2同理
}

(2)迭代器

//四种迭代器:可读可写正向迭代器,可读可写反向迭代器,只读正向迭代器,只读反向迭代器
//begin和end迭代器的比较一般使用!=,除了一些特殊情况使用<,标准化
//begin获取第一个字符的迭代器,end获取最后一个字符即(\0处)下一个位置的迭代器,begin和end的区间范围是左闭右开,rbegin和rend同理
void test7() {
	string s1("hello world!");
	//可读可写正向迭代器
	string::iterator sit = s1.begin();
	while (sit != s1.end()) {
		(*sit) += 1;
		cout << *sit << " ";
		++sit;
	}
	cout << endl;
	cout << s1 << endl;

	//可读可写反向迭代器
	string::reverse_iterator rsit = s1.rbegin();
	while (rsit != s1.rend()) {
		(*rsit) -= 1;
		cout << *rsit << " ";
		++rsit;
	}
	cout << endl;
	cout << s1 << endl;



	const string s2("hello world");
	//只读正向迭代器
	string::const_iterator sit2 = s2.begin();
	while (sit2 != s2.end()) {
		//(*sit2) += 1;//报错
		cout << *sit2 << " ";
		++sit2;
	}
	cout << endl;

	//只读反向迭代器
	string::const_reverse_iterator rsit2 = s2.rbegin();
	while (rsit2 != s2.rend()) {
		//(*rsit2) -= 1;//报错
		cout << *rsit2 << " ";
		++rsit2;
	}
	cout << endl;
}

4. string类对象的修改操作

函数名称功能说明
push_back在字符串后尾插字符c
append在字符串后追加一个字符串
operator+=在字符串后追加字符串str
c_str返回C格式字符串
find+npos从字符串pos位置开始往后找字符c,后悔该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,如何将其返回
//string转化成C语言字符串
void test4() {
	string s("hello wordl!");
	cout << s << endl;
	cout << s.c_str() << endl;//c_str()返回C语言的字符串,为了更好的与C语言适应
}

//find、rfind、substr
void test5() {
    //利用find、rfind和substr取出文件后缀
	string file1("string.cpp");
	string file2("string.c");
	string file3("string.c.tar.zip");//这里针对多个含有标记的可以使用rfind,找最后一个标记

	string& file = file1;//这里使用引用方便更改

	size_t pos = file.find('.');//查找字符,找到返回 该字符下标,否则返回npos
	//size_t pos = file.rfind('.');//查找字符,找到返回 该字符下标,否则返回npos
	string suffix = file.substr(pos);//不传返回字符串长度默认是npos
	if (pos != string::npos) {
		cout << suffix << endl;
	}else {
		cout << "无后缀" << endl;
	}

    //npos是string里面的一个静态成员变量
    //static const size_t npos = -1;

    //利用substr和find取出url中的协议,域名,uri(资源)
	string url1("http://www.cplusplus.com/reference/string/string/find/");
	string url2("https://leetcode.cn/problems/reverse-only-letters/submissions/");

	string& url = url1;//方便更改

	//找出协议、域名、uri
	string protocol;//协议
	size_t pos1 = url.find("://", 0);
	if (pos1 != string::npos) {
		protocol = url.substr(0, pos1);
		cout << protocol << endl;
	}
	else {
		cout << "false" << endl;
	}

	string domain;//域名
	size_t pos2 = url.find('/', pos1+3);//从w开始找,找到/停下
	if (pos2 != string::npos) {
		domain = url.substr(pos1 + 3, pos2 - (pos1 + 3));//第一个参数传起始位置,第二个参数传长度
		cout << domain << endl;
	}
	else {
		cout << "false" << endl;
	}

	string uri;//资源
	uri = url.substr(pos2 + 1);
	cout << uri << endl;
}

//push_back、append和+=
void test6() {
    //连接字符串并扩容
	string s1;
	s1.push_back('x');//只能用来连接字符
	s1.append("hello");//连接字符串
	string s2("world");
	s1.append(s2);//连接字符串
	cout << s1 << endl;

	//常用为以下方法,使用重载后的+=
	string s3;
	s3 += 'x';
	s3 += "hello";
	string s4("world");
	s3 += s4;
	cout << s3 << endl;
    cout << s3.c_str << endl; //以C语言的方式打印字符串
}

注意:

1. 在string尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般情况下string类的+=操作的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。

2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reverse把空间预留好。

5. string类非成员函数

函数功能说明
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>>输入运算符重载
operator<<输出运算符重载
getline获取一行字符串,输入时不会受到空格的影响,只会受到换行符的影响
relational operators大小比较,接口很多,过于冗杂
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
C++string类提供了许多常用的函数。其中一些函数包括: 1. c_str():将string字符串转换为C风格的字符串,并返回该字符串的const指针(const char*)。这个函数可以用于将const string转换为const char*。例如: ```cpp string s1("1234567"); const char* s2 = s1.c_str(); ``` 2. operator\[\]和at():这两个函数都用于访问string中的字符。operator\[\]使用索引来访问字符,而at()使用位置来访问字符。例如: ```cpp string str = "abcdefg"; char c1 = str\[0\]; // 使用operator\[\] char c2 = str.at(1); // 使用at() ``` 3. to_string():将数值转换为对应的字符串。这个函数可以将整数、浮点数等数值类型转换为string类型。例如: ```cpp int a = 4; double b = 3.14; string str1 = to_string(a); string str2 = to_string(b); ``` 4. 构造函数:string类提供了多个构造函数,用于创建string对象。其中包括默认构造函数、使用字符常量构造、拷贝构造和数量*字符构造等。例如: ```cpp const char* str = "Hello World"; string s1; // 默认构造 string s2(str); // 使用字符常量构造 string s3("hello World"); // 同上 string s4(s2); // 拷贝构造 string s5(10, 'a'); // 数量*字符 ``` 这些是C++ string类的一些常用函数,可以帮助你在处理字符串时更加方便和灵活。 #### 引用[.reference_title] - *1* [C++ string常用函数用法总结](https://blog.csdn.net/qq_61514490/article/details/126165076)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [C++String常用函数总结](https://blog.csdn.net/weixin_51954217/article/details/127990342)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hiland.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值