


1. string 使用
1.1 string 头文件+链接
- #include头文件以及using namespace std
1.2 auto和范围for
1.2.1 auto
auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器, auto声明的变量必须由编译器在编译时期推导而得。
- 用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
- 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个进行推导,然后用推导出来的类型定义其他变量
- auto不能作为函数的参数,可以做返回值,但是建议谨慎使用
- auto不能直接用来声明数组
1.2.2 范围for
for循环后的括号由冒号" :"分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束
- 可以作用到数组和容器对象上进行遍历
- 底层很简单,容器遍历实际就是替换为迭代器,从汇编层也可以看到。

1.3 string类的常用接口
1.3.1 对象的常见构造
1.3.2 对象的容量操作


1.3.4 对象的访问及遍历操作

1.3.5 对象的修改操作

1.3.6 非成员函数

2. 模拟实现
2.1 string.h
cpp
class string {
public:
//迭代器
typedef char* iterator;
typedef const char* const_iterator;
iterator begin() { return _str; }
iterator end() { return _str + _size; }
const_iterator begin()const { return _str; }
const_iterator end()const { return _str + _size; }
string();//默认构造
string(const char* str);//字符串构造
string(const string& s);//拷贝构造(深拷贝)
string& operator=(const string& s);//拷贝赋值
~string();
//reverse 反转
//resize(size,可能连capacity一起改)
void reserve(size_t n);//扩容(capacity)
void push_back(char ch);//尾插
void append(const char* str);//追加
string& operator+=(char ch);//单字符+=
string& operator+=(const char* str);//字符串+=
void insert(size_t pos, char ch);//插入(挪动数据)
void insert(size_t pos, const char* str);
void erase(size_t pos = 0, size_t len = string::npos);//删除(挪动数据)
size_t find(char ch, size_t pos = 0)const;//(内容)查找位置
size_t find(const char* s, size_t pos = 0)const;
string substr(size_t pos = 0,size_t len=npos)const;//(位置)查找内容
void swap(string& s);
const char* c_str()const { return _str; }//将string对象转换成const char*
size_t size() const { return _size; }
size_t capacity() const { return _capacity; }
//下标
char& operator[](size_t pos) {
assert(pos < _size);
return _str[pos];
}
const char& operator[](size_t pos)const {
assert(pos < _size);
return _str[pos];
}
static const size_t npos = -1;
//string & operator<(char ch);
//string& operator<(const char* str);
private:
char* _str;
size_t _size;
size_t _capacity;//存储有效字符空间大小,不包含最后\0(实际空间>capacity 1个bite)
};
cpp
string operator+(const string& lhs, const string& rhs);
string operator+(const string& lhs, const char* rhs);
string operator+(const char* lhs, const string& rhs);
bool operator==(const string& lhs, const string& rhs);
bool operator!=(const string& lhs, const string& rhs);
bool operator>(const string& lhs, const string& rhs);
bool operator<(const string& lhs, const string& rhs);
bool operator>=(const string& lhs, const string& rhs);
bool operator<=(const string& lhs, const string& rhs);
ostream& operator<<(ostream& out, const string& s);
istream& operator>>(istream& in, string& s);
istream& getline(istream& in, string& s);
void swap(zyl::string& s1, zyl::string& s2);

