从零开始学C++ (string类)

一、简单认识string类

1.string类的简介

string是用来表示字符序列的对象,标准string类为一些对象提供了类似于标准字节容器的接口,而且添加了特殊设计去操作单字节。是basic_string类模板针对char类型的实例化。它独立于所采用的编码来处理字节。

2.string类的默认成员函数

1.构造函数

C++98共有7种构造函数

  1. string():默认构造函数,无参数。构造一个空字符串,有0个字符。
  2. 拷贝构造,使用字符串str来拷贝构造一个字符串。
  3. 复制str字符串从pos位置开始的len个字符,如果字符串太短或者len为string::npos就直接复制到结尾。(string::npos是静态成员常数,在表示len时取值最大,意味着直到字符串结束,作为返回值时表示没有匹配。)
  4. 从c风格构造一个字符串,接受const char *s 的参数。
  5. 从s指向的字符数组中复制前n个字符。
  6. 使用n个字符C填满字符串。
cpp 复制代码
int main()
{
	string s1;                //1
	string s2("hello world"); //4
	string s3(s2);            //2
	string s4(s2, 6, 5);      //3
	string s5("xxxxxxxxx", 3);//5
	string s6(5, 'o');        //6
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	cout << s5 << endl;
	cout << s6 << endl;

	return 0;
}

2.析构函数

销毁对象,释放字符串通过分配器分配的所有内存。

3.赋值重载

赋值重载的功能是为字符串分配新值,替换当前内容。参数可以是string类类型对象,字符串,单个字符。

cpp 复制代码
	s4 = s2;
	s5 = "天天开心";
	s6 = 'x';
	cout << s4 << endl;
	cout << s5 << endl;
	cout << s6 << endl;

3.迭代器

迭代器是用来遍历和访问字符串的一种方式。他的底层实现和用法都类似于指针,可以对字符串进行修改,任何迭代器都属于他的类域。

迭代器一般有四种:iterator,const_iterator,reverse_iterator,const_reverse_iterator,分为正向迭代器,反向迭代器,普通字符串迭代器,const修饰的字符串迭代器,编译器会自动匹配最合适的迭代器。前面加C确定了是常量字符串。

使用方法:

cpp 复制代码
void test()
{
	string s("hello world");
	//正向迭代器
	string::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
	//反向迭代器
	string::reverse_iterator rit = s.rbegin();
	while (rit != s.rend())
	{
		cout << *rit << " ";
		rit++;
	}
	cout << endl;
	//const
	const string s1("hello world");
	string::const_iterator cit = s1.begin();
	while (cit != s1.end())
	{
		cout << *cit << " ";
		cit++;
	}
	cout << endl;
}

遍历字符串的三种方式:

1.下标+\[\]:通过下标可以访问字符串,也可以直接修改字符串内容。

cpp 复制代码
	string s("hellooooo!");
	//1.下标+[]
	for (int i = 0; i < s.size(); i++)
	{
		cout << s[i];
	}
	cout << endl;
	s[0] = 'e';
	cout << s << endl;

2.迭代器:通过迭代器访问字符串,用法类似指针,所以它也可以修改字符串内容。

cpp 复制代码
	string s("hellooooo!");

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

3.范围for:范围for可以遍历字符串,auto用来自动赋值,自动迭代,自动判断结束。在底层也是通过迭代器来实现,把*it的值赋给ch,所有容器也都支持范围for,因为所有容器支持迭代器。ch是将字符串中每个字符遍历拷贝给ch,修改ch不影响原字符串。因为ch仅仅是字符串的拷贝。若想修改字符串,需要将auto改成auto&。

cpp 复制代码
	for (auto ch : s)
	{
		cout << ch;
	}
	cout << endl;

auto和范围for

