手机版网站做一下多少钱,wordpress 视频网站,贵阳最新消息今天,班级网站制作建设的设计和作用一.string介绍
1. string是表示字符串的字符串类#xff0c;对C语言的字符串指针进行了包装。
2. 该类的接口与常规容器的接口基本相同#xff0c;有增删查改等#xff0c;再添加了一些专门用来操作string的常规操作。
二.成员变量
创建string类的时候要在自己的命名空间…一.string介绍
1. string是表示字符串的字符串类对C语言的字符串指针进行了包装。
2. 该类的接口与常规容器的接口基本相同有增删查改等再添加了一些专门用来操作string的常规操作。
二.成员变量
创建string类的时候要在自己的命名空间内不然会和std的string重名了。函数都写在这个空间里我的取名为qf你们可以自己取喜欢的名字。
namespace qf
{class string{private:char* _str;int _size;//有效字符个数int _capacity;//有效空间 \0不算有效空间const static size_t npos;};const size_t string::npos -1;//初始化
}
npos 会初始化成 -1转化成size_t的话会变成2^32 - 1;很大很大所以一般npos用于表示无穷
三.构造函数析构函数
string(const char* str )
{//开辟空间,小于4个就给4的空间。int len strlen(str) ;if (len 4){_capacity 4;}else{_capacity len;}_size len;// \0不算有效字符所以要多整一个空间_str new char[_capacity 1];strcpy(_str, str);
}//拷贝构造
string(string s)//记得加上引用不然一直会进入拷贝死循环。
{int size s.size();if (size 4){_capacity 4;}else{_capacity size;}_size size;//\0不算有效字符所以要多整一个空间_str new char[_capacity 1];strcpy(_str, s.c_str());
}//析构函数
~string()
{//如果_str是空那就不用deleteif (_str){delete[] _str;}_size 0;_capacity 0;
}
有些朋友可能会感到奇怪因为编译器其实会自动实现一个拷贝构造但系统实现的拷贝构造内容完全一样char* _str 这个指针储存的地址都是一样的。例如 string a(b);a由b拷贝来的改变a的字符串b的字符串也会变。我们要让它们独立。所以我们要重新开一份相同大小的空间再去拷贝这就是深浅拷贝的区别。系统自动生成的拷贝构造是浅拷贝我们上面写的是深拷贝。
四.简单的接口
//返回字符串长度
size_t size()const
{return _size;
}//返回c语言的字符串
char* c_str()const
{return _str;
}//返回容量
size_t capacity()const
{return _capacity;
}
//判断是否为空
bool empty()const
{return 0 _size;
}五.尾上插入字符与字符串
//重新分配capacity大小
void reserve(size_t capacity)
{_capacity capacity;//多开一个空间是因为为了放\0的char* tem new char[_capacity 1];strcpy(tem, _str);delete[] _str;_str tem;
}//插入单个字符
void push_back(char ch)
{//检查容量是否满了if (_size _capacity){reserve(2 * _capacity);}_str[_size] ch;_size;_str[_size] \0;
}
//插入字符串
void append(const char* str)
{int len strlen(str);//检查容量是否足够if (_capacity len _size){reserve(len _size);//在里面会扩容且改变capacity的值}strcpy(_str _size, str);//将传来的字符串加到原来的字符串后面_size len;
}六.指定插入与删除
//在pos位置加上字符串pos后面的字符串向后移
string inserter(size_t pos, const char *str)
{assert(str);if (pos _size)return *this;else{int len strlen(str);//检测容量是否足够if (_size len _capacity)reserve(_size len);//挪数据,//如果pos 0那么i 要等于-1才能结束// size_t 和int 比较会自动转换成容量大的所以// -1 0 会死循环,所以要将pos强制类型转化成intfor (int i _size - 1; i (int)pos; i--){_str[i len] _str[i];}//将字符串拷贝到pos后面for (int i 0; i len; i){_str[pos] str[i];pos;}_size len;_str[_size] \0;}
}//在pos位置删n个字符。如果只传pos说明后面都要删光光
string erase(size_t pos ,size_t n npos)
{// 1.pos size 那就不删直接返回if (pos _size);// 2.n pos size 那就pos后面可以删完else if (n pos _size){_size pos;_size \0;}// 3.pos n size 那就pos n后面的元素移到pos的位置else{for (int i pos n; i _size; i){_str[pos] _str[i];pos;}_size - n;_str[_size] \0;}return *this;
}//截取n个字符然后后面加给定的字符
//有三种情况
//1. n size
//2. size n capacity;
//3. n capacity 第二和第三一样,加个扩容就行
string resize(size_t n, char ch \0)
{//1.if (n _size){_size n;_str[_size] \0;return *this;}//2 and 3if (n _capacity){reserve(n);}for (int i _size; i n; i){_str[i] ch;}_size n;_str[_size] \0;return *this;
}
七.运算符重载
//要重载俩
//这个返回的是可以改的,
//比如 string s(abcd); s[0] 1;
//s内容就变成了bbcd;
char operator[](size_t i)
{return _str[i];
}//这个返回的是不可改的,
//因为用上面的权限会被放大。
const char operator[](size_t i)const
{return _str[i];
}string operator (const char ch)
{push_back(ch);return *this;
}string operator (const char* str)
{append(str);return *this;
}bool operator (const string s)const
{int ret strcmp(_str, s.c_str());return ret 0;
}bool operator (const string s)const
{int ret strcmp(_str, s.c_str());return ret 0;
}bool operator (const string s)const
{//直接复用上面return *this s || *this s;
}bool operator (const string s)const
{return !(*this s);
}bool operator (const string s)const
{return !(*this s);
}
八.查找字符和字符串
//注意点就是要返回npos(2^32 - 1)然后利用接口strstr
//返回npos说明没找到
size_t find(const char* str)const
{char* p strstr(_str, str);if (p nullptr)return npos;elsereturn p - _str;//俩个指针相减刚好是这个的角标}size_t find(char ch)const
{for (int i 0; i _size; i){if (_str[i] ch){return i;}}return npos;
}九.输入输出重载
ps:1.这个要放在命名空间外面返回以后还能输出其他的内容所以要重载std::ostream和std::istream。
2.不能放类里面 的左操作数一定要是std::ostream第一个参数默认左操作数。 std::ostream operator(std::ostream out, const string s){for (int i 0; i s.size(); i){out s[i];}return out;}std::istream operator(std::istream in, string s){while (1){//这里不能用cout ch;//因为cout ch;读到 和 \n直接跳过了;char ch in.get();if (ch || ch \n)break;elses ch;}return in;}
}十.迭代器的实现
C中迭代器和指针很像为什么要有迭代器呢 当然是因为方便操作C中有很多容器遍历方式各有不同为了让他们一样就产生了迭代器string类的迭代器就是指针。但其他类可能是一些更复杂的自定义类型。 typedef char* iterator;const typedef char* const_iterator;const_iterator begin()const{return _str;}const_iterator end()const{return _str _size;}iterator begin(){return _str;}iterator end(){return _str _size;}
迭代器的使用如下
qf::string::iterator it s.begin();while (it ! s.end()){cout *it ;it;}cout endl;
范围for就是利用了迭代器如下代码编译器会转化成上面的。 for (auto e : s){cout e ;}cout endl;
十一.拷贝构造和operator优化
void swap(string s)
{//因为在qf命名空间内所以调用swap要说明是std的std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);
}//现代写法
string(const string s):_str(nullptr)
{string tem(s._str);swap(tem);
}string operator(string s)
{swap(s);return *this;
}
很简洁对不对。利用了临时变量出了作用域会自动销毁并且swap交换时会帮你new好空间。极其方便。
十二.总代码
#includeiostream
#includeassert.h
namespace qf
{class string{public://迭代器typedef char* iterator;const typedef char* const_iterator;const_iterator begin()const{return _str;}const_iterator end()const{return _str _size;}iterator begin(){return _str;}iterator end(){return _str _size;}//构造函数string(const char* str ){//开辟空间int size strlen(str) ;if (size 4){_capacity 4;}else{_capacity size;}_size size;//\0不算有效字符所以要多整一个空间_str new char[_capacity 1];strcpy(_str, str);}string(char ch){_str new char[2];_size 1;_capacity 1;_str[0] ch;}//古代写法//string(string s)//{// int size s.size();// if (size 4)// {// _capacity 4;// }// else// {// _capacity size;// }// _size size;// //\0不算有效字符所以要多整一个空间// _str new char[_capacity 1];// strcpy(_str, s.c_str());//}void swap(string s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}//现代写法string(const string s):_str(nullptr){string tem(s._str);swap(tem);}string operator(string s){swap(s);return *this;}char* c_str()const{return _str;}//析构函数~string(){if (_str){delete[] _str;}_size 0;_capacity 0;}size_t size()const{return _size;}size_t capacity()const{return _capacity;}//要重载俩因为这个是可读可写char operator[](size_t i){return _str[i];}//这个只能读一般打印的时候用const char operator[](size_t i)const{return _str[i];}bool empty()const{return 0 _size;}void push_back(char ch){if (_size _capacity){reserve(2 * _capacity);}_str[_size] ch;_size;_str[_size] \0;}void append(const char* str){int len strlen(str);if (_capacity len _size){reserve(len _size);}strcpy(_str _size, str);_size len;}string operator (const char ch){push_back(ch);return *this;}bool operator (const string s)const{int ret strcmp(_str, s.c_str());return ret 0;}bool operator (const string s)const{int ret strcmp(_str, s.c_str());return ret 0;}bool operator (const string s)const{//直接复用上面return *this s || *this s;}bool operator (const string s)const{return !(*this s);}bool operator (const string s)const{return !(*this s);}string operator (const char* str){append(str);return *this;}//重新分配capacity大小void reserve(size_t capacity){_capacity capacity;char* tem new char[_capacity 1];strcpy(tem, _str);delete[] _str;_str tem;}//有三种情况。截取n个字符然后后面加给定的字符//1. n size //2. size n capacity;//3. n capacity 第二和第三一样加个扩容就行string resize(size_t n, char ch \0){//1.if (n _size){_size n;_str[_size] \0;return *this;}//2 and 3if (n _capacity){reserve(n);}for (int i _size; i n; i){_str[i] ch;}_size n;_str[_size] \0;return *this;}//在指定位删n个string erase(size_t pos ,size_t n npos){// 1.pos size 那就不删直接返回if (pos _size);// 2.n pos size 那就pos后面可以删完else if (n pos _size){_size pos;_size \0;}// 3.pos n size 那就pos n后面的元素移到pos的位置else{for (int i pos n; i _size; i){_str[pos] _str[i];pos;}_size - n;_str[_size] \0;}return *this;}//在指定位置插入string inserter(size_t pos, const char *str){assert(str);if (pos _size)return *this;else{int len strlen(str);if (_size len _capacity)reserve(_size len);//挪数据,如果pos 0那么i 要等于-1才能结束// size_t 和int 比较会自动转换成容量大的所以// -1 0 会死循环,所以要强制类型转化for (int i _size - 1; i (int)pos; i--){_str[i len] _str[i];}// strncpy(_str _size, str, len);for (int i 0; i len; i){_str[pos] str[i];pos;}_size len;_str[_size] \0;}}//注意点就是要返回npos然后利用接口strstrsize_t find(const char* str)const{char* p strstr(_str, str);if (p nullptr)return npos;elsereturn p - _str;}size_t find(char ch)const{for (int i 0; i _size; i){if (_str[i] ch){return i;}}return npos;}private:char* _str;int _size;//有效字符int _capacity;//有效空间 \0不算有效哦const static size_t npos;};const size_t string::npos -1;std::ostream operator(std::ostream out, const string s){for (int i 0; i s.size(); i){out s[i];}return out;}std::istream operator(std::istream in, string s){while (1){char ch in.get();if (ch || ch \n)break;elses ch;}return in;}
}ps仅供参考有问题可以一起交流加油共勉