string类是表示字符串的字符类,是一块连续的空间存储字符串,并且可以通过统一接口,实现插入,删除,尾插,查找,迭代器遍历等一系列操作。
#define _CRT_SECURE_NO_WARNINGS 1;
#include
#include
using namespace std;
namespace xff {
class string {
public:
typedef char* iterator;
//迭代器
iterator begin() {
return _str;
}
iterator rbegin() { //最后一个字符
return _str+_size-1;
}
iterator end() {
return _str + _size;
}
iterator rend() { //第一个字符的前一个
return --_str;
}
//构造函数
string(const char* str=""){
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity + 1];
strcpy(_str, str);
}
//拷贝构造
string(const string& s)
:_str(nullptr)
,_size(0)
,_capacity(0)
{
string tmp(s._str);
this->swap(tmp);
}
//析构函数
~string(){
if (_str) {
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
}
//=
string operator=(string s) {
this->swap(s);
return *this;
}
//size
size_t size()const {
return _size;
}
//capacity
size_t capacity()const {
return _capacity;
}
//[]
char& operator[](size_t index) {
assert(index < _size);
return _str[index];
}
//[]const
const char& operator[](size_t index)const {
assert(index < _size);
return _str[index];
}
//c_str
const char* c_str() {
return _str;
}
void swap( string& s) {
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
//判断是否为空
bool empty() {
if (_size == 0) {
return true;
}
return false;
}
//reserve预留空间
void reserve(size_t num) {
if (num > _capacity) {
char* newstr = new char[num + 1];
strcpy(newstr, _str);
delete[] _str;
_str = newstr;
_capacity = num;
}
}
//push_back
void push_back(const char ch) {
if (_size == _capacity) {
size_t newcapacity = _capacity == 0 ? 2 : 2*_capacity;
reserve(newcapacity);
}
_str[_size++] = ch;
_str[_size] = '\0';
}
//operator+=()字符
string& operator+=(const char ch) {
this->push_back(ch);
return *this;
}
//operator+=()字符串
string& operator+=(const char* str) {
this->append(str);
return *this;
}
//append加字符串
void append(const char* str = "") {
size_t len = strlen(str);
if (len + _size > _capacity) {
/*size_t newcapacity = _capacity = len + _size;
char* newstr = new char[newcapacity + 1];
strcpy(newstr, _str);
delete[] _str;
_str = newstr;*/
reserve(len + _size);
}
strcpy(_str + _size, str);
_size += len;
}
//将有效字符串置0
void clear() {
_size = 0;
}
//resize重置有效字符个数
//小于有效字符个数就截
//大于补字符
void resize(size_t num, const char ch ='\0') {
if (num <= _size) {
_size = num;
}
else {
while (num - _size > 0) {
push_back(ch);
}
}
}
//插入单个字符
string& insert(size_t pos, const char ch) {
assert(pos < _size);
size_t size = _size;
if (_size == _capacity) {
size_t newcapacity = _capacity == 0 ? 2 : 2 * _capacity;
reserve(newcapacity);
}
while (pos<=size)
{
_str[size+1] = _str[size];
--size;
}
_str[pos] = ch;
++_size;
return *this;
}
//插入字符串
string& insert(size_t pos, const char* str) {
assert(pos <= _size);
size_t len = strlen(str);
if (_size+len > _capacity) {
reserve(_size + len);
}
int size = _size;
while ((int)pos <= size)//无符号-1是最大值,容易死循环
{
_str[size+len] = _str[size];
--size;
}
strncpy(_str + pos, str, len);//不要复制这个字符串尾部的空格,不然会覆盖移动的字符
_size += len;
return *this;
}
//删除
//大于等于pos到_size全删
//小于保留余下的,并且移动
string& erase(size_t pos,size_t len = npos) {
assert(pos < _size);
if (len>=_size-pos) {
_str[pos] = '\0';
_size = pos;
}
else
{
size_t i = pos+len;
while (i <= _size) {
_str[pos++] = _str[i++];
}
_size -= len;
}
return *this;
}
//find字符
size_t find(const char ch, size_t pos = 0) {
for (size_t i = pos; i < _size; ++i) {
if (_str[i] == ch) {
return i;
}
}
return npos;
}
//find字符串
size_t find(const char* str, size_t pos = 0) {
size_t len = strlen(str);
size_t dst = pos;
while (dst<_size) {
size_t src = 0;
pos = dst;
while (src<len&&_str[dst] == str[src]) {
++src;
++dst;
}
if (src == len) {
return pos;
}
++dst;
}
return npos;
}
bool operator==(const string& s) {
int ret = strcmp(_str, s._str);
if (ret == 0)
return true;
return false;
}
bool operator!=(const string& s) {
if (*this == s) {
return false;
}
return true;
}
bool operator>(const string& s) {
int ret = strcmp(_str, s._str);
if (ret > 0)
return true;
return false;
}
bool operator<(const string& s) {
int ret = strcmp(_str, s._str);
if (ret < 0)
return true;
return false;
}
bool operator>=(const string& s) {
if (*this < s) {
return false;
}
return true;
}
bool operator<=(const string& s) {
if (*this > s) {
return false;
}
return true;
}
const string substr(size_t pos, size_t n=npos) {
assert(pos < _size);
if (_size-pos<n) {
n = _size - pos;
}
char* newstr = new char[n + 1];
strncpy(newstr,_str + pos, n);
newstr[n] = '\0';
string s(newstr);
delete[] newstr;
return s;
}
private:
char* _str;
size_t _size;
size_t _capacity;
const static size_t npos;
};
const size_t string::npos = -1;
//重载<<
ostream& operator <<(ostream& _out, const string& s) {
for (size_t i = 0; i < s.size(); ++i) {
_out << s[i];
}
return _out;
}
//重载>>
istream& operator >>(istream& _in, string& s) {
while (1) {
char ch;
ch = _in.get();//输入的全接收,包括空格换行
if (ch == '\n') {
break;
}
else
{
s += ch;
}
}
return _in;
}
void test_String1() {
string s1;
//cout << s1 << endl;
string s2("hello");
//cout << s2 << endl;
//cout << s2.size() << " " << s2.capacity() << endl;
string s3;
s3 = s2;
cout << s3 << endl;
//cin >> s1;
//cout << s1 << " " <
s2 += "world";
cout << s2 << endl;
//迭代器访问
/*string::iterator it = s3.begin();
while (it != s3.end()) {
cout << *it << " ";
++it;
}
//for
for (auto e : s3) {
cout << e;
}*/
//s2.reserve(15);
//s2.reserve(3);
//cout << s2 << endl;
//cout << s2.size() << " " << s2.capacity() << endl;
//s3.resize(2);
//s3.resize(10);
//cout << s3 << endl;
//cout << s3.size() << " " << s3.capacity() << endl;
//s3.push_back(' ');
//cout << s3 << " ";
//cout << s3.size() << " " << s3.capacity() << endl;
//s3.append("world!");
//cout << s3 << " ";
//cout << s3.size() << " " << s3.capacity() << endl;
//s3.insert(0,"a");
//s3.insert(10, "abc");
//s3.insert(5,"a");
//s3.insert(1, 'a');
//s3.erase(2, 8);
//s3.erase(0);
//s3.erase(2, 2);
//cout << s3 << " ";
//cout << s3.size() << " " << s3.capacity() << endl;
//size_t num1 =s3.find('l');
//size_t num2 = s2.find("q",1);
//cout << num1 << " " << num2 << endl;
//cout << (s3>=s2)<< endl;
//cout << s3.substr(0, 8);
}
}
#include
int main() {
string s1("hello");
//cout<
//s1.insert(1,"ac");
//s1 += " world!";
//s1.push_back('!');
//s1.append("world!");
//s1.reserve(16);
//s1.resize(14,'a');
//s1.clear();
//s1.erase();
//cout << s1.substr(2);
//cout << s1 << endl;
//int num = s1.find("ello",0);
//cout << s1<<" "<
/*string::iterator it = s1.begin();
while (it != s1.end()) {
cout << *it;
++it;
}
cout << endl;
string::reverse_iterator rit = s1.rbegin();
while (rit != s1.rend()) {
cout << *rit;
++rit;
}*/
xff::test_String1();
system("pause");
return 0;
}
1.迭代器是c++ STL组件之一,是通用的遍历容器的方式,讲操作和底层实现分离,我们只需要调用对应的接口,就能实现对容器的遍历,针对不同的数据结构,有规范接口的作用。
2.实现插入删除等操作时,迭代器会失效,可能会出现重新分配内存空间的情况,迭代器就失效了。
3.clear()清除有效字符,容量不变。
4.reserve(size_t n)预留空间,不改变有效字符个数,扩容作用。
5.resize(size_t n,char ch)改变有效字符个数,小于有效字符个数就只保留到n,大于当前有效字符个数就补ch到n,前面的字符不变。
6.push_back(ch)尾部插入,不可以为空,可以插空格。
7.append(str) 尾插字符串。
8.erase(pos,n)从pos开始删除n个字符,默认是最大值size_t npos=-1。
9.insert(_size,str)只能插入字符串,并且小于等于_size。
10.find(str/ch,pos)从pos位置开始查找str/ch,找到返回第一个下标,找不到返回npos,rfind反向查找。
11.c_str() 返回C格式字符串,return _str.
12.substr(pos,n)从pos截取n个字符,默认npos,返回字符串。
13.getline string类的非成员函数,获取一行字符串,空格也接收,cin会将\n和空格,作为结束的标志。
14.reverse(s.begin(),s.end()),结尾是需要逆置的字符的下一个位置。
通过实现string类,我对string类的认识进一步加强,同时我也更加熟悉构造函数,析构函数等,同时对new,delete的使用更加熟练。初次学习,可能有不对的地方,希望大家指出来,共同进步。