C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库 中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
string类是表示字符串的字符串类,该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
string在底层实际是:basic_string模板类的别名,typedef basic_string string;
在使用string类时,必须包含头文件
//构建一个空的字符串
string();
//用c-string来构造string类对象
string(const char* s);
//构造一个包含有n个c字符的对象
string(size_t n,char c);
//拷贝构造函数
string(const string& s);
//用s中的前n个字符构造一个新对象
string(const string& s,size_t n);
示例:
#include
using namespace std;
int main(){
string s1;
string s2("Hello World!");
string s3(10,'a');
string s4(s2);
string s5(s3,5);
return 0;
}
==> s1是空字符串;s2->"Hello World";s3->"aaaaaaaaaa";s4->"Hello World";s5->"aaaaa";
//返回字符串的有效字符长度
size_t size() const;
//返回字符串的有效字符长度
size_t length() const;
//返回空间的总大小
size_t capacity() const;
//检测字符串是否为空,为空返回ture,不为空返回false
bool empty() const;
//清空有效字符
void clear();
其中需要注意的地方:
还有几个修改有效字符个数的操作:
//将有效字符的个数改成n个,多出的空间用字符c填充
void resize(size_t n,char c);
//将有效字符的个数改成n个,多出的空间用\0填充
void resize(size_t n);
//为字符串预留空间
void reserve(size_t res_arg=0);
需要注意的地方:
对于reserve()进行如下测试:
void Test() {
string s("Hello world");
cout << s.size() << endl;
cout << s.capacity() << endl;
s.reserve(500);
cout << s.size() << endl;
cout << s.capacity() << endl;
s.reserve(50);
cout << s.size() << endl;
cout << s.capacity() << endl;
}
//返回pos位置的字符,const string类对象调用
char& operator[](size_t pos);
//返回pos位置的字符,非const string类对象调用
const char& operator[](size_t pos) const;
类似于对数组的下标访问;
1、增加
//在字符串后尾插字符串c
void push_back(char c);
//在字符串后追加一个字符串
string& append(const char* c);
//在字符串后追加字符串str
string& operator+=(const string& str);
//在字符串后追加字符C
string& operator+=(char c);
2、返回C格式字符串
const char* c_str()const;
3、寻找/匹配/删除
//从字符串pos位置开始往后匹配字符C,返回C的位置
size_t find(char c,size_t pos = 0)const;
//从字符串pos位置开始往前匹配字符C,返回C的位置
size_t rfind(char c,size_t pos = npos);
//在str中从pos位置开始,截取n个字符,然后将其返回
string substr(size_t pos = 0,size_t n = nops)const;
//在str中从pos位置开始,删除n个字符
string& erase ( size_t pos = 0, size_t n = npos );
==》小练习:去除url中的域名
void UrlStrTest() {
string url("http://www.baidu.com/hahah/heheh/121231");
cout << url << endl;
size_t start = url.find("://");
if (start == string::npos) {
cout << "invalid url" << endl;
return;
}
start += 3;
size_t finish = url.find('/',start);
string address = url.substr(start, finish - start);
cout << "address" << address << endl;
}
要自主实现string类其实不是很难,但是在完成拷贝构造函数的时候需要注意,之前我们有总结过,默认的拷贝构造函数都是进行浅拷贝,而在string类中实现拷贝构造则需要进行深拷贝,这是特别需要注意的一点!!!那么什么是深拷贝?什么是浅拷贝??
浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时这份资源就会被释放掉,而此时另一些对象并不知道,还会对原来的内存空间进行资源操作,会发生访问违规;
深拷贝:给每个对象都独立分配资源,保证多个对象之间不会因为共享资源而造成多次释放,造成程序的崩溃;
所以在完成string类的自主实现时,有以下做法:
class string {
public:
string(const char* str = ""){
if (str == nullptr) {
assert(false);
return;
}
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
string(const string& s)
:_str(new char[strlen(s._str) + 1])
{
strcpy(_str, s._str);
}
~string() {
if (_str) {
delete[] _str;
_str = nullptr;
}
}
private:
char* _str;
};
当然除了拷贝构造函数,还有赋值运算符的重载!!!!
namespace My {
class String {
public:
//构造
String(const char* str = "") {
if (str == nullptr) {
assert(false);
return;
}
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity + 1];
strcpy(_str,str);
}
String(const String& s)
: _str(new char[s._capacity + 1])
, _size(s._size)
, _capacity(s._capacity)
{
strcpy(_str, s._str);
}
String& operator=(const String& s) {
if (this != &s) {
char* pStr = new char[s._capacity + 1];
strcpy(pStr, s._str);
delete[] _str;
_str = pStr;
_size = s._size;
_capacity = s._capacity;
}
return *this;
}
~String() {
if (_str) {
delete[] _str;
_str = nullptr;
}
}
//Iterators:begin、end
typedef char* Interators;
Interators Begin() {
return _str;
}
Interators End() {
return _str + _size;
}
//Capacity:size,length,
void Reserve(size_t res_arg = 0) {
if (_capacity >= res_arg)
return;
else
_capacity = res_arg;
}
//Modify:operator+=、PushBack、Append、
void PushBack(char c) {
if (_size == _capacity)
Reserve(_capacity * 2);
_str[_size++] = c;
_str[_size] = '/0';
}
void Append(size_t n,char c) {
for (size_t i = 0; i < n; ++i) {
PushBack(c);
}
}
void Append(const char* str) {
}
String& operator+=(char c) {
PushBack(c);
return *this;
}
String& operator+=(const char* str) {
}
private:
char* _str;
size_t _capacity;
size_t _size;
};
}
还没写完,等有时间会完善的~