深圳网站搜索优化,网络推广方案的基本思路,网站根目录在哪儿,东莞站福公司工资string类的模拟 目录 string类的模拟功能介绍各功能的实现类的构造函数#xff0c;拷贝构造函数#xff0c;析构函数迭代器的实现string的内部容量访问成员函数string的修改成员函数string类的相关联函数string类的输入输出友元 汇总string功能的实现汇总测试代码 功能介绍
…string类的模拟 目录 string类的模拟功能介绍各功能的实现类的构造函数拷贝构造函数析构函数迭代器的实现string的内部容量访问成员函数string的修改成员函数string类的相关联函数string类的输入输出友元 汇总string功能的实现汇总测试代码 功能介绍
namespace bit
{class string{private:char* _str;size_t _capacity;size_t _size;public:typedef char* iterator;typedef const char*const_iterator;static const int npos;public:string(){}~string(){}//各个成员函数的实现}
}
const int bit::string::npos -1;实现思路
迭代器的实现{typefef 一个指针模拟指针这里用的指针}先实现构造函数{注意初始化的动态内存开辟} 这里还要注意如何实现缺省值赋予nullptr? 赋予空 拷贝构造函数{开辟字符串长度大小的空间strcpy内存复制}c_str(){返回数组内容}运算符重载 拷贝 {设计现代写法利用临时变量在此函数调用其他已经实现的构造函数与临时变量交换实现拷贝。第二种普遍想法开同等大小的空间注意实际多出1来存‘/0’内存复制函数}析构函数{释放空间成员变量归零}扩容函数reserve{若空间不足new思想和栈链表开空间一样临时变量来做缓冲}调整字符串大小函数resize{若参数的长度小于当前string的长度便将[n]位置的数据赋予‘/0’
修改 尾插push_pack{判断扩容尾部插入字符} append{扩容复制拷贝字符串} 插入函数insert字符串字符{扩容对pos位置的字符往后排在pos位置插入字符或者插入字符串strncpy不会复制空字符} 擦除erase{在pos位置删除之后的字符串} 交换swap{交换函数模板各成员变量都交换} 查找find字符字符串 判断pos位置的合理性循环比较相等 字符串需要用到库函数strstr 获取从某个位置开始的字符串substr{临时变量string来储存pos之后的字符串注意的是谨慎判断pos与_size和npos之间的关系大小 清除clear{_str[0]置空字符大小变为零}[ ]
各功能的实现
类的构造函数拷贝构造函数析构函数
其中涉及到库函数内存拷贝的4个库函数 void * memcpy ( void * destination, const void * source, size_t num ); 返回值是destination此函数是复制内存块将字节数的值从源指向的位置直接复制到目标指向的内存块不检查是否source是否有终止符号 void * memmove ( void * destination, const void * source, size_t num ); 返回值是destination此函数是移动内存块。将 num 字节的值从源指向的位置复制到目标指向的内存块。复制就像使用中间缓冲区一样进行从而允许目标和源重叠 char * strcpy ( char * destination, const char * source ); 返回值是destination此函数的复制包括结尾的‘/0’ char * strncpy ( char * destination, const char * source, size_t num ); 返回值是 destination此函数是复制字符串复制n个字符至des 构造拷贝构造
//不建议的写法
string():_str(new char[1]),_capacity(0),_size(0)
{_str[0] /0;
}
string(const char* s):_capacity(strlen(s))
{_str new char[_capacity 1];_size _capacity;strcpy(_str, s);
}string(const char* str ):_capacity(strlen(str))//缺省值不给字符也就是空字符串
{_str new char[_capacity 1];//多开一个空间给‘/0’_size _capacity;strcpy(_str, str);
}string(const string s)
{_str new char[s._capacity 1];_capacity s._capacity;_size s._size;strcpy(_str, s._str);
}string operator(const string s)
{_str new char[s._capacity 1];_capacity s._capacity;_size s._size;strcpy(_str, s._str);return *this;
}现代写法在实现了一个构造函数在此基础上调用构造函数来实现另一个构造函数
string operator(const string s)
{//_str new char[s._capacity 1];//_capacity s._capacity;//_size s._size;//strcpy(_str, s._str);//return *this;string tem(s);swap(tem);//这里交换要注意一开始给成员变量初始值return *this;
}注意交换后临时开辟的变量若对成员变量不初始化临时变量就会变成野指针在析构可能出现异常 析构函数
~string()
{delete[] _str;_str nullptr; _size _capacity 0;
}迭代器的实现
string的迭代器这里用的是指针实现,迭代器用指针是比较容易实现的只需返回指针即可
// iterator
typedef char* iterator;
typedef const 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;
}实现了迭代器那么for循环也可以使用其实for循环的本质也是用的迭代器的原理表面是任意变量的拷贝底层是迭代器的转换 void test(){bit::string s2(abcdefg);bit::string::iterator begin s2.begin();while (begin ! s2.end()){(*begin);cout *begin;begin;}cout endl;for (auto ch : s2){cout ch;}}string的内部容量访问成员函数
string大小容量的实现
// capacity
size_t size()const
{return _size;
}size_t capacity()const
{return _capacity;
}bool empty()const
{return _size 0;
}在实现resize和reserve成员函数应该充分了解他们的底层逻辑resize只增容不缩容若参数大于当前容量扩容并且以参数char c来填充扩容后的内容。 reserve是用来为其他成员函数扩容的不缩容所有扩容函数构造函数都会多开一个空间来留个‘\0’这个空字符
void resize(size_t n, char c \0)
{if (n _capacity){_str[n] \0;_size n;}else {reserve(n);for (size_t i _size;i n; i) {_str[i] c;}_str[n] \0;_size n;}
}void reserve(size_t n)
{if (n _capacity){char* tem new char[n 1];//多开一个空间strcpy(tem, _str);delete[] _str;_str tem;_capacity n;}
}string的修改成员函数
string的修改成员函数 modify//void push_back(char c);//string operator(char c);//void append(const char* str);//string operator(const char* str);//void clear();//void swap(string s);//const char* c_str()const
实现插入增加的原理是一样的 先判断是否扩容然后插入字符或者strcpy插入字符串 void push_back(char c){if (_size _capacity){reserve(_capacity 0 ? 4 : 2 * _capacity);}_str[_size] c;_str[_size] \0;}string operator(char c){push_back(c);return *this;}void append(const char* str){int len strlen(str);if(_sizelen_capacity||_size _capacity - len)//最大值溢出问题{reserve(_size len);}strcpy(_str _size, str);_size _size len;}string operator(const char* str){append(str);return *this;}string operator(const string s){reserve(_size s._size);strcpy(_str _size, s._str);_size _size s._size;return *this;}
清除函数和交换函数也是很容易实现的 清除成员函数不需要考虑释放空间只需要将第一个有效字符设置为’\0’即可 而交换函数可以利用库函数的模板来实现将各个成员变量进行交换 void clear(){_str[0] \0;_size 0;}void swap(string s){std::swap(_str, s._str);std::swap(_capacity, s._capacity);std::swap(_size, s._size);}在swap中应用中还是不太普遍需要s1.swap(s2) ,看起来还是不够使用也不像库函数那样所以可以再重载一个全局函数这里注意是在类域外全局处重载函数
void swap(string s1, string s2)
{s1.swap(s2);
}返回字符串函数返回成员变量_str开辟空间的地址即可
const char* c_str()const{return _str;}string类的相关联函数
find成员函数的实现
// 返回c在string中第一次出现的位置
size_t find(char c, size_t pos 0) const
{//pos合理assert(pos _size);for (size_t i pos;i _size;i){if (_str[i] c)return i;}return npos;
}find的字符串的实现
这里用到了库函数strstr const char * strstr ( const char * str1, const char * str2 ); 此函数查找子字符串若匹配了返回指针不匹配返回空指针
// 返回子串s在string中第一次出现的位置
size_t find(const char* s, size_t pos 0) const
{assert(pos _size);char* ch strstr(_str, s);if (ch){//返回俩个指针的差值就是当前的位置return ch - _str;}else{return npos;}
}
insert插入函数的实现 在pos位置上插入字符c/字符串str并返回该字符的位置
string insert(size_t pos, char c)
{assert(pos _size);if (_size _capacity){reserve(_capacity 0 ? 4 : 2 * _capacity);}for (size_t i _size1;i pos;i--){_str[i] _str[i-1];}_str[pos] c;_size;return* this;
}string insert(size_t pos, const char* str)
{assert(pos _size);//和append实现思路一样size_t len strlen(str);if (_size _capacity - len || _sizelen _capacity )//最大值溢出的问题{reserve(_size len);}for (size_t i _size len;i pos len -1 ;i--){_str[i] _str[i - len]; }strncpy(_str pos, str,len);_size _size len;return *this;
}erase擦除函数将pos位置及后面的总计len个字符擦除
// 删除pos位置上的元素并返回该元素的下一个位置
string erase(size_t pos, size_t lennpos)
{assert(pos _size);//不用取等最后一个_size位置是不能擦除的\0if (len npos || len _size - pos-1){_str[pos] \0;_size pos;}else{strcpy(_str pos, _str pos len);_size - len;}return *this;
}string比较函数的实现可以借助库函数的strcmp int strcmp ( const char * str1, const char * str2 ); 此函数将俩个字符串进行比较相等返回0 str1小于str2返回一个负数反之
string类的输入输出友元
注意此类函数的实现都是基于类域的外面也就是全局
输出流cout
输入流cin
输入流的实现思路有很多种优化。 很普遍的实现是将输入的字符一个一个塞进string的实例中一边塞一边扩容 获取输入字符可以借助库函数get() //istream operator(istream _cin, bit::string s)//{// //清空当前的内容// s.clear();// char ch;// ch _cin.get();// s.reserve(64);// while (ch ! ch ! \n)//当遇到enter和空格就停止获取// {// s.push_back(ch);// ch _cin.get();// }// return _cin;//}优化用一个大小固定的临时数组来存储当前输入字符当输入结束或者数组已满就赋值给string将数组的有效字符重置继续下一轮如果还有输入字符
istream operator(istream _cin, bit::string s)
{s.clear();char ch;ch _cin.get();char c[128];size_t i 0;while (ch ! ch ! \n){c[i] ch;//当数组满时if (i 127){c[127] \0;//注意在这个位置赋予结束字符否则会出现随机字符s c;i 0;}ch _cin.get();}if (i 0){c[i] \0;//注意先给结束字符否则会将上一次循环的已无效字符或随机字符进入strings c;}return _cin;
}汇总
string功能的实现汇总
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#includeiostream
#includeassert.h
using namespace std;namespace bit
{class string{private:char* _str nullptr;size_t _capacity 0;size_t _size 0;friend ostream operator(ostream _cout, const bit::string s);friend istream operator(istream _cin, bit::string s);public:typedef char* iterator;typedef const char*const_iterator;static const int npos;public://string() :_str(new char[1]), _capacity(0), _size(0)//{// _str[0] /0;//}//string(const char* s) :_capacity(strlen(s))//{// _str new char[_capacity 1];// _size _capacity;// strcpy(_str, s);//}string(const char* str ):_capacity(strlen(str))//缺省值不给字符也就是空字符串{_str new char[_capacity 1];//多开一个空间给‘/0’_size _capacity;strcpy(_str, str);}string(const string s){_str new char[s._capacity 1];_capacity s._capacity;_size s._size;strcpy(_str, s._str);}string operator(const string s){//_str new char[s._capacity 1];//_capacity s._capacity;//_size s._size;//strcpy(_str, s._str);//return *this;string tem(s);swap(tem);//这里交换要注意一开始给成员变量初始值return *this;}//俩种现代写法在完成其他成员函数的基础上~string(){delete[] _str;_str nullptr; _size _capacity 0;}// iteratorconst_iterator begin()const{return _str;}const_iterator end()const{return _str _size;}iterator begin(){return _str;}iterator end(){return _str _size;}// modifyvoid push_back(char c){if (_size _capacity){reserve(_capacity 0 ? 4 : 2 * _capacity);}_str[_size] c;_str[_size] \0;}string operator(char c){push_back(c);return *this;}void append(const char* str){size_t len strlen(str);if (_size _capacity - len||_sizelen_capacity)//最大值溢出问题{reserve(_size len);}strcpy(_str _size, str);_size _size len;}string operator(const char* str){append(str);return *this;}string operator(const string s){reserve(_size s._size);strcpy(_str _size, s._str);_size _size s._size;return *this;}void clear(){_str[0] \0;_size 0;}void swap(string s){std::swap(_str, s._str);std::swap(_capacity, s._capacity);std::swap(_size, s._size);}const char* c_str()const{return _str;}// capacitysize_t size()const{return _size;}size_t capacity()const{return _capacity;}bool empty()const{return _size 0;}void resize(size_t n, char c \0){if (n _capacity){_str[n] \0;_size n;}else {reserve(n);for (size_t i _size;i n; i) {_str[i] c;}_str[n] \0;_size n;}}void reserve(size_t n){if (n _capacity){char* tem new char[n 1];strcpy(tem, _str);delete[] _str;_str tem;_capacity n;}} accesschar operator[](size_t index){return *(_str index);}const char operator[](size_t index)const{return *(_str index);}//relational operatorsbool operator(const string s){if (strcmp(c_str(), s.c_str()) 0){return true;}return false;}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);}bool operator(const string s){if (strcmp(c_str(), s.c_str()) 0)return true;return false;}bool operator!(const string s){return !(*this s);}// 返回c在string中第一次出现的位置size_t find(char c, size_t pos 0) const{//pos合理assert(pos _size);for (size_t i pos;i _size;i){if (_str[i] c)return i;}return npos;}// 返回子串s在string中第一次出现的位置size_t find(const char* s, size_t pos 0) const{assert(pos _size);char* ch strstr(_str, s);if (ch){//返回俩个指针的差值就是当前的位置return ch - _str;}else{return npos;}} 在pos位置上插入字符c/字符串str并返回该字符的位置string insert(size_t pos, char c){assert(pos _size);if (_size _capacity){reserve(_capacity 0 ? 4 : 2 * _capacity);}for (size_t i _size1;i pos;i--){_str[i] _str[i-1];}_str[pos] c;_size;return* this;}string insert(size_t pos, const char* str){assert(pos _size);//和append实现思路一样size_t len strlen(str);if (_size _capacity - len || _sizelen _capacity )//最大值溢出的问题{reserve(_size len);}for (size_t i _size len;i pos len -1 ;i--){_str[i] _str[i - len]; }strncpy(_str pos, str,len);_size _size len;return *this;}// 删除pos位置上的元素并返回该元素的下一个位置string erase(size_t pos, size_t lennpos){assert(pos _size);//不用最后一个pos是不能擦除的‘\0if (len npos || len _size - pos-1){_str[pos] \0;_size pos;}else{strcpy(_str pos, _str pos len);_size - len;}return *this;}};const int bit::string::npos -1;void swap(string s1, string s2){s1.swap(s2);}ostream operator(ostream _cout, const bit::string s){for (auto ch : s){_cout ch;}return _cout;}//istream operator(istream _cin, bit::string s)//{// //清空当前的内容// s.clear();// char ch;// ch _cin.get();// s.reserve(64);// while (ch ! ch ! \n)//当遇到enter和空格就停止获取// {// s.push_back(ch);// ch _cin.get();// }// return _cin;//}istream operator(istream _cin, bit::string s){s.clear();char ch;ch _cin.get();char c[128];size_t i 0;while (ch ! ch ! \n){c[i] ch;//当数组满时if (i 127){c[127] \0;//注意在这个位置赋予结束字符否则会出现随机字符s c;i 0;}ch _cin.get();}if (i 0){c[i] \0;//注意先给结束字符否则会将上一次循环的已无效字符或随机字符进入strings c;}return _cin;}
}测试代码
#includeimitate_string.hvoid test1()
{//bit::string s1;bit::string s2(abcdefg);bit::string::iterator begin s2.begin();while (begin ! s2.end()){(*begin);cout *begin;begin;}cout endl;for (auto ch : s2){cout ch;}//cout s2[2] endl;
}void test2()
{bit::string s1(abcdefg);//s1.resize(4);//s1.resize(5, i);//cout s1.c_str() endl;//bit::string s2;//s2.resize(10, 1);//s1.push_back(2);s1.append(you donot know .... ,just nothing);cout s1.c_str() endl;
}void test3()
{bit::string s1;bit::string s2(ijustlovebutitwillbenothing);bit::string s3 s2;s3 s2;s2 itjustnothing OK;cout s3.c_str() endl;cout s2.c_str() endl;s1.swap(s2);cout s1.c_str() endl;s1.clear();cout s1.c_str() endl;
}void test4()
{bit::string s1(abadfadf);//bit::string s2(it just be ok,i think i only gave up);//swap(s1, s2);//bit::string s3 s2;//cout s1.c_str() endl s2.c_str() s3.c_str() endl;
}void test5()
{bit::string s1(abadfadf);bit::string s2(ac);size_t i s1.find(b);//s1.insert(i, 5);//s2.insert(0,12345);s1.erase(i, 2);s2.erase(0);s2 s1;s2.erase(3);cout s1.c_str() endl;cout s2.c_str();
}void test6()
{bit::string s1(qwert);bit::string s2(qwert);bit::string s3(qert);//cout (s1 s2) endl;//0//cout (s1 s2) endl;//1//cout (s3 s2) endl;//1cout s1 endl;cin s2;cout s2;bit::swap(s2, s1);cout s1;}int main()
{//using namespace bit;//bit::string s1();//bit::string s2(abcdefg);//test5();//test6();bit::string s1(abka);cin s1;//s1.append(ab);cout s1;return 0;
}