auto

  • 在早期C++中,使用auto修饰的变量,是具有自动存储器的局部变量,后来这个不重要了。C++11赋予了其新的含义,auto不再是一个存储类型提示符,而是作为新的类型提示符来指示编译器,auto声明的编译器必须在编译器编译时推导而得。
  • auto声明指针类型时auto和auto*没有任何区别,但声明引用时必须加&。
  • 在同一行声明多个变量时,必须是相同类型的变量,否则将会报错,编译器只会对第一个类型进行推导,用推导出来的类型定义其他变量。
  • auto不能用来做参数,可以用来做返回值,但建议谨慎使用。
  • auto不能用来声明数组。

注意:auto的主要作用是用来简化代码,替换长类型,因此必须知道类型,否则无法推导,但这也牺牲了可读性。(typeid().name()是用来查看类型)。

范围for

  • 对于一个有范围的集合,使用范围for可以自动迭代,自动取数据,自动判断结束。
  • 范围for适用于容器和数组。
  • 他的底层就是替换为迭代器,可以从汇编的角度看到。
cpp 复制代码
int main()
{
	//test();
	int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
	for (auto a : arr)
	{
		cout << a << " ";
	}
	cout << endl;
	string s("hello world!");
	for (auto ch : s)
	{
		cout << ch;
	}
	cout << endl;
	return 0;
}

