目录
f,Non-member function overloads
一、string介绍
C语言中,字符串是以 ‘\0’ 结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
C++封装了这些接口和操作,创建出string类:
1,string底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>string
2,string是表示字符串的字符串类
3,该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作
4,不能操作多字节或者变长字符的序列
二、string类底层模拟实现
C++标准库中的string我们使用起来很方便,但我们只有自己去实现过string类的常用接口,我们才能更加深入的去了解string类。这里我将以多文件的形式去模拟实现string类,以下是我要实现的接口:
#ifndef _STRING_H_
#define _STRING_H_
#include <iostream>
#include <string>
#include <assert.h>
#pragma warning(disable:4996)
using namespace std;
namespace jzh
{
class string
{
public:
//构造函数
string(const char* s = "")
{
if (nullptr == s)
s = "";
_size = strlen(s);
_capacity = _size;
_str = new char[_capacity + 1];
strcpy(_str, s);
}
//拷贝构造函数
string(const string& str)
:_str(nullptr)
{
string tmp(str._str);
swap(tmp);
}
//析构函数
~string()
{
if (_str)
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
}
//赋值运算符重载
string& operator=(const string& str)
{
if (this != &str)
{
string tmp(str);
swap(tmp);
}
return *this;
}
//迭代器(iterator)
typedef char* iterator;
iterator begin();
iterator end();
typedef const char* const_iterator;
const_iterator begin()const;
const_iterator end()const;
//容量(capacity)
size_t size()const;
size_t capacity()const;
void reserve(size_t n);
void resize(size_t n, char ch = '\0');
void clear();
bool empty()const;
//元素访问(element access)
char& operator[](size_t pos);
const char& operator[](size_t pos)const;
//修改操作(modify)
string& insert(size_t pos, char ch);
string& insert(size_t pos, const char* s);
void push_back(char ch);
string& append(const char* s);
string& operator+=(char ch);
string& operator+=(const char* s);
string& operator+=(const string& str);
string& erase(size_t pos = 0, size_t len = npos);
void swap(string& str);
//字符串操作(String operations)
const char* c_str()const;
size_t find(char ch, size_t pos = 0)const;
size_t find(const char* sub, size_t pos = 0)const;
private:
size_t _size;
size_t _capacity;
char* _str;
public:
static const size_t npos;
};
//非成员函数重载(Non-member function overloads)
istream& operator>>(istream& in, string& str);
ostream& operator<<(ostream& out, const string& str);
string operator+(const string& str, char ch);
string operator+(const string& str, const char* s);
string operator+(const string& s1, const string& s2);
}
#endif
1,默认成员函数的实现
由于string类中涉及到资源的管理,所以其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。
a,构造函数
string(const char* s = "")
{
if (nullptr == s)
s = "";
_size = strlen(s);
_capacity = _size;
//开辟一个与传入的字符串的长度 + 1的空间 ,+1是保存 \0
_str = new char[_capacity + 1];
//将传入的字符串内容拷贝到当前类的内容中
strcpy(_str, s);
}
b, 析构函数
~string()
{
if (_str)
{
delete[] _str;
_str = nullptr;
}
}
c,拷贝构造函数
通过构造函数和传进来的对象创建一个临时对象,再将该临时对象的成员变量与新对象的成员变量做交换,从而完成拷贝构造。_str一开始要置为
nullptr
原因是让交换后的临时变量不进行释放。
string(const string& str)
:_str(nullptr)
{
//复用构造函数创建临时对象
string tmp(str._str);
//swap的实现代码在后面
swap(tmp);
}
d,赋值运算符重载
string& operator=(const string& str)
{
if (this != &str)
{
string tmp(str);
swap(tmp);
}
return *this;
}
2,常用接口实现
a,Iterator
jzh::string::iterator jzh::string::begin()
{
return _str;
}
jzh::string::iterator jzh::string::end()
{
return _str + _size;
}
//const类型
jzh::string::const_iterator jzh::string::begin()const
{
return _str;
}
jzh::string::const_iterator jzh::string::end()const
{
return _str + _size;
}
b,Capacity
size_t jzh::string::size()const
{
return _size;
}
size_t jzh::string::capacity()const
{
return _capacity;
}
void jzh::string::reserve(size_t n)
{
if (n > _capacity)
{
char* tmp = new char[n + 1];
strcpy(tmp, _str);
delete[] _str;
_str = tmp;
_capacity = n;
}
}
void jzh::string::resize(size_t n,char ch)
{
if (n > _size)
{
if (n > _capacity)
{
reserve(n);
}
for (size_t i = _size; i < n; i++)
{
_str[i] = ch;
}
}
_size = n;
_str[n] = '\0';
}
void jzh::string::clear()
{
_size = 0;
_str[0] = '\0';
}
bool jzh::string::empty()const
{
return 0 == _size;
}
c,Element access
char& jzh::string::operator[](size_t pos)
{
assert(pos < _size);
return _str[pos];
}
const char& jzh::string::operator[](size_t pos)const
{
assert(pos < _size);
return _str[pos];
}
d,Modifiers
jzh::string& jzh::string::insert(size_t pos, char ch)
{
assert(pos <= _size);
if (_size == _capacity)
{
if (0 == _capacity)
reserve(15);
else
reserve(_capacity * 2);
}
size_t end = _size + 1;
while (end > pos)
{
_str[end] = _str[end - 1];
end--;
}
_str[pos] = ch;
_size++;
return *this;
}
jzh::string& jzh::string::insert(size_t pos, const char* s)
{
assert(pos <= _size);
size_t len = strlen(s);
if (len + _size > _capacity)
{
reserve(len + _size);
}
size_t end = _size + len;
while (end != 0 && end >= pos + len)
{
_str[end] = _str[end - len];
end--;
}
strncpy(_str + pos, s, len);
_size += len;
return *this;
}
void jzh::string::push_back(char ch)
{
insert(_size, ch);
}
jzh::string& jzh::string::append(const char* s)
{
insert(_size, s);
return *this;
}
jzh::string& jzh::string::operator+=(char ch)
{
push_back(ch);
return *this;
}
jzh::string& jzh::string::operator+=(const char* s)
{
append(s);
return *this;
}
jzh::string& jzh::string::operator+=(const string& str)
{
append(str._str);
return *this;
}
jzh::string& jzh::string::erase(size_t pos, size_t len)
{
assert(pos < _size);
if (len == npos || pos + len >= _size)
{
_str[pos] = '\0';
_size = pos;
}
else
{
strcpy(_str + pos, _str + pos + len);
_size -= len;
}
return *this;
}
void jzh::string::swap(string& str)
{
std::swap(_str, str._str);
std::swap(_size, str._size);
std::swap(_capacity, str._capacity);
}
e,String operations
const char* jzh::string::c_str()const
{
return _str;
}
size_t jzh::string::find(char ch, size_t pos)const
{
assert(pos < _size);
for (size_t i = pos; i < _size; i++)
{
if (ch == _str[i])
return i;
}
return npos;
}
size_t jzh::string::find(const char* sub, size_t pos)const
{
assert(pos < _size);
const char* ret = strstr(_str + pos, sub);
if (nullptr == ret)
return npos;
else
return ret - _str;
}
f,Non-member function overloads
istream& jzh::operator>>(istream& in, string& str)
{
str.resize(0);
char ch = 'a';
while (1)
{
in.get(ch);
if (ch==' ' || ch == '\n')
{
break;
}
else
{
str += ch;
}
}
return in;
}
ostream& jzh::operator<<(ostream& out, const string& str)
{
for (size_t i = 0; i < str.size(); i++)
{
out << str[i];
}
return out;
}
string operator+(const string& str, char ch)
{
string tmp(str);
tmp += ch;
return tmp;
}
string operator+(const string& str, const char* s)
{
string tmp(str);
tmp += s;
return tmp;
}
jzh::string jzh::operator+(const string& s1, const string& s2)
{
string tmp(s1);
tmp += s2;
return tmp;
}
总代码:
#include "string.h"
const size_t jzh::string::npos = -1;
//迭代器(Iterator)
jzh::string::iterator jzh::string::begin()
{
return _str;
}
jzh::string::iterator jzh::string::end()
{
return _str + _size;
}
jzh::string::const_iterator jzh::string::begin()const
{
return _str;
}
jzh::string::const_iterator jzh::string::end()const
{
return _str + _size;
}
//容量(capacity)
size_t jzh::string::size()const
{
return _size;
}
size_t jzh::string::capacity()const
{
return _capacity;
}
void jzh::string::reserve(size_t n)
{
if (n > _capacity)
{
char* tmp = new char[n + 1];
strcpy(tmp, _str);
delete[] _str;
_str = tmp;
_capacity = n;
}
}
void jzh::string::resize(size_t n,char ch)
{
if (n > _size)
{
if (n > _capacity)
{
reserve(n);
}
for (size_t i = _size; i < n; i++)
{
_str[i] = ch;
}
}
_size = n;
_str[n] = '\0';
}
void jzh::string::clear()
{
_size = 0;
_str[0] = '\0';
}
bool jzh::string::empty()const
{
return 0 == _size;
}
//元素访问(element access)
char& jzh::string::operator[](size_t pos)
{
assert(pos < _size);
return _str[pos];
}
const char& jzh::string::operator[](size_t pos)const
{
assert(pos < _size);
return _str[pos];
}
//修改操作(Modifiers)
jzh::string& jzh::string::insert(size_t pos, char ch)
{
assert(pos <= _size);
if (_size == _capacity)
{
if (0 == _capacity)
reserve(15);
else
reserve(_capacity * 2);
}
size_t end = _size + 1;
while (end > pos)
{
_str[end] = _str[end - 1];
end--;
}
_str[pos] = ch;
_size++;
return *this;
}
jzh::string& jzh::string::insert(size_t pos, const char* s)
{
assert(pos <= _size);
size_t len = strlen(s);
if (len + _size > _capacity)
{
reserve(len + _size);
}
size_t end = _size + len;
while (end != 0 && end >= pos + len)
{
_str[end] = _str[end - len];
end--;
}
strncpy(_str + pos, s, len);
_size += len;
return *this;
}
void jzh::string::push_back(char ch)
{
insert(_size, ch);
}
jzh::string& jzh::string::append(const char* s)
{
insert(_size, s);
return *this;
}
jzh::string& jzh::string::operator+=(char ch)
{
push_back(ch);
return *this;
}
jzh::string& jzh::string::operator+=(const char* s)
{
append(s);
return *this;
}
jzh::string& jzh::string::operator+=(const string& str)
{
append(str._str);
return *this;
}
jzh::string& jzh::string::erase(size_t pos, size_t len)
{
assert(pos < _size);
if (len == npos || pos + len >= _size)
{
_str[pos] = '\0';
_size = pos;
}
else
{
strcpy(_str + pos, _str + pos + len);
_size -= len;
}
return *this;
}
void jzh::string::swap(string& str)
{
std::swap(_str, str._str);
std::swap(_size, str._size);
std::swap(_capacity, str._capacity);
}
//字符串操作(String operations)
const char* jzh::string::c_str()const
{
return _str;
}
size_t jzh::string::find(char ch, size_t pos)const
{
assert(pos < _size);
for (size_t i = pos; i < _size; i++)
{
if (ch == _str[i])
return i;
}
return npos;
}
size_t jzh::string::find(const char* sub, size_t pos)const
{
assert(pos < _size);
const char* ret = strstr(_str + pos, sub);
if (nullptr == ret)
return npos;
else
return ret - _str;
}
//非成员函数重载(Non-member function overloads)
istream& jzh::operator>>(istream& in, string& str)
{
str.resize(0);
char ch = 'a';
while (1)
{
in.get(ch);
if (ch==' ' || ch == '\n')
{
break;
}
else
{
str += ch;
}
}
return in;
}
ostream& jzh::operator<<(ostream& out, const string& str)
{
for (size_t i = 0; i < str.size(); i++)
{
out << str[i];
}
return out;
}
string operator+(const string& str, char ch)
{
string tmp(str);
tmp += ch;
return tmp;
}
string operator+(const string& str, const char* s)
{
string tmp(str);
tmp += s;
return tmp;
}
jzh::string jzh::operator+(const string& s1, const string& s2)
{
string tmp(s1);
tmp += s2;
return tmp;
}
本文若有不足之处欢迎大家指出,谢谢大家!!