当前位置: 首页 > news >正文

视频门户网站建设服务器今天建设银行网站无法登录

视频门户网站建设服务器,今天建设银行网站无法登录,河北建筑培训网首页,wordpress 1g1核1m文章目录 前言1. STL的简单理解1.1 什么是STL1.2 STL的版本1.3 STL的六大组件1.4 STL的重要性1.5 STL的缺陷 2. string类2.1 为什么学习string类#xff1f;2.1.1 C语言中的字符串2.1.2 两个面试题 2.2 标准库中的string类2.2.1 string类(了解)2.2.2 string类的常用接口说明 2… 文章目录 前言1. STL的简单理解1.1 什么是STL1.2 STL的版本1.3 STL的六大组件1.4 STL的重要性1.5 STL的缺陷 2. string类2.1 为什么学习string类2.1.1 C语言中的字符串2.1.2 两个面试题 2.2 标准库中的string类2.2.1 string类(了解)2.2.2 string类的常用接口说明 2.3 string类的模拟实现中的一些问题2.3.1 经典的string类问题2.3.2 浅拷贝2.3.3 深拷贝 2.4 string的模拟实现2.4.1 构造函数2.4.2 拷贝构造2.4.3 析构函数2.4.4 赋值运算符重载2.4.5 [ ]的实现2.4.6 扩容2.4.7 尾插2.4.8 插入一个字符串2.4.9 的运算符重载2.4.10 插入2.4.11 删除2.4.12 重新设置大小2.4.13 与 的重载2.4.14 、、运算符重载2.4.15 查找函数 3.全部代码3.1 String.h3.2 String.cpp3.3 Test.cpp 4. 总结 前言 可能很多人都不太清楚STL是什么它是用来干什么的大家在看完这篇文章之后相信能有个大概的了解目前我只能说STL是C的中十分重要的部分之一是大家学习C必须掌握的部分。 1. STL的简单理解 1.1 什么是STL STL(standard template libaray-标准模板库)是C标准库的重要组成部分不仅是一个可复用的组件库而且是一个包罗数据结构与算法的软件框架。 1.2 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要阅读部分源代码 主要参考的就是这个版本。 1.3 STL的六大组件 1.4 STL的重要性 在笔试中 1. 二叉树层序打印 2. 重建二叉树 3. 两个栈实现一个队列 在面试中 3.在工作中 网上有句话说“不懂STL不要说你会C”。STL是C中的优秀作品有了它的陪伴许多底层的数据结构以及算法都不需要自己重新造轮子站在前人的肩膀上健步如飞的快速开发。 1.5 STL的缺陷 STL库的更新太慢了。这个得严重吐槽上一版靠谱是C98中间的C03基本一些修订。C11出来已经相隔了13年STL才进一步更新。STL现在都没有支持线程安全。并发环境下需要我们自己加锁。且锁的粒度是比较大的。STL极度的追求效率导致内部比较复杂。比如类型萃取迭代器萃取。STL的使用会有代码膨胀的问题比如使用vector/vector/vector这样会生成多份代码当然这是模板语法本身导致的。 2. string类 string类是一个容器它是我们学习STL的第一部分我们的主线是讲解STL的容器其余部分会在讲解容器时进行穿插讲解。 2.1 为什么学习string类 2.1.1 C语言中的字符串 C语言中字符串是以’\0’结尾的一些字符的集合为了操作方便C标准库中提供了一些str系列的库函数但是这些库函数与字符串是分离开的不太符合OOP的思想而且底层空间需要用户自己管理稍不留神可能还会越界访问. 2.1.2 两个面试题 1. 字符串转整形数字   2. 字符串相加   在OJ中有关字符串的题目基本以string类的形式出现而且在常规工作中为了简单、方便、快捷基本都使用string类很少有人去使用C库中的字符串操作函数。 2.2 标准库中的string类 2.2.1 string类(了解) string类的文档介绍 字符串是表示字符序列的类标准的字符串类提供了对此类对象的支持其接口类似于标准字符容器的接口但添加了专门用于操作单字节字符字符串的设计特性。string类是使用char(即作为它的字符类型使用它的默认char_traits和分配器类型(关于模板的更多信息请参阅basic_string)。string类是basic_string模板类的一个实例它使用char来实例化basic_string模板类并用char_trai ts和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。注意这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列这个类的所有成员(如长度或大小)以及它的迭代器将仍然按照字节(而不是实际编码的字符)来操作。 总结 string是表示字符串的字符串类该类的接口与常规容器的接口基本相同再添加了一些专门用来操作string的常规操作。string在底层实际是basic_string模板类的别名typedef basic_stringchar, char_traits, allocator string;不能操作多字节或者变长字符的序列。 在使用string类时必须包含#include头文件以及using namespace std; 2.2.2 string类的常用接口说明 上面就是关于string修改部分的一些接口比如插入、删除等等。   上面就是关于string容量部分的一些接口比如计算长度、计算容量等等。   此外还有大量的其他接口再后面我会将用的比较多的接口进行模拟实现如果有小伙伴对其他接口也十分感兴趣可以通过下面的链接进行跳转观看string的全部接口对于每一个接口点进去都会有详细的文档说明和测试用例十分便于大家理解。 2.3 string类的模拟实现中的一些问题 2.3.1 经典的string类问题 上面已经对string类进行了简单的介绍大家只要能够正常使用即可。在面试中面试官总喜欢让学生自己来模拟实现string类最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数。大家看下以下string类的实现是否有问题 // 为了和标准库区分此处使用String class String { public:/*String():_str(new char[1]){*_str \0;}*///String(const char* str \0) 错误示范//String(const char* str nullptr) 错误示范String(const char* str ){// 构造String类对象时如果传递nullptr指针可以认为程序非if (nullptr str){assert(false);return;}_str new char[strlen(str) 1];strcpy(_str, str);}~String(){if (_str){delete[] _str;_str nullptr;}} private:char* _str; }; // 测试 void TestString() {String s1(hello bit!!!);String s2(s1); }我们会发现程序运行崩溃这是因为上述String类没有显式定义其拷贝构造函数与赋值运算符重载此时编译器会合成默认的当用s1构造s2时编译器会调用默认的拷贝构造。最终导致的问题是s1、s2共用同一块内存空间在释放时同一块空间被释放多次而引起程序崩溃这种拷贝方式称为浅拷贝。这个知识点我在C类和对象中的赋值运算符部分进行过详细的讲解有不懂的小伙伴可以点击链接进行跳转阅读。 2.3.2 浅拷贝 浅拷贝也称位拷贝编译器只是将对象中的值拷贝过来。如果对象中管理资源最后就会导致多个对象共享同一份资源当一个对象销毁时就会将该资源释放掉而此时另一些对象不知道该资源已经被释放以为还有效所以当继续对资源进项操作时就会发生发生了访问违规。   可以采用深拷贝解决浅拷贝问题即每个对象都有一份独立的资源不要和其他对象共享。 2.3.3 深拷贝 如果一个类中涉及到资源的管理其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。   深拷贝的具体如何实现在下一小节模拟实现中进行讲解。 2.4 string的模拟实现 2.4.1 构造函数 //声明这一行是放在String.h文件中的 //string(const char* str );WY::string::string(const char* str):_size(strlen(str)),_capacity(strlen(str)) {_str new char[_capacity 1];strcpy(_str, str); }在实现拷贝构造时一般都会采用缺省值的方式是为了避免使用者在实例化对象时忘记赋予初始值。对于缺省参数在声明和定义中一般是在声明时书写缺省值。并且在开辟空间时是要开辟容量1 个空间因为参数的字符串中是包含一个字符零的因此在开辟时要给字符零预留一个空间 2.4.2 拷贝构造 WY::string::string(const string s) {_str new char[s._capacity 1];strcpy(_str, s._str);_capacity s._capacity;_size s._size; }拷贝构造一定需要注意的点是参数必须进行引用传参负责会出现无限递归的问题具体过程在C类和对象有关拷贝构造的小节有详细说明。   初次之外这里也是涉及到了深拷贝在拷贝构造中我们是重新开辟了一块新空间进行拷贝因此原来的对象与新对象指向的是不同的空间在析构时是不会发生对一块空间析构两次的情况。 2.4.3 析构函数 //析构 WY::string::~string() {delete[] _str;_str nullptr;_capacity _size 0; }就是释放空间并将对象中的成员变量都进行归零。需要注意的是在释放空间是要加 [ ]中括号对于单个变量是不需要加中括号的但是对于多个变量比如数组在释放时需要加中括号。详细原理见C/C动态内存管理。 2.4.4 赋值运算符重载 WY::string WY::string::operator (const string s) {if (this ! s){char* tmp new char[s._capacity 1];strcpy(tmp, s._str);delete[] _str;_str tmp;_capacity s._capacity;_size s._size;}return *this; }首先需要说明的是这里的引用传参仅仅只是为了提高效率因为在实现了拷贝构造函数之后再进行传值传参就不会发生无穷递归了。为了避免浅拷贝问题需要重新开辟一块空间将数据进行拷贝过去然后将被赋值的对象的原数据进行释放将新开辟的空间给了被赋值对象再将其余成员变量依次进行修改。 2.4.5 [ ]的实现 char WY::string::operator[](size_t index) {return _str[index]; }const char WY::string::operator[](size_t index)const {return _str[index]; }中括号的实现可以让用户更加方便的查询数据但是const成员是无法调用非const 的成员函数的因此要将const成员函数也要实现一下。 2.4.6 扩容 //扩容 void WY::string::reserve(size_t n) {if (_capacity n){_capacity n;char* tmp new char[n 1];strcpy(tmp, _str);delete[] _str;_str tmp;} }重新开辟一块空间再将原数据进行拷贝就可以了要记得释放原对象的空间噢 2.4.7 尾插 void WY::string::push_back(char c) {if (_size _capacity){reserve(_capacity 0 ? 4 : _capacity * 2);}_str[_size] c;_size;_str[_size] \0; }尾插无法避免的情况就是当容量已满时就需要进行扩容。 2.4.8 插入一个字符串 void WY::string::append(const char* str) {int len strlen(str);if (_size len _capacity){reserve(_size len);}strcpy(_str _size, str);_size len; }上面的尾插只是插入了一个字符这个函数是用来专门插入一个字符串的。在库函数中这个函数是可以实现在各个位置进行插入这里我只实现了尾部插入需要更加详细了解的可以去看相关的需求文档。 2.4.9 的运算符重载 WY::string WY::string::operator(char c) {push_back(c);return *this; }WY::string WY::string::operator(const char* str) {append(str);return *this; }这里的逻辑跟尾插一样直接调用尾插就好了这也是进行分模块实现功能的好处可以进行代码复用十分方便。 2.4.10 插入 void WY::string::insert(size_t pos, char c) {assert(pos 0);if (_size _capacity){reserve(_capacity * 2);}size_t end _size 1;while (end pos){_str[end] _str[end - 1];end--;}_str[pos] c;_size; }只要插入数据就需要进行扩容判断然后从后往前不断挪动数据一直到pos位置再进行插入这一块的时间复杂度是O(n)。 void WY::string::insert(size_t pos, const char* str) {assert(pos 0);size_t len strlen(str);if (_size len _capacity){reserve(_size len);}size_t end _size 1;while (end pos){_str[end len - 1] _str[end - 1];end--;}strncpy(_str pos, str, len);_size len; }插入一个字符串和插入一个字符的逻辑是一样的。 2.4.11 删除 void WY::string::erase(size_t pos, size_t len) {assert(pos _size);if (len npos ||pos len _size){_str[pos] \0;_size pos;}else{size_t begin pos len;while (begin _size){_str[pos] _str[begin];}_size - len;} }删除有两种情况一种是将pos位置之后的数据全部删除一种是只删除pos位置之后长度为len的数据。这里的npos是一个全局变量是为了与库函数中的实现方式相对应同时它也是参数len的缺省值。   如果用户没有具体说明删除多长的数据默认为删除pos位置之后的所有数据而当你删除的数据长度加上pos位置大于整个数据的大小说明此时也是删除了pos位置之后的所有数据。另一种情况就是将需要删除的数据后面所剩的数据全部挪移到前面即可。 2.4.12 重新设置大小 void WY::string::resize(size_t n, char c) {if (n _size){_str[n] \0;_size n;}else{reserve(n);while (_size n){_str[_size] c;}_str[_size] \0;} }如果小于原数据大小直接在n位置填上’\0’即可如果大于原数据就需要先扩容再多余的空间上填上字符c这里的c的默认参数是’\0’。 2.4.13 与 的重载 ostream WY::operator(ostream _cout, const WY::string s) {for (size_t i 0; i s.size(); i){_cout s[i];}return _cout; }istream WY::operator(istream _cin, WY::string s) {char ch _cin.get();while (ch ! ch ! \n){s ch;ch _cin.get();}return _cin; }ostream与istream也是一个对象一个是输出流cout一个是输入流对象cin)。这个运算符重载需要注意的是这个是写在类外面的并不是一个类的成员函数因为如果写成成员函数的话就是这个样子operator(thisistream _cin)由于this是在前面因此在外面调用的话就需要书写成 s cout而我们正常写的是cout s所有需要在类的外面进行声明定义。但是类外面的函数要是无法访问类内部的成员变量的所以还需要将这两个函数声明为该类的友元函数有关友元函数的讲解在C类和对象中有详细解释。当一个函数被声明为友元函数时这个函数就可以访问该类的成员变量。   还需要注意的一个点是这两个函数一般都是引用返回一是为了提高效率(引用传参、引用返回都不需要再进行拷贝构造因此可以提高效率二是可以实现连续输入输出。比如cout s s1 ------operator (opeartor cout,s)s1)。 2.4.14 、、运算符重载 bool WY::string::operator(const string s) {return strcmp(_str, s._str) 0; }bool WY::string::operator(const string s) {return strcmp(_str, s._str) 0; }bool WY::string::operator(const string s) {return (*this s) || (*this s); }bool WY::string::operator(const string s) {return !(*this s); }bool WY::string::operator(const string s) {return !(*this s); }bool WY::string::operator!(const string s) {return !(*this s); }实现上两个其他的就可以直接进行复用了。 2.4.15 查找函数 size_t WY::string::find(char c, size_t pos) const {for (size_t i pos; i size(); i){if (_str[i] c)return i;}return npos; }size_t WY::string::find(const char* s, size_t pos) const {const char* p strstr(_str pos, s);if (p){return p - _str;}else{return npos;} }pos是用户可以指定从哪里开始进行查找查找单个字符依次便利尽心比较即可。在查找子串时可以调用库函数的strstr函数如果找到它返回的是子串的首地址如果没找到返回的是空指针。还需要注意的是指针减指针的含义是两个指针之间的数据个数这里也就是子串首字母的位置。 3.全部代码 3.1 String.h #pragma once #includeiostream #includeassert.h using namespace std;namespace WY {class string{friend ostream operator(ostream _cout, const WY::string s);friend istream operator(istream _cin, WY::string s);public:typedef char* iterator;typedef const char* const_iterator;public:string(const char* str );string(const string s);string operator (const string s);~string();//// iteratoriterator begin();const_iterator begin()const;iterator end();const_iterator end()const;/// modifyvoid 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;/// capacitysize_t size()const;size_t capacity()const;bool empty()const;void resize(size_t n, char c \0);void reserve(size_t n);/// accesschar operator[](size_t index);const char operator[](size_t index)const;///relational operatorsbool 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并返回该字符的位置void insert(size_t pos, char c);void insert(size_t pos, const char* str);// 删除pos位置上的元素并返回该元素的下一个位置void erase(size_t pos, size_t len npos);private:char* _str;size_t _capacity;size_t _size;const static size_t npos;};ostream operator(ostream _cout, const WY::string s);istream operator(istream _cin, WY::string s);void test_string1();void test_string2();void test_string3();void test_string4();void test_string5();void test_string6(); };3.2 String.cpp #define _CRT_SECURE_NO_WARNINGS 1 #includeString.hconst size_t WY::string::npos -1;//构造 WY::string::string(const char* str):_size(strlen(str)),_capacity(strlen(str)) {_str new char[_capacity 1];strcpy(_str, str); }//拷贝构造 WY::string::string(const string s) {_str new char[s._capacity 1];strcpy(_str, s._str);_capacity s._capacity;_size s._size; }WY::string WY::string::operator (const string s) {if (this ! s){char* tmp new char[s._capacity 1 ];strcpy(tmp, s._str);delete[] _str;_str tmp;_capacity s._capacity;_size s._size;}return *this; }//析构 WY::string::~string() {delete[] _str;_str nullptr;_capacity _size 0; }char WY::string::operator[](size_t index) {return _str[index]; }const char WY::string::operator[](size_t index)const {return _str[index]; }//扩容 void WY::string::reserve(size_t n) {if (_capacity n){_capacity n;char* tmp new char[n 1];strcpy(tmp, _str);delete[] _str;_str tmp;} }void WY::string::push_back(char c) {if (_size _capacity){reserve(_capacity 0 ? 4 : _capacity * 2);}_str[_size] c;_size;_str[_size] \0; }void WY::string::append(const char* str) {int len strlen(str);if (_size len _capacity){reserve(_size len);}strcpy(_str _size, str);_size len; }const char* WY::string::c_str()const {return _str; }WY::string WY::string::operator(char c) {push_back(c);return *this; }WY::string WY::string::operator(const char* str) {append(str);return *this; }void WY::string::clear() {_str[0] \0; }void WY::string::swap(string s) {char* tmp new char[_capacity 1];strcpy(tmp, _str);strcpy(_str, s._str);strcpy(s._str, tmp); }size_t WY::string::size()const {return _size; }size_t WY::string::capacity()const {return _capacity; }bool WY::string::empty()const {return _size 0; }void WY::string::insert(size_t pos, char c) {assert(pos 0);if (_size _capacity){reserve(_capacity * 2);}size_t end _size 1;while (end pos){_str[end] _str[end - 1];end--;}_str[pos] c;_size; }void WY::string::insert(size_t pos, const char* str) {assert(pos 0);size_t len strlen(str);if (_size len _capacity){reserve(_size len);}size_t end _size 1;while (end pos){_str[end len - 1] _str[end - 1];end--;}strncpy(_str pos, str, len);_size len; }void WY::string::erase(size_t pos, size_t len) {assert(pos _size);if (len npos ||pos len _size){_str[pos] \0;_size pos;}else{size_t begin pos len;while (begin _size){_str[pos] _str[begin];}_size - len;} }void WY::string::resize(size_t n, char c) {if (n _size){_str[n] \0;_size n;}else{reserve(n);while (_size n){_str[_size] c;}_str[_size] \0;} }WY::string::iterator WY::string::begin() {return _str; }WY::string::const_iterator WY::string::begin()const {return _str; }WY::string::iterator WY::string::end() {return _str _size; }WY::string::const_iterator WY::string::end()const {return _str _size; }// cout s ---- operator (cout,s) ostream WY::operator(ostream _cout, const WY::string s) {for (size_t i 0; i s.size(); i){_cout s[i];}return _cout; }istream WY::operator(istream _cin, WY::string s) {char ch _cin.get();while (ch ! ch ! \n){s ch;ch _cin.get();}return _cin; }bool WY::string::operator(const string s) {return strcmp(_str, s._str) 0; }bool WY::string::operator(const string s) {return strcmp(_str, s._str) 0; }bool WY::string::operator(const string s) {return (*this s) || (*this s); }bool WY::string::operator(const string s) {return !(*this s); }bool WY::string::operator(const string s) {return !(*this s); }bool WY::string::operator!(const string s) {return !(*this s); }size_t WY::string::find(char c, size_t pos) const {for (size_t i pos; i size(); i){if (_str[i] c)return i;}return npos; }size_t WY::string::find(const char* s, size_t pos) const {const char* p strstr(_str pos, s);if (p){return p - _str;}else{return npos;} } 3.3 Test.cpp #define _CRT_SECURE_NO_WARNINGS 1 #includeString.hvoid WY::test_string1() {string s(hello world);cout s.c_str() endl;string s1(s);cout s1.c_str() endl;string s2;s2 s;cout s2.c_str() endl;s.push_back(x);cout s.c_str() endl;s1.append(xxx);cout s1.c_str() endl;s2 x;cout s2.c_str() endl;s2 xxx;cout s2.c_str() endl;}void WY::test_string2() {string s(hello world);s.insert(0, x);cout s.c_str() endl;string s1(hello world);s1.insert(0, xxx);cout s1.c_str() endl;s.erase(0, 1);cout s.c_str() endl;s1.erase(0, 3);cout s1.c_str() endl;s1.erase(1);cout s1.c_str() endl;}void WY::test_string3() {string s(hello world);s.resize(5);cout s.c_str() endl;s.resize(20,x);cout s.c_str() endl; }void WY::test_string4() {string s;cin s;cout s endl; }void WY::test_string5() {string s(hello world);string s1(hello world);cout (s s1) endl;string s2(hello);cout (s s2) endl;string s3(a);string s4(b);cout (s3 s4) endl; }void WY::test_string6() {string s(hello world);size_t pos s.find(w);cout pos endl; }int main() {WY::test_string1();//WY::test_string2();//WY::test_string3();//WY::test_string4();//WY::test_string5();//WY::test_string6();return 0; }4. 总结 STL是学习是C中必不可少的一部分必须熟练掌握才行我建议大家可以通过刷题来快速掌握STL的使用熟练使用是最重要的其次才是了解它的底层实现。   如果大家发现有什么错误的地方可以私信或者评论区指出喔。我会继续深入学习C希望能与大家共同进步那么本期就到此结束让我们下期再见觉得不错可以点个赞以示鼓励
http://www.pierceye.com/news/573930/

