目录
六、STL简介
(一)什么是STL
STL(standard template libaray- 标准模板库 ) : 是 C++ 标准库的重要组成部分 ,不仅是一个可复用的组件库,而且 是一个包罗数据结构与算法的软件框架 。(二)STL的版本
原始版本Alexander Stepanov 、 Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。 HP 版本 -- 所有 STL 实现版本的始祖。P. J. 版本由 P. J. Plauger 开发,继承自 HP 版本,被 Windows Visual C++ 采用,不能公开或修改,缺陷:可读性比较低,符号命名比较怪异。RW 版本由 Rouge Wage 公司开发,继承自 HP 版本,被 C+ + Builder 采用,不能公开或修改,可读性一般。SGI 版本由 Silicon Graphics Computer Systems , Inc 公司开发,继承自 HP 版 本。被 GCC(Linux) 采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。我们后面学习 STL 要阅读部分源代码, 主要参考的就是这个版本。(三)STL六大组件
学习STL的三个境界:能用,明理,能扩展 。
string严格来说不是STL,而是标准库。
以下是常用的构造方式
- string s1;
- string s2("123");
- string s3 = "123";
- string s4(s3);
函数名称 | 作用 |
---|---|
size | 返回字符串有效长度 |
length | 返回字符串有效长度 |
capacity | 返回空间总大小 |
empty | 若字符串为空返回true,不为空返回false |
clear | 清空有效字符 |
reserve | 预留空间 |
resize | 将字符串大小改为n |
- #include
- int main()
- {
- string s = "C++";
- cout << s << endl;
- cout <<"s.size():"<< s.size() << endl;
- cout <<"s.length():"<< s.length() << endl;
- cout << "s.capacity():"<
capacity() << endl; - cout << "s.empty():"<
empty() << endl; - cout << "-----------------------------------------------------" << endl;
- s.resize(6);
- cout << "s.size():" << s.size() << endl;
- cout << "s.capacity():" << s.capacity() << endl;
- cout << "-----------------------------------------------------" << endl;
- s.reserve(16);
- cout << "s.capacity():" << s.capacity() << endl;
- cout << "-----------------------------------------------------" << endl;
- s.clear();
- cout << "s.empty():" << s.empty() << endl;
-
- return 0;
- }
函数名称 | 作用 |
operator[] |
返回
pos
位置的字符,
const string
类对象调用
|
begin+end | 返回首元素地址+返回最后一个元素的下一个位置的地址 |
rbegin+rend | 返回最后一个元素的地址+返回第一个元素的前一个位置地址 |
范围for | for的新遍历方式(C++11) |
- string s = "asdfghjkl";
- string::iterator it = s.begin();
- while (it != s.end())
- {
- cout << *it ;
- it++;
- }
- cout << endl;
这就是正向迭代器,其中string::iterator也可以用auto
- string s = "asdfghjkl";
- auto it = s.begin();
- while (it != s.end())
- {
- cout << *it ;
- it++;
- }
- cout << endl;
还有反向迭代器
- string s = "asdfghjkl";
- auto it = s.rbegin();
- while (it != s.rend())
- {
- cout << *it ;
- it++;
- }
- cout << endl;
范围for(原理:编译器会将范围for变成迭代器)
- string s = "asdfghjkl";
- for (auto a : s)
- {
- cout << a;
- }
- cout << endl;
函数名称 | 作用 |
push_back | 在字符串尾部添加字符 |
append | 在字符串后面追加一个字符串 |
operator+= | 在字符串后面追加字符串str |
c_str | 返回C格式的字符串 |
find+npos |
从字符串pos位置开始往后找字符,返回该字符在字符串中的位置
|
rfind |
从字符串pos位置开始往前找字符,返回该字符在字符串中的位置
|
substr |
在str中从pos位置开始,截取n个字符,然后将其返回
|
insert | 插入字符或字符串 |
erase | 删除字符或字符串 |
- int main()
- {
- string s = "hello ";
- cout << s << endl;
- cout << "------------------------------------------------" << endl;
- s.push_back('w');
- cout << s << endl;
- cout << "------------------------------------------------" << endl;
- s += "orld";
- cout << s << endl;
- cout << "------------------------------------------------" << endl;
- s.append(" /C++");
- cout << s << endl;
- cout << "------------------------------------------------" << endl;
- cout << s.find('h') << endl;
- cout << "------------------------------------------------" << endl;
- cout << s.substr(2, 5) << endl;
- cout << "------------------------------------------------" << endl;
- s.insert(0,1,'+');
- s.insert(s.begin(), '+');
- cout << s << endl;
- cout << "------------------------------------------------" << endl;
- s.erase(0, 2);
- cout << s << endl;
- cout << "------------------------------------------------" << endl;
-
- return 0;
- }
注意,我们在文档时,substr是有缺省值的
当我们不给截多少字符的时候,会给npos值,那么npos值是多少呢???
是-1吗???
文档中npos的类型是size_t,这是无符号整形,也就是说这里的-1并不真的是,而是42亿+
到现在为止,我们并没有遇到过这么大的长度,所以可以理解为,截到字符串结束
还有值得注意的是insert
在插入一个字符的时候我们需要传三个参数,或者传迭代器也就是(6)
- s.insert(0,1,'+'); //(5)
- s.insert(s.begin(), '+'); //(6)
当erasr没有第二个参数时,默认为删除到字符串最后
函数名称 | 作用 |
operator+ | 字符串添加,不改变原来的字符串 |
operator>> | 输入运算符重载 |
operator<< | 输出运算符重载 |
getline | 获取一行字符串 |
relational operators | 比较大小 |
- #include
- int main()
- {
- string s = "hello ";
- cout << s << endl;
- cout << "------------------------------------------------" << endl;
- string s2 = s + "C++";
- cout << s << endl;
- cout << s2 << endl;
- cout << "------------------------------------------------" << endl;
- string s4;
- getline(cin, s4);
- cout << s4 << endl;
- cout << "------------------------------------------------" << endl;
- return 0;
- }
getline主要是解决cin遇到空格就停止读取的问题
这些是比较常见的string接口,当然还有很多接口
具体介绍,大家可以看看官网 https://cplusplus.com/
下面代码是有问题的
- class String
- {
- public:
- /*String()
- :_str(new char[1])
- {*_str = '\0';}
- */
- //String(const char* str = "\0") 错误示范
- //String(const char* str = nullptr) 错误示范
- String(const char* str = "")
- {
- // 构造String类对象时,如果传递nullptr指针,可以认为程序非
- if (nullptr == str)
- {
- assert(false);
- return;
- }
- _str = new char[strlen(str) + 1];
- strcpy(_str, str);
- }
- ~String()
- {
- if (_str)
- {
- delete[] _str;
- _str = nullptr;
- }
- }
- private:
- char* _str;
- };
- // 测试
- void TestString()
- {
- String s1("hello bit!!!");
- String s2(s1);
- }
代码仅供参考
- class string
- {
- friend ostream& operator<<(ostream& out, const string& s);
- friend istream& operator>>(istream& in, string& s);
- public:
- typedef char* iterator;
-
- string(const char* str = "")
- :_size(strlen(str))
- ,_capacity(_size)
- {
- _str = new char[_capacity + 1];
- strcpy(_str, str);
- }
- string(const string& s)
- {
- char* tmp = new char[_capacity + 1];
- strcpy(tmp, s._str);
- _str = tmp;
- _size = s._size;
- _capacity = s._capacity;
- }
-
- ~string()
- {
- delete[] _str;
- _str = nullptr;
- _size = _capacity = 0;
- }
- iterator begin()
- {
- return _str;
- }
- iterator end()
- {
- return _str + _size;
- }
- const iterator begin()const
- {
- return _str;
- }
- const iterator end()const
- {
- return _str + _size;
- }
- void reserve(size_t n)
- {
- if(n>_capacity)
- {
- char* tmp = new char[n+1];
- strcpy(tmp,_str);
- delete[] _str;
- _str = tmp;
- _capacity = n;
- }
- }
- void push_back(char c)
- {
- if (_size == _capacity)
- {
- reserve(_capacity == 0 ? 4 : _capacity * 2);
- }
- _str[_size] = c;
- _size++;
- _str[_size] = '\0';
- }
- string& operator+=(char c)
- {
- push_back(c);
- return *this;
- }
- void append(const char* str)
- {
- size_t len = strlen(str);
- if (_size + len > _capacity)
- {
- reserve( _size + len );
- }
- strcpy(_str + _size, str);
- _size += len;
- }
- string& operator+=(const char* str)
- {
- append(str);
- return *this;
- }
- void clear()
- {
- _str[0] = '\0';
- _size = 0;
- }
- void swap(string& s)
- {
- std::swap(_str, s._str);
- std::swap(_size, s._size);
- std::swap(_capacity, s._capacity);
- }
- string substr(size_t pos,size_t len = npos)
- {
- string s;
- int a = pos;
- if (len == npos || len >= _size)
- {
- len = _size - pos;
- s.reserve(len);
- for (int i = pos; i < _size; i++)
- {
- s += _str[i];
- }
- }
- else
- {
- s.reserve(len);
- for (int i = pos; i < pos + len; i++)
- {
- s += _str[i];
- }
- }
- return s;
- }
- string& insert(size_t pos,size_t len,char c)
- {
- assert(pos <= _size);
- if (_size + len > _capacity)
- {
- reserve(_size + len);
- }
- int a = _size;
- while (a >= (int)pos)
- {
- _str[a + len] = _str[a];
- a--;
- }
- int i = pos;
- while (i < pos+len)
- {
- _str[i] = c;
- i++;
- }
- _size++;
- return *this;
- }
- string& insert(size_t pos, const char* str)
- {
- int len = strlen(str);
- assert(pos <= _size);
- if (_size + len > _capacity)
- {
- reserve(_size + len);
- }
- int a = _size;
- while (a >= (int)pos)
- {
- _str[a + len] = _str[a];
- a--;
- }
- int i = pos;
- int j = 0;
- while (i < pos + len)
- {
- _str[i] = str[j];
- i++;
- j++;
- }
- _size += len;
- return *this;
- }
- size_t size()const
- {
- return _size;
- }
- size_t capacity()const
- {
- return _capacity;
- }
- const char*c_str()const
- {
- return _str;
- }
-
- bool empty()const
- {
- return _size == 0;
- }
- void resize(size_t n, char c = '\0')
- {
- if (n < _size)
- {
- _str[n] = '\0';
- _size = n;
- }
- if (n > _size)
- {
- reserve(n);
- while (_size < n)
- {
- _str[_size] = c;
- _size++;
- }
- _str[_size] = '\0';
- }
- }
-
- char operator[](size_t index)
- {
- assert(index < _size);
- return _str[index];
- }
- const char& operator[](size_t index)const
- {
- assert(index < _size);
- return _str[index];
- }
- bool operator<(const string& s)
- {
- int num1 = 0;
- int count = 0;
- while (num1<_size && num1 < s._size)
- {
- if (_str[num1] > s._str[num1])
- return false;
- if (_str[num1] < s._str[num1])
- count++;
- num1++;
- }
- if (s._str[num1] != '\0')
- return true;
- if (count == 0)
- return false;
- return true;
- }
- bool operator==(const string& s)
- {
- int num1 = 0;
- while (num1 < _size && num1 < s._size)
- {
- if (_str[num1] != s._str[num1])
- {
- return false;
- }
- num1++;
- }
- if (s._str[num1] != '\0'||_str[num1]!='\0')
- return false;
- return true;
- }
- bool operator<=(const string& s)
- {
- return *this == s || *this < s;
- }
- bool operator>(const string& s)
- {
- return !(*this <= s);
- }
- bool operator>=(const string& s)
- {
- return *this == s || *this > s;
- }
-
- bool operator!=(const string& s)
- {
- return !(*this== s);
- }
- // 返回c在string中第一次出现的位置
- size_t find(char c, size_t pos = 0) const
- {
- int a = pos;
- while (a < _size)
- {
- if (_str[a] == c)
- return a;
- a++;
- }
- return -1;
- }
- // 返回子串s在string中第一次出现的位置
- size_t find(const char* s, size_t pos = 0) const
- {
- int a = pos;
- int i = 0;
- while (a < _size)
- {
- int j = a;
- while (_str[j] == s[i])
- {
- i++;
- j++;
- if (s[i] == '\0')
- return a;
- }
- i = 0;
- a++;
- }
- }
- // 删除pos位置上的元素
- string& erase(size_t pos, size_t len)
- {
- if (len >= _size)
- {
- _str[pos] = '\0';
- _size = pos;
- return *this;
- }
- int a = pos;
- while (a+len <= _size)
- {
- _str[a] = _str[a + len];
- a++;
- }
- _size -= len;
- return *this;
- }
- const static size_t npos;
- private:
- char* _str;
- size_t _size;
- size_t _capacity;
- };
- const size_t string::npos = -1;
- ostream& operator<<(ostream& out, const string& s)
- {
- for (auto a : s)
- {
- cout << a;
- }
- return cout;
- }
- istream& operator>>(istream& in, string& s)
- {
- s.clear();
- char ch;
- ch = in.get();
- while (ch!='\n')
- {
- s += ch;
- ch = in.get();
- }
- return in;
- }