4.容量相关

  • size和length都是返回字符串的长度,考虑到C++发展历史,length先出来,size是为了后面适应STL后出来,他们的功能相同。
  • max_size是返回字符串最大值,由于技术上的缺陷,返回的实际是整形的最大值,一般不常用。
  • capacity返回字符串的容量,不包括\0,实际开的空间会比capacity多。在vs下有buffer,字符串内容少时就放在buffer中。
  • reserve的功能是提前开好空间,避免扩容,提高效率。(当size = 10,capacity = 20时,如果要开的空间n>20,确定一定会开空间,但是当n<10或10<n<20时,不具有约束力,在不同平台下情况可能不同,在vs平台不缩容,在g++会缩容。
  • clear清除字符串中数据,不清除容量。
  • empty,判断字符串是否为空,不包括\0。

5.元素遍历

  • \[\] 返回pos位置的字符,用断言来判断是否越界。
  • at越界会抛异常

6.修改相关

1.operator+=

拼接字符串,他的参数可以是string类类型对象,字符串,单个字符。

cpp 复制代码
int main()
{
	string s("hello");
	string ss("world");

	s += ss;
	cout << s << endl;

	s += "xxxxxxx";
	cout << s << endl;

	s += 'z';
	cout << s << endl;
	return 0;
}

2.append

功能和+=类似,一般+=用的比较多。

cpp 复制代码
	string s1("hi");
	s1.append(s);
	cout << s1 << endl;
	s1.append("!!!");
	cout << s1 << endl;
	s1.append(1,'c');
	cout << s1 << endl;

3.push_back

尾插。

cpp 复制代码
	s1.push_back('v');
	cout << s1 << endl;

4.assign

赋值,会覆盖原字符串的内容,一般用处不大。

cpp 复制代码
	string s3("iiitttssss");
	s1.assign(s3);
	cout << s1 << endl;
	s1.assign("hiiiiiiiii");
	cout << s1 << endl;
	s1.assign(5, 'a');
	cout << s1 << endl;

5.insert

在pos位置插入,可以是类类型对象,字符串或者他们的一部分,也可以是单个字符,可以是头插或者中间插入。

cpp 复制代码
	string s("hello");
	string ss("world");
	s.insert(3, ss);
	cout << s << endl;
	s.insert(0, "xxxx");
	cout << s << endl;
	s.insert(0, 2, 'c');
	cout << s << endl;
	s.insert(s.begin(), 'h');
	cout << s << endl;

6.erase

删除字符串的一部分。

cpp 复制代码
	s.erase(0, 3);
	cout << s << endl;
	s.erase(s.begin());
	cout << s << endl;
	s.erase(s.begin(), s.end());
	cout << s << endl;

7.replace

replace可以替换字符串中的部分内容。

cpp 复制代码
	string s("h  e  l  l  o w  o  r  l  d");
	//s.replace(5, 1, "%%");
	//cout << s << endl;
	size_t pos = s.find(' ');
	while (pos != string::npos)
	{
		s.replace(pos, 1, "%%");
		cout << s << endl;
		pos = s.find(' ', pos + 2);
	}

注意:insert ,erase,replace性能较差,应该谨慎使用。

8.swap

交换此容器(即当前字符串对象)与另一个字符串对象 str 的内容。两者的长度可以不同。

7.string一些其他操作

c_str

获取C风格的字符串,返回一个指向以 \0 结尾的字符数组的指针。

cpp 复制代码
	string file;
	cin >> file;
	FILE* fout = fopen(file.c_str(), "r");
	char ch = fgetc(fout);
	while (ch != EOF)
	{
		cout << ch;
		ch = fgetc(fout);
	}
	fclose(fout);

data

与c_str功能类似。

find

在字符串内查找子串或字符。

cpp 复制代码
	string s("test.cpp");
	size_t t = s.find('.');
	string subffer = s.substr(t);
	cout << subffer << endl;

rfind

和find功能相同,但是是倒着找。

cpp 复制代码
	string s("test.cpp.zip");
	size_t t = s.rfind('.');
	string subffer = s.substr(t);
	cout << subffer << endl;

find_first_of find_last_of

在字符串中搜索任意一个 指定的字符集合中的字符,返回第一个匹配到的位置。find_last_of() :与上面类似,但是从字符串末尾开始向前搜索,返回最后一个匹配指定字符集合的位置。

cpp 复制代码
    string str("Please, replace the vowels in this sentence by asterisks.");
    size_t found = str.find_first_of("aeiou");
    while (found != string::npos)
    {
        str[found] = '*';
        found = str.find_first_of("aeiou", found + 1);
    }

    cout << str << '\n';

find_first_not_of() :在字符串中搜索不属于指定字符集合中的第一个字符。

find_last_not_of() :从字符串末尾开始 向前搜索,查找第一个不属于指定字符集合的字符。

substr

通过一个类类型对象的一部分构建一个新的类类型对象。

相关推荐
名字还没想好☜1 天前
Next.js App Router 约定式文件实战:loading、error、not-found 怎么兜住加载态与异常
开发语言·前端·javascript·react·next.js
BerryS3N1 天前
C++在AI时代的核心力量:从底层加速到大规模大模型推理引擎的高能实践
开发语言·c++·人工智能
AAIshangyanxiu1 天前
R 语言耦合遥感技术的水环境综合评估完整技术体系,水质水深水温定量反演方法
开发语言·r语言·遥感水文·水文遥感·r语言遥感
乐启国际旅行社有限公司1 天前
SpringSecurity+JWT实现文旅系统细粒度数据权限管控(多角色数据隔离)
开发语言·python
FlightYe1 天前
音视频修炼之视频基础(一):视频基础理论
android·c++·vscode·音视频·androidx·android runtime
小小帅呀1 天前
CUDA编程实战09:CUDA Graph 实战——降低重复 Kernel 与流水线提交开销
c++·人工智能·矩阵
AI人工智能集结号1 天前
AI回答采集数据清洗:Python实现空回答、拒绝与无关样本识别
开发语言·人工智能·python
jaysee-sjc1 天前
【JavaWeb】JDBC与Mybatis零基础入门详解
java·开发语言·前端·mybatis
星恒随风1 天前
C++ STL 详解:map 与 multimap 的使用、operator[]
开发语言·c++·笔记·学习·状态模式
森叶1 天前
用 DataTransfer 模拟“用户选择本地文件“:不用系统对话框,也能给 `<input type=“file“>` 塞进真实文件
java·开发语言·log4j