2.2 接口实现
构造
cpp
string::string()//默认构造
:_str(new char[1])
, _size(0)
, _capacity(0) {
_str[0] = '\0';
}
string::string(const char* str)//字符串构造
:_size(strlen(str)) {
_str = new char[_size + 1];
_capacity = _size;
strcpy(_str, str);
}
string::string(const string& s)//拷贝构造(深拷贝)
:_str(new char[s._capacity + 1])
, _size(s._size)
, _capacity(s._capacity) {
strcpy(_str, s._str);
}
operator= / 析构
cpp
string& string::operator=(const string& s) {
if (this != &s) {
delete[]_str;
_str = new char[s._capacity + 1];
strcpy(_str, s._str);
_size = s._size;
_capacity = s._capacity;
}
return *this;
}
string::~string() {
delete[]_str;
_str = nullptr;
_size = _capacity = 0;
}
operator+=
cpp
string& string::operator+=(char ch) {
push_back(ch);
return *this;
}
string& string::operator+=(const char* str) {
append(str);
return *this;
}
reserve
cpp
void string::reserve(size_t n) {//扩容(capacity)
if (n > _capacity) {
// 每次开空间多开一个,因为_capacity不包含\0
char* tmp = new char[n + 1];
strcpy(tmp, _str);
delete[] _str;
_str = tmp;
_capacity = n;
}
}
push_back
cpp
void string::push_back(char ch) {
// 扩容
if (_size == _capacity) {
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
}
append
cpp
void string::append(const char* str) {//追加
size_t len = strlen(str);
// 扩容
if (_size + len > _capacity) {
reserve(_size + len);
}
strcpy(_str + _size, str);
_size += len;
}
insert
cpp
void string::insert(size_t pos, const char* str) {
assert(pos <= _size);
size_t len = strlen(str);
// 扩容
if (_size + len > _capacity) {
reserve(_size + len);
}
//挪动数据
//int end = _size;
//while (end >= (int)pos) {
// _str[end + len] = _str[end];
// --end;
//}
size_t end = _size + len;
while (end > pos) {
_str[end] = _str[end - len];
--end;
}
for (size_t i = 0; i < len; i++) {
_str[pos + i] = str[i];
}
_size += len;
}
void string::insert(size_t pos, char ch) { //插入(挪动数据)
assert(pos <= _size);
if (_size == _capacity) {//扩容
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
//挪动数据
//int end = _size;
//while (end >= (int)pos) {
// _str[end + 1] = _str[end];
// --end;
//}
size_t end = _size + 1;
while (end > pos) {
_str[end] = _str[end - 1];
--end;
}
_str[pos] = ch;
_size++;
}
erase
cpp
void string::erase(size_t pos, size_t len) {//删除(挪动数据)
if (pos > _size) pos = _size;
if (len == string::npos || len >= _size - pos) {
_str[pos] = '\0';
_size = pos;
}
else {
for (size_t i = pos + len; i < _size; ++i) {
_str[pos++] = _str[i];
}
_size -= len;
}
}
find
cpp
size_t string::find(char ch, size_t pos)const {//(内容)查找位置
assert(pos < _size);
for (size_t i = pos; i < _size; i++) {
if (_str[i] == ch)
return i;
}
return npos;
}
size_t string::find(const char* s, size_t pos)const {
const char* ptr = strstr(_str + pos, s);
if (ptr == nullptr)
return npos;
else
return ptr - _str;
}
substr / swap
cpp
string string::substr(size_t pos, size_t len)const {//(位置)查找内容,构造返回
if (pos > _size) pos = _size;
if (len == string::npos || len >= _size - pos)
len = _size - pos;
string sub;
sub.reserve(len);
for (size_t i = 0; i < len; ++i) {
sub += _str[pos + i];
}
return sub;
}
void string::swap(string& s) {
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
++operator + / == / != / > / < / >= / <=++
cpp
string operator+(const string& lhs, const string& rhs) {
string ret(lhs);//复制lhs
ret += rhs.c_str();//再追加转换成const char*的rhs
return ret;
}
string operator+(const string& lhs, const char* rhs) {
string ret(lhs);
ret += rhs;
return ret;
}
string operator+(const char* lhs, const string& rhs) {
string ret(lhs);
ret += rhs.c_str();
return ret;
}
bool operator==(const string& lhs, const string& rhs) {
return strcmp(lhs.c_str(), rhs.c_str()) == 0;
}
bool operator!=(const string& lhs, const string& rhs) {
return !(lhs == rhs);
}
bool operator>(const string& lhs, const string& rhs) {
return strcmp(lhs.c_str(), rhs.c_str()) > 0;
}
bool operator<(const string& lhs, const string& rhs) {
return strcmp(lhs.c_str(), rhs.c_str()) < 0;
}
bool operator>=(const string& lhs, const string& rhs) {
return !(lhs < rhs);
}
bool operator<=(const string& lhs, const string& rhs) {
return !(lhs > rhs);
}
operator << / >>
cpp
ostream& operator<<(ostream& out, const string& s) {
for (auto ch : s) {
out << ch;
}
return out;
}
istream& operator>>(istream& in, string& s) {
//char ch;
//ch = in.get();//读取单个字符
//while (ch != ' ' && ch != '\n') {
// s += ch;
// ch = in.get();
//}
//return in;
s.erase();
char ch;
ch = in.get();
char buff[128];
int i = 0;
while (ch != ' ' && ch != '\n') {
buff[i++] = ch;
if (i == 127) {
buff[i] = '\0';
s += buff;
i = 0;
}
ch = in.get();
}
if (i > 0) {
buff[i] = '\0';
s += buff;
}
return in;
}
getline
cpp
istream& getline(istream& in, string& s) {
char ch;
ch = in.get();
while (ch != '\n') {
s += ch;
ch = in.get();
}
return in;
}
swap
cpp
void swap(zyl::string& s1, zyl::string& s2) {
s1.swap(s2);
}
