字符串的表示字符序列的类
标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作
单字节字符字符串的设计特性。
string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信
息,请参阅basic_string)。
string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits
和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如utf-8)的序列,这个
类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
代码演示:
#include<iostream>#include<string>using namespace std;int main(){ string s1; string s4("hello world"); string s5("hello world", 7); string s6(10, 'x'); string s2(s4); string s3(s4, 6, 3); cout << "s1:"<< s1.c_str() << endl; cout << "s4:" << s4.c_str() << endl; cout << "s5:" << s5.c_str() << endl; cout << "s6:" << s6.c_str() << endl; cout << "s2:" << s2.c_str() << endl; cout << "s3:" << s3.c_str() << endl; }
运行结果:
模拟实现
由于上面有些接口不常用,所以我就模拟实现了一部分常用的接口
string (const char* s)
namespace cxy{ class string { public: string(const char*s = "") { if (s==nullptr) return; _size = strlen(s); _capacity = _size; _str = new char[_capacity + 1]; strcpy(_str, s); } const char* c_str() { return _str; } private: size_t _size; size_t _capacity; char* _str; };}
string (const string& str)
void swap (string& str)
namespace cxy{ class string { public: void swap(string& str) { //下面的swap会调用库里面的接口 ::swap(_size, str._size); ::swap(_capacity, st爱图片r._capacity); ::swap(_str, str._str); } string(const char*s = "") { if (s==nullptr) return; _size = strlen(s); _capacity = _size; _str = new char[_capacity + 1]; strcpy(_str, s); } string(const string& str) :_str(nullptr), _size(0), _capacity(0) { string tmp(str._str); swap(tmp); } char* c_str() { return _str; } private: size_t _size; size_t _capacity; char* _str; };}
代码演示:
int main(){ string s1("hello world"); cout <<"s1.size(): " <<s1.size() << endl; cout <<"s1.length(): "<< s1.length() << endl; cout <<"s1.capacity(): "<<s1.capacity() << endl; cout <<"s1:"<< s1 << endl; cout << endl; s1.clear(); cout <<"s1:"<< s1 << endl; cout << "s1.size(): " << s1.size() << endl; cout << "s1.capacity(): " << s1.capacity() << endl; cout << endl; s1 = "hello world"; cout << "s1:" << s1 << endl; cout << "s1.size(): " << s1.size() << endl; cout << "s1.capacity(): " << s1.capacity() << endl; s1.resize(17,'x'); //当n>capacity,则扩容,并且把0~27上位置的空余位置填充‘字符' cout << "s1:" << s1 << endl; cout << "s1.size(): " << s1.size() << endl; cout << "s1.capacity(): " << s1.capacity() << endl; s1.resize(27, 'x'); //当size<n<capacity,则把0~27上位置的空余位置填充‘字符' cout << "s1:" << s1 << endl; cout << "s1.size(): " << s1.size() << endl; cout << "s1.capacity(): " << s1.capacity() << endl; s1.resize(5, 'x'); //当n<size,则只保留n个‘字符',空间大小不变 cout << "s1:" << s1 << endl; cout << "s1.size(): " << s1.size() << endl; cout << "s1.capacity(): " << s1.capacity() << endl; cout << endl; string s2("hello world"); s2.rerve(5); //当n<=capacity时,空间大小不变,且不改变数据内容 cout << "s2:" << s2 << endl; cout << "s2.size(): " << s2.size() << endl; cout << "s2.capacity(): " << s2.capacity() << endl; s2.rerve(100); //当n>capacity时,空间会增大 cout << "s2:" << s2 << endl; cout << "s2.size(): " << s2.size() << endl; cout << "s2.capacity(): " << s2.capacity() << endl;}
运行结果:
得知:
rerve和resize的区别:rerve不会影响内容,resize会影响内容。
模拟实现
size_t size() const
返回字符串的有效长度
namespace cxy{ class string { public: size_t size()const { return _size; } private: size_t _size; size_t _capacity; char* _str; };}
size_t capacity() const
返回空间的大小
namespace cxy{ class string { public: size_t capacity()const { return _capacity; } private: size_t _size; size_t _capacity; char* _str; };}
bool empty() const
检测字符串优师助手释放为空串,是返回true,否则返回fal
namespace cxy{ class string { public: bool empty()const { return _str == 0; } private: size_t _size; size_t _capacity; char* _str; };}
void clear()
清空有效字符 ,不会改变容量
namespace cxy{ class string { public: void clear() { _size = 0; _str[_size] = 'namespace cxy{class string{public:void clear(){_size = 0;_str[_size] = '\0';}private:size_t _size;size_t _capacity;char* _str;};}'; } private: size_t _size; size_t _capacity; char* _str; };}
void rerve (size_t n = 0)
请求改变容量 ,此功能对字符串长度没有影响,无法改变其内容
如果 n 大于当前字符串容量,则该金刚藤的功效与作用函数会导致容器将其容量增加到 n 字符(或更大)
n小于当前字符串容量时,不会发生改变
namespace cxy{ class string { public: void rerve(size_t n=0) { if (n > _capacity) { char *tmp = new char[n + 1]; st北京八中少年班rncpy(tmp,_str,_size+1); delete[]_str; _str = tmp; _capacity = n; } private: size_t _size; size_t _capacity; char* _str; };}
补充:strncpy是c语言中的函数
char * strncpy ( char * destination, const char * source, size_t num )
功能:
将source中的字符串复制到destination中,且复制num个字符个数,如果在没有复制完num个字符之前,找到了source的末尾,则目标填充零,直到向其编写了总共num字符。如果来source中的字符有效长度大于数字,则目的地末尾不会隐含任何空字符(’\0’)。因此,在这种情况下,目的地不应被视为无效终止的 c 字符串(因此读取它将溢出,所以这种时候记得要在末尾添加’\0’)。void resize (size_t n, char c)
void resize (size_t n)
将有效字符的个数该成n个,多出的空间用字符c填充
namespace cxy{ class string { public: void resize(size_t n,char c='namespace cxy{class string{public:void resize(size_t n,char c='\0'){if (n<_size){_size = n;_str[_size] = '\0';}el{ if (n > _capacity){rerve(n);}memt(_str + _size, c, n - _size); _size = n;_str[_size] = '\0';}private:size_t _size;size_t _capacity;char* _str;};}') { if (n<_size) { _size = n; _str[_size] = 'namespace cxy{class string{public:void resize(size_t n,char c='\0'){if (n<_size){_size = n;_str[_size] = '\0';}el{ if (n > _capacity){rerve(n);}memt(_str + _size, c, n - _size); _size = n;_str[_size] = '\0';}private:size_t _size;size_t _capacity;char* _str;};}'; } el { if (n > _capacity) { rerve(n); } memt(_str + _size, c, n - _size); _size = n; _str[_size] = 'namespace cxy{class string{public:void resize(size_t n,char c='\0'){if (n<_size){_size = n;_str[_size] = '\0';}el{ if (n > _capacity){rerve(n);}memt(_str + _size, c, n - _size); _size = n;_str[_size] = '\0';}private:size_t _size;size_t _capacity;char* _str;};}'; } private: size_t _size; size_t _capacity; char* _str; };}
补充:memt是c语言中的函数
void * memt ( void * ptr, int value, size_t num )
功能:
将value传到prt中,以第一个位置开始传,传num个,传完为止。总结
size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。clear()只是将string中有效字符清空,不改变底层空间大小。
resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大
rerve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当rerve的参数小于string的底层空间总大小时,rerver不会改变容量大小。
代码演示:
int main(){ string s("hello world"); cout << "operator[] :"; for (size_t i = 0; i < s.size(); i++) cout << s[i] ; cout << endl; //迭代器 string::iterator it = s.begin(); cout << "iterator :"; while (it != s.end()) { cout << *it ; ++it; } cout << endl; //范围for cout << "范围for :"; for (auto ch : s) { cout << ch ; } cout << endl;}
模拟实现
const char& operator[] (size_t pos) const
namespace cxy{ class string { public: const char& operator[](size_t pos)const { asrt(pos < _size); return _str[pos]; } private: size_t _size; size_t _capacity; char* _str; };}
iterator begin() iterator end()
namespace cxy{ class string { public: typedef char* iterator; iterator begin() { return _str; } iterator end() { return _str+_size; } private: size_t _size; size_t _capacity; char* _str; };}
c++11:范围for
在这里不实现,知道怎么用就行
代码演示:
int main(){ string s("hello world"); s.push_back('k'); cout << s << endl; s.append("sssss"); cout << s << endl; s += "ff"; cout << s << endl; cout << s.find("kss") << endl; s.era(11, 8); cout << s << endl;}
运行结果:
模拟实现:只实现了一些常用的接口
void push_back (char c)
在字符串后面插入字符c
namespace cxy{ class string { public: void push_back(char c) { if (_size == _capacity) { rerve(_capacity * 2); } _str[_size] = c; _str[_size+1] = 'namespace cxy{class string{public:void push_back(char c){if (_size == _capacity){rerve(_capacity * 2);}_str[_size] = c;_str[_size+1] = '\0';_size++;}private:size_t _size;size_t _capacity;char* _str;};}'; _size++; } private: size_t _size; size_t _capacity; char* _str; };}
string& append (const char*s)
在字符串后面追加字符串s
namespace cxy{ class string { public: string &append(const char*s) { size_t len = strlen(s)+_size; if (len > _capacity) { rerve(len); } strncpy(_str + _size, s, len - _size+1); _size = len; return *this; } private: size_t _size; size_t _capacity; char* _str; };}
string& operator+= (const char* s)
在字符串后面追加字符串s
namespace cxy{ class string { public: string& operator+=(const char*s) { append(s); return *this; } private: size_t _size; size_t _capacity; char* _str; };}
const char* c_str() const
返回c格式的字符串
namespace cxy{ class string { public: const char* c_str()const { return _str; } private: size_t _size; size_t _capacity; char* _str; };}
size_t find (const char* s, size_t pos = 0) const
从字符串pos位置开始往后找字符串s,返回该字符串s在字符串中的位置
namespace cxy{ class string { public: size_t find(const char*s,size_t pos=0)const { char *str = _str+pos; while (*str) { char* str_s = str; const char* tmp = s; while (*str_s&&*tmp==*str_s) { tmp++; str_s++; } if (*tmp=='namespace cxy{class string{public:size_t find(const char*s,size_t pos=0)const{char *str = _str+pos;while (*str){char* str_s = str;const char* tmp = s;while (*str_s&&*tmp==*str_s){tmp++;str_s++;}if (*tmp=='\0')return str - _str;elstr++;}return -1;}private:size_t _size;size_t _capacity;char* _str;};}') return str - _str; el str++; } return -1; } private: size_t _size; size_t _capacity; char* _str; };}
string& era (size_t pos = 0, size_t len = npos)
擦除字符串的一部分,减少其长度
static const size_t npos = 0;namespace cxy{ class string { public: string &era(size_t pos = 0, size_t len = npos) { asrt(pos < _size); if (len+pos >= _size) { _str[pos] = 'static const size_t npos = 0;namespace cxy{class string{public:清华大学专业string &era(size_t pos = 0, size_t len = npos){asrt(pos < _size);if (len+pos >= _size){_str[pos] = '\0';_size = pos;}el{strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;}private:size_t _size;size_t _capacity;char* _str;};}'; _size = pos; } el { strcpy(_str + pos, _str + pos + len); _size -= len; } return *this; } private: size_t _size; size_t _capacity; char* _str; };}
模拟实现
istream& operator>> (istream& is, string& str)
namespace cxy{ class string { public: private: size_t _size; size_t _capacity; char* _str; }; istream& operator >> (istream& is, string& str) { str.clear(); char ch; ch = is.get(); while (ch != ' '&&ch != 'namespace cxy{class string{public:private:size_t _size;size_t _capacity;char* _str;};istream& operator >> (istream& is, string& str){str.clear();char ch;ch = is.get();while (ch != ' '&&ch != '\0'){str += ch;ch = is.get();}return is;}}') { str += ch; ch = is.get(); } return is; }}
说明一下:这个函数实现放在全局,是因为他的is要和对象str抢第一个位置,如果放在string类里面实现,那么第一个位置是this指针,也就是str对象,在用这个函数的时候就会很变扭。
ostream& operator<< (ostream& os, const string& str);
namespace cxy{ class string { public: private: size_t _size; size_t _capacity; char* _str; }; ostream& operator<< (ostream& os, string& str) { for (auto ch:str) { os << ch; } return os; } }
istream& getline (istream& is, string& str)
获取一行字符串
namespace cxy{ class string { public: private: size_t _size; size_t _capacity; char* _str; }; istream&getline(istream&is ,string&s) { s.clear(); char ch; ch = is.get(); while (ch != 'namespace cxy{class string{public:private:size_t _size;size_t _capacity;char* _str;}; istream&getline(istream&is ,string&s){s.clear();char ch;ch = is.get();while (ch != '\0'){s += ch;ch = is.get();}return is;}}') { s += ch; ch = is.get(); } return is; }}
到此这篇关于 关于c++stl string类的介绍及模拟实现的文章就介绍到这了,更多相关c++stl string类介绍及模拟实现内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
本文发布于:2023-04-07 20:36:48,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/6cef93c4c2d989fedc64c1ec2044f39f.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:关于C++STL string类的介绍及模拟实现.doc
本文 PDF 下载地址:关于C++STL string类的介绍及模拟实现.pdf
留言与评论(共有 0 条评论) |