酒店网站建设流程,举报网站平台,企业网站的基本内容有哪些,烟台网站建设工作STL简介什么是STLSTL(standard template libaray-标准模板库)#xff1a;是C标准库的重要组成部分#xff0c;不仅是一个可复用的组件库#xff0c;而且是一个包罗数据结构与算法的软件框架。STL的版本原始版本Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本是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 SystemsInc公司开发继承自HP版 本。被GCC(Linux)采用可移植性好可公开、修改甚至贩卖从命名风格和编程 风格上看阅读性非常高。我们后面学习STL要阅读部分源代码主要参考的就是这个版本。 STL的六大组件仿函数、算法、迭代器、空间适配器、容器、配接器STL的缺陷STL库的更新太慢了。这个得严重吐槽上一版靠谱是C98中间的C03基本一些修订。C11出来已经相隔了13年STL才进一步更新。 STL现在都没有支持线程安全。并发环境下需要我们自己加锁。且锁的粒度是比较大的。STL极度的追求效率导致内部比较复杂。比如类型萃取迭代器萃取。STL的使用会有代码膨胀的问题比如使用vector/vector/vector这样会生成多份代码当然这是模板语法本身导致的。string类为什么学习string类C语言中字符串是以\0结尾的一些字符的集合为了操作方便C标准库中提供了一些str系列的库函数但是这些库函数与字符串是分离开的不太符合OOP的思想而且底层空间需要用户自己管理稍不留神可能还会越界访问。 标准库中的string类string类的文档介绍https://cplusplus.com/reference/string/string/?kwstring字符串是表示字符序列的类标准的字符串类提供了对此类对象的支持其接口类似于标准字符容器的接口但添加了专门用于操作单字节字符字符串的设计特性。string类是使用char(即作为它的字符类型使用它的默认char_traits和分配器类型(关于模板的更多信息请参阅basic_string)。 string类是basic_string模板类的一个实例它使用char来实例化basic_string模板类并用char_traits和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。注意这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列这个类的所有成员(如长度或大小)以及它的迭代器将仍然按照字节(而不是实际编码的字符)来操作。总结string时表示字符串的字符串类。该类的接口与常规容器接口基本相同再添加了一些专门用来操作string的常规操作。string在底层实际是basic_string模板类的别名typedef basic_stringchar,char_traits,allocator string;不能操作多字节或者变长字符的序列。string类的常用接口说明最常用的接口string类对象的常见构造constructor函数名称功能说明string()构造空的string类对象即空字符串string(const char* s)用C-string来构造string类对象string(size_t n,char c)string类对象中包含n个字符cstring(const string s)拷贝构造函数void Teststring()
{string s1; // 构造空的string类对象s1string s2(hello bit); // 用C格式字符串构造string类对象s2string s3(s2); // 拷贝构造s3
}string类对象的容量操作函数名称功能说明size返回字符串有效字符长度length返回字符串有效字符长度capacity返回空间总大小empty检测字符串释放为空是返回true否则返回falseclear清空有效字符reserve为字符串预留空间resize将有效字符的个数改成n个多出的空间用字符c填充// size/clear/resize
void Teststring1()
{// 注意string类对象支持直接用cin和cout进行输入和输出string s(hello, bit!!!);cout s.size() endl;cout s.length() endl;cout s.capacity() endl;cout s endl;// 将s中的字符串清空注意清空时只是将size清0不改变底层空间的大小s.clear();cout s.size() endl;cout s.capacity() endl;// 将s中有效字符个数增加到10个多出位置用a进行填充// “aaaaaaaaaa”s.resize(10, a);cout s.size() endl;cout s.capacity() endl;// 将s中有效字符个数增加到15个多出位置用缺省值\0进行填充// aaaaaaaaaa\0\0\0\0\0// 注意此时s中有效字符个数已经增加到15个s.resize(15);cout s.size() endl;cout s.capacity() endl;cout s endl;// 将s中有效字符个数缩小到5个s.resize(5);cout s.size() endl;cout s.capacity() endl;cout s endl;
}
//
void Teststring2()
{string s;// 测试reserve是否会改变string中有效元素个数s.reserve(100);cout s.size() endl;cout s.capacity() endl;// 测试reserve参数小于string的底层空间大小时是否会将空间缩小s.reserve(50);cout s.size() endl;cout s.capacity() endl;
}
// 利用reserve提高插入数据的效率避免增容带来的开销
//
void TestPushBack()
{string s;size_t sz s.capacity();cout making s grow:\n;for (int i 0; i 100; i){s.push_back(c);if (sz ! s.capacity()){sz s.capacity();cout capacity changed: sz \n;}}
}
void TestPushBackReserve()
{string s;s.reserve(100);size_t sz s.capacity();cout making s grow:\n;for (int i 0; i 100; i){s.push_back(c);if (sz ! s.capacity()){sz s.capacity();cout capacity changed: sz \n;}}
}【注意】 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在改变元素个数时如果是将元素个数增多可能会改变底层容量的大小如果是将元素个数减少底层空间总大小不变。 reserve(size_t res_arg0)为string预留空间不改变有效元素个数当reserve的参数小于string的底层空间总大小时reserver不会改变容量大小。string类对象的访问及遍历操作函数名称功能说明operator[]返回pos位置的字符const string类对象调用beginendbegin获取一个字符的迭代器end获取最后一个字符下一个位置的迭代器rbeginrendbegin获取一个字符的迭代器end获取最后一个字符下一个位置的迭代器范围forC11支持更简洁的范围for的新遍历方式void Teststring()
{string s1(hello Bit);const string s2(Hello Bit);couts1 s2endl;couts1[0] s2[0]endl;s1[0] H;couts1endl;// s2[0] h; 代码编译失败因为const类型对象不能修改
}
void Teststring()
{string s(hello Bit);// 3种遍历方式// 需要注意的以下三种方式除了遍历string对象还可以遍历是修改string中的字符// 另外以下三种方式对于string而言第一种使用最多// 1. foroperator[]for(size_t i 0; i s.size(); i)couts[i]endl;// 2.迭代器string::iterator it s.begin();while(it ! s.end()){cout*itendl;it;}string::reverse_iterator rit s.rbegin();while(rit ! s.rend())cout*ritendl;// 3.范围forfor(auto ch : s)coutchendl;
}string类对象的修改操作函数名称功能说明push_back在字符串后尾插字符cappend在字符串后追加一个字符串operator在字符串后追加字符串strc_str返回C格式的字符串findnpos从字符串pos位置开始往后找字符c返回该字符在字符串中的位置rfind从字符串pos位置开始往前找字符c返回该字符在字符串中的位置substr在str中从pos位置开始截取n个字符然后将其返回void Teststring()
{string str;str.push_back( ); // 在str后插入空格str.append(hello); // 在str后追加一个字符hellostr b; // 在str后追加一个字符b str it; // 在str后追加一个字符串itcoutstrendl;coutstr.c_str()endl; // 以C语言的方式打印字符串// 获取file的后缀string file1(string.cpp);size_t pos file.rfind(.);string suffix(file.substr(pos, file.size()-pos));cout suffix endl;// npos是string里面的一个静态成员变量// static const size_t npos -1;// 取出url中的域名sring url(http://www.cplusplus.com/reference/string/string/find/);cout url endl;size_t start url.find(://);if (start string::npos){cout invalid url endl;return;}start 3;size_t finish url.find(/, start);string address url.substr(start, finish - start);cout address endl;// 删除url的协议前缀pos url.find(://);url.erase(0, pos3);couturlendl;
}
【注意】在string尾部追加字符时s.push_back(c) / s.append(1, c) / s c三种的实现方式差不多一般情况下string类的操作用的比较多操作不仅可以连接单个字符还可以连接字符串。对string操作时如果能够大概预估到放多少字符可以先通过reserve把空间预留好。string类非成员函数函数功能说明operator尽量少用因为传值返回导致深拷贝效率低下operator输入运算符重载operator输出运算符重载getline获取一行字符串relational operators大小比较运用仅仅反转字母class Solution {
public:string reverseOnlyLetters(string S) {char* pLeft (char*)S.c_str();char* pRight pLeft (S.size()-1);while(pLeft pRight){// 从前往后找找到一个字母while(pLeft pRight){// 找到有效字母后停下来if(isalpha(*pLeft))break;pLeft;}// 从后往前找找一个字母while(pLeft pRight){// 找到有效字母后停下来if(isalpha(*pRight))break;--pRight;}if(pLeft pRight){swap(*pLeft, *pRight);pLeft;--pRight;}}return S;}
};
找字符串中第一个只出现一次的字符class Solution {
public:int firstUniqChar(string s) {// 统计每个字符出现的次数int count[256] {0};int size s.size();for(int i 0; i size; i)count[s[i]] 1;// 按照字符次序从前往后找只出现一次的字符for(int i 0; i size; i)if(1 count[s[i]])return i;return -1;}
};字符串里面最后一个单词的长度#includeiostream
#includestring
using namespace std;
int main()
{string line;// 不要使用cinline,因为会它遇到空格就结束了// while(cinline)while(getline(cin, line)){size_t pos line.rfind( );coutline.size()-pos-1endl;}return 0;
}验证一个字符串是否回文class Solution {
public:bool isLetterOrNumber(char ch){return (ch 0 ch 9)|| (ch a ch z)|| (ch A ch Z);}bool isPalindrome(string s) {// 先小写字母转换成大写再进行判断for(auto ch : s){if(ch a ch z)ch - 32;}int begin 0, end s.size()-1;while(begin end){while(begin end !isLetterOrNumber(s[begin]))begin;while(begin end !isLetterOrNumber(s[end]))--end;if(s[begin] ! s[end]){return false;}else{begin;--end;}}return true;}
}字符串相加class Solution {
public:string addstrings(string num1, string num2) {// 从后往前相加相加的结果到字符串可以使用insert头插// 或者尾插以后再reverse过来int end1 num1.size()-1;int end2 num2.size()-1;int value1 0, value2 0, next 0;string addret;while(end1 0 || end2 0){if(end1 0)value1 num1[end1--]-0;elsevalue1 0;if(end2 0)value2 num2[end2--]-0;elsevalue2 0;int valueret value1 value2 next;if(valueret 9){next 1;valueret - 10;}else{next 0;}//addret.insert(addret.begin(), valueret0);addret (valueret0);}if(next 1){//addret.insert(addret.begin(), 1);addret 1;}reverse(addret.begin(), addret.end());return addret;}
};string类的模拟实现namespace bit
{class string{public:typedef char* iterator;public:string(const char* str ){_size strlen(str);_capacity _size;_str new char[_capacity1];strcpy(_str, str);}string(const string s): _str(nullptr), _size(0), _capacity(0){string tmp(s);this-Swap(tmp);}string operator(string s){this-Swap(s)return *this;}~string(){if (_str){delete[] _str;_str nullptr;}}/// iteratoriterator begin() {return _str;}iterator end(){return _str _size;}/// modifyvoid push_back(char c){if (_size _capacity)Reserve(_capacity*2);_str[_size] c;_str[_size] \0;}string operator(char c){PushBack(c);return *this;}// 作业实现void append(const char* str);string operator(const char* str); void clear(){_size 0;_str[_size] \0;}void swap(string s){swap(_str, s._str);swap(_size, s._size);swap(_capacity, s._capacity);}const char* c_str()const{return _str;}/// capacitysize_t size()constsize_t capacity()constbool empty()constvoid resize(size_t newSize, char c \0){if (newSize _size){// 如果newSize大于底层空间大小则需要重新开辟空间if (newSize _capacity){Reserve(newSize);}memset(_str _size, c, newSize - _size);}_size newSize;_str[newSize] \0;}void reserve(size_t newCapacity){// 如果新容量大于旧容量则开辟空间if (newCapacity _capacity){char* str new char[newCapacity 1];strcpy(str, _str);// 释放原来旧空间,然后使用新空间delete[] _str;_str str;_capacity newCapacity;}}// accesschar 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);bool operator(const string s);bool operator(const string s);bool operator(const string s);bool operator(const string s);bool operator!(const string s);// 返回c在string中第一次出现的位置size_t find (char c, size_t pos 0) const;// 返回子串s在string中第一次出现的位置size_t find (const char* s, size_t pos 0) const;// 在pos位置上插入字符c/字符串str并返回该字符的位置string insert(size_t pos, char c);string insert(size_t pos, const char* str);// 删除pos位置上的元素并返回该元素的下一个位置string erase(size_t pos, size_t len);private:friend ostream operator(ostream _cout, const bit::string s);friend istream operator(istream _cin, bit::string s);private:char* _str;size_t _capacity;size_t _size;};
}
ostream bit::operator(ostream _cout, const bit::string s)
{// 不能使用这个//cout s._str;for(size_t i 0; i s.size(); i){_couts[i];}return _cout;
}
///对自定义的string类进行测试
void TestBitstring()
{bit::string s1(hello);s1.push_back( );s1.push_back(b);s1.append(1, i);s1 t;cout s1 endl;cout s1.size() endl;cout s1.capacity() endl;// 利用迭代器打印string中的元素string::iterator it s1.begin();while (it ! s1.end()){cout *it ;it;}cout endl;// 这里可以看到一个类只要支持的基本的iterator就支持范围forfor(auto ch : s1)coutch ;coutendl;
}