相关文章:

  • 企炬网站wordpress会员付费插件
  • 在哪里购买虚拟空间建设网站网页设计培训机构培训费
  • 网站建设的色彩搭配做网站赚钱吗 怎么赚
  • 门头沟富阳网站建设西安企业电话
  • 电子商务网站建设概括湘潭专业seo优化推荐
  • 炫彩发光字制作免费网站动漫制作就业方向
  • 阿里巴巴可以做网站吗网站的可用性
  • 云虚拟主机怎么做2个网站装饰工程施工
  • 网站备案查询流程wordpress手机页面没有注册
  • 辽宁城乡建设集团官方网站精品课程网站建设
  • 威海 网站建设个人做网站可以盈利么
  • 机关网站源码网站建设 备案什么意思
  • 做理财的网站有哪些怎么弄数据库备份做网站
  • 网站不接入备案易企互联网站建设
  • 那种网站打不开北京网站建设找华网天下
  • 网站建设seo优化浙江网站名称怎么收录
  • 天津网站制作工具想自己做网站 有免费的吗
  • 宝塔织梦网站建设求网站备案照片
  • 聊城住房和城乡建设厅网站研发项目管理软件
  • 国投集团网站开发杭州网站界面设计
  • 做关于什么的网站莆田网站建设解决方案
  • 湖南长沙做网站那些网站可以做反链
  • 成都金牛网站建设公司高端网站配色
  • 做喜报的网站设计师的工作内容
  • 济南网站建设工作wordpress 资讯
  • 网站调用数据库平台公司名单
  • 移动网站怎么做成都设计公司名字
  • 杭州最好的网站设计公司服务器域名解析
  • 做试用网站的原理塘沽网吧开门了吗
  • 网站域名的作用古典网站源码