文章目录
- 六、string类
- 5. string类的操作
- 6. string类的转换
- 7. string类的模拟实现
- 未完待续
搭配文档食用
六、string类
5. string类的操作
上面的函数中,有些是不常用的,咱们只挑几个重要的进行讲解。
c_str 就是将字符串转换成 C语言 字符串的格式。
get_allocator 就是申请内存池,目前用不上。
copy 就是拷贝,缺点是必须先创建好一个字符数组,字符数组还是形参,返回拷贝的个数,被下面的 substr 函数完虐。substr 函数返回一个 string 类型。
假设有个情景:需要我们找出文件名的后缀,该怎么办?
#include<iostream>
#include<string>
using namespace std;
void test1()
{
string s("file.cpp");
// find函数返回第一个出现的下标
size_t pos = s.find('.');
// 在string类里,没找到都会以npos的形式返回。
if (pos != string::npos)
{
string suffix = s.substr(pos);
cout << suffix << endl;
}
}
int main()
{
test1();
return 0;
}
find 函数
substr 函数
那么假设这个文件里 . 很多,我们要返回最后一个后缀,该怎么办?这个时候,就到了 rfind 大展身手的时候了,rfind 函数也是查找,不过是从后往前查找。
#include<iostream>
#include<string>
using namespace std;
void test2()
{
string s("file.cpp.rar.zip.tar");
size_t pos = s.rfind('.');
if (pos != string::npos)
{
string suffix = s.substr(pos);
cout << suffix << endl;
}
}
int main()
{
test2();
return 0;
}
再假设一个情景,有一个网址,将其 协议 , 域名 , 资源名 给分离开,怎么搞呢?
#include<iostream>
#include<string>
using namespace std;
void test3()
{
string url("https://cplusplus.com/reference/string/string/substr/");
// 协议
string protocol;
// 域名
string domain;
// 资源名
string uri;
size_t i1 = url.find(":");
if (i1 != string::npos)
{
protocol = url.substr(0, i1 - 0);
cout << protocol << endl;
}
// 从域名开始找 '/'
size_t i2 = url.find('/', i1 + 3);
if (i2 != string::npos)
{
domain = url.substr(i1 + 3, i2 - i1 - 3);
cout << domain << endl;
// 剩下的都是资源名
uri = url.substr(i2 + 1);
cout << uri << endl;
}
}
int main()
{
test3();
return 0;
}
compare 就是比较,不过 string 针对比较都做了重载,可用直接用 > ! = 等比较。
6. string类的转换
当我们涉及到其他类型转换成字符串类型时,有这样一个函数:
#include<iostream>
#include<string>
using namespace std;
void test4()
{
int a = 123456;
string s = to_string(a);
cout << s << endl;
}
int main()
{
test4();
return 0;
}
当然,有其他类型转换成字符串类型,就有字符串类型转换成其他类型。
#include<iostream>
#include<string>
using namespace std;
void test5()
{
string s1("13579");
string s2("3.1415926");
int i = stoi(s1);
double d = stod(s2);
cout << i << endl << d << endl;
}
int main()
{
test5();
return 0;
}
7. string类的模拟实现
接下来我们来具体实现一下 string 类。在实现 string 类的时候,我们需要将其封装一下,包含在自己的命名空间下。
// string.h 头文件下
#pragma once
#include<iostream>
// 我们自己实现的 string 类的专属命名空间
namespace my
{
class string
{
public:
//
private:
// 字符数组 存数据
char* _str;
// 无符号整形 存数据个数、字符串的长度
size_t _size;
// 存为该字符串已经分配的空间、容量
size_t _capacity;
};
}
接下来我们来实现构造函数,分为无参构造函数,和有参构造函数。
// my 命名空间下
class string
{
public:
// 无参构造函数
string()
:_str(nullptr) // 初始化列表
,_size(0)
,_capacity(0)
{}
// 有参构造函数
string(const char* str)
:_size(strlen(str))
{
_capacity = _size;
_str = new char[_capacity + 1];
strcpy(_str, str);
}
private:
char* _str;
size_t _size;
size_t _capacity;
};
构造函数不一定非要使用初始化列表,我们在有参构造函数里面若是使用初始化列表,由于三个对象都需要调用 strlen 函数,导致效率不高,所以可以初始化列表和赋值一起使用。