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

大连旅游必去景点seo快速上排名

大连旅游必去景点,seo快速上排名,做网站就上房山华网天下,用html建设网站目录 1.string类的结构 2.默认成员函数 2.1.默认构造函数 2.2拷贝构造函数 2.3赋值运算符重载 2.4析构函数 3.迭代器(Iterators) 4.string类的空间操作(Capacity) 4.1size() 4.2capacity() 4.3clear() 4.4reserve() 5.元素访问(Element access) 6.string类的修…

目录

1.string类的结构

2.默认成员函数

2.1.默认构造函数

2.2拷贝构造函数 

2.3赋值运算符重载 

2.4析构函数

 3.迭代器(Iterators)

4.string类的空间操作(Capacity)

4.1size()

4.2capacity()

4.3clear() 

4.4reserve()

5.元素访问(Element access)

6.string类的修改操作(Modifiers) 

6.1push_back()

6.2append() 

6.3operator+=()

6.4swap()

6.5insert() 

6.6 erase()

7.字符串操作(String operations) 

7.1c_str()

7.2find()

7.3substr()

8.非成员函数重载(Non-member function overloads) 

8.1关系运算符(relational operators)

8.2输入输出重载(operator>> and operator<<) 

 8.2.1输出运算符重载

8.2.2输入运算符重载

9.参考代码

9.1string.h 

9.2string.cpp

9.3Test.cpp 


1.string类的结构

		char* _str = nullptr;size_t _capacity = 0;size_t _size = 0;//这里可以直接给默认值,相当于定义,因为有const,只有整型可以//static const size_t npos = -1;static const size_t npos;

        string类结构里有一个_str指针,指向存储字符的数组,_capacity表示当前string的空间大小,_size表示当前string中的有效元素个数,静态常量npos默认等于-1,表示整形的最大值。 

2.默认成员函数

2.1.默认构造函数

		//默认构造函数string()//直接给空指针在使用.c_str()时进行打印对空指针进行了解引用:_str(new char[1] {'\0'})//:_str(nullptr),_size(0),_capacity(0){}//带参的构造string(const char* str){_size = strlen(str);//_capacity不包含\0_capacity = _size;//开空间的时候多开一个用于存储\0_str = new char[_capacity + 1];strcpy(_str, str);}

        这里的默认构造函数不能给_str空指针,如果是个空串进行打印的话,会对空指针进行解引用会导致程序崩溃。 因为要存一个'\0',所以空串也要开一个空间。

        这里可以把上述两个构造合成一个构造函数。

//将上述两个构造函数合并成一个全缺省的构造函数
string(const char* str = "")	//空的常量字符串默认包含一个\0
{_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);	//strcpy先拷贝再判断,会拷贝\0
}

2.2拷贝构造函数 

        1.传统写法

//传统写法
string(const string& s)
{_str = new char[s._capacity + 1];    //多开一个空间给'\0'strcpy(_str, s._str);                //拷贝数据_size = s._size;_capacity = s._capacity;
}

        2.现代写法

void swap(string& s) 
{std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);
}//现代写法
string(const string& s)
{string tmp(s._str);swap(tmp);
}

        这里调用库里面的交换函数,交换string结构里面的数据。然后在拷贝函数中用被拷贝的string对象s中的_str构造一个临时对象,然后进行交换,函数结束之后这个临时对象自动销毁,构造出一个与s一样的新对象。

2.3赋值运算符重载 

         1.写法1

		string& operator=(const string& s){if (this != &s)    //检测是否是自己给自己赋值{delete[] _str;    //释放原来对象的空间_str = new char[s._capacity + 1];    //new一个和s一样大的空间strcpy(_str, s._str);    //拷贝数据_size = s._size;_capacity = s._capacity;}return *this;}

        2.写法2 

		string& operator=(const string& s){if (this != &s){string tmp(s);swap(tmp);}return *this;}

        这个和拷贝函数的现代写法思路一样。

        3.写法3

		string& operator=(string tmp){swap(tmp);	//这里虽然tmp被交换了,但是形参的改变不影响实参return *this;}

        这里直接使用传值传参,然后进行交换,函数结束之后并不会影响实参。 

2.4析构函数

		~string(){if (_str){delete[] _str;_str = nullptr;   _size = 0;_capacity = 0;}}

 3.迭代器(Iterators)

		// iteratortypedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}const_iterator begin() const    //函数重载,重载迭代器用于const对象{return _str;}const_iterator end() const{return _str + _size;}

         因为string的底层是利用数组进行存储的,所以这里直接利用原始指针作为迭代器即可,用两个typedef关键字将char*类型和const char*类型改为迭代器的名字。

4.string类的空间操作(Capacity)

4.1size()

		size_t size() const{return _size;}

4.2capacity()

		size_t capacity() const{return _capacity;}

4.3clear() 

         清除string对象里面的数据,但是这里不缩容_capacity不改变。

		void clear(){_str[0] = '\0';_size = 0;}

4.4reserve()

         该函数在string.cpp里面实现的,所以加上了类域限定符.

	void string::reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}

5.元素访问(Element access)

        这里仅实现[]的重载。 

		char& operator[](size_t index){assert(index < _size);return _str[index];}const char& operator[](size_t index)const{assert(index < _size);return _str[index];}

6.string类的修改操作(Modifiers

6.1push_back()

        尾插一个字符.

	void string::push_back(char c){//扩容if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = c;++_size;_str[_size] = '\0';}

6.2append() 

        尾插一个字符串.这里扩容保持一个对齐的原则,如果需要的空间大于原来空间的两倍,则需要多少开多少,如果小于原来的两倍,则开2倍.

	void string::append(const char* str){size_t len = strlen(str);    //计算尾插的str大小if (_size + len > _capacity){//需要的空间大于原空寂的2倍,需要多少开多少,小于2倍开2倍reserve((_size + len) > (2 * _capacity) ? (_size + len) : (2 * _capacity));}strcpy(_str + _size, str);_size += len;}

6.3operator+=()

        +=运算符的重载实现能加一个字符,也能加一个字符串,复用上述两个接口进行实现.

	string& string::operator+=(char c){push_back(c);return *this;}string& string::operator+=(const char* str){append(str);return *this;}

6.4swap()

		void swap(string& s) {std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}

6.5insert() 

	// 在pos位置上插入字符c/字符串strvoid string::insert(size_t pos, char c){assert(pos <= _size);if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}//这里用size_t类型头插会出错,因为end永远都小于不了0//size_t end = _size;	//从最后一个\0开始往后挪动数据//用int end在与pos比较时会提升为size_t类型,也会出错//int end = _size;//while (end >= (int)pos)//{//	_str[end + 1] = _str[end];//	end--;//}//挪动数据,_size处是\0,从后面的\0开始挪动size_t end = _size + 1;while (end > pos)    {_str[end] = _str[end - 1];end--;}_str[pos] = c;++_size;}
	//在pos位置插入字符串void string::insert(size_t pos, const char* str){assert(pos <= _size);size_t len = strlen(str);if (_size + len > _capacity){//大于2倍,需要多少扩多少,小于2倍,扩2倍reserve((_size + len) > (2 * _capacity) ? (_size + len) : (2 * _capacity));}//挪动数据size_t end = _size + len;while (end >= pos + len - 1){_str[end] = _str[end - len];--end;}//插入字符串for (size_t i = 0; i < len; i++){_str[pos + i] = str[i];}_size += len;}

6.6 erase()

        如果需要删除的len的长度大于从pos到最后位置的长度,则修正len之后进行删除.

	// 删除pos位置上之后的len个元素void string::erase(size_t pos, size_t len){assert(pos < _size);//如果删除的元素个数大于从pos到最后的个数,修正一下lenif (len >= _size - pos){_str[pos] = '\0';_size = pos;}else{for (size_t i = pos + len; i <= _size; i++){_str[i - len] = _str[i];}_size -= len;}}

7.字符串操作(String operations) 

7.1c_str()

        这里返回string对象中的数组指针,可以说是返回C语言类型的字符串对象.

		//返回string中的指向字符串的指针const char* c_str() const{return _str;}

7.2find()

	// 返回c在string中第一次出现的位置size_t string::find(char c, size_t pos) const{assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == c){return i;}}//没找到返回最大的整数return npos;}// 返回子串s在string中第一次出现的位置size_t string::find(const char* s, size_t pos) const{assert(pos < _size);//调用库里面的strstr函数在自身中寻找子串const char* ptr = strstr(_str + pos, s);if (ptr == nullptr){return npos;}else{return ptr - _str;}}

7.3substr()

	//返回子串string string::substr(size_t pos, size_t len) const{assert(pos < _size);//len大于剩余字符的长度,更新一下lenif (len > _size - pos){len = _size - pos;}string sub;sub.reserve(len);for (size_t i = 0; i < len; i++){sub += _str[pos + i];}return sub;}

8.非成员函数重载(Non-member function overloads) 

8.1关系运算符(relational operators)

        字符串的关系运算符与C语言中的compare()类似,这里直接复用库里面的compare()函数.

需要注意的是compare()函数是使用C语言中的字符串格式进行比较的,这里比较的是string对象中_str指向的数组.

//relational operatorsbool operator<(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str()) < 0;}bool operator==(const string s1, const string& s2){return strcmp(s1.c_str(), s2.c_str()) == 0;}bool operator<=(const string s1, const string& s2){return s1 < s2 || s1 == s2;}bool operator>(const string s1, const string& s2){return !(s1 <= s2);}bool operator>=(const string s1, const string& s2){return !(s1 < s2);}bool operator!=(const string s1, const string& s2){return !(s1 == s2);}

8.2输入输出重载(operator>> and operator<<) 

         这里的输入和输出为什么重载成全局函数请参考C++类和对象(5)--日期类的实现中友元声明中的注释.

 8.2.1输出运算符重载

        遍历string对象一个一个输出即可.

	ostream& operator<<(ostream& _cout, const string& s){for (auto ch : s){_cout << ch;}return _cout;}

8.2.2输入运算符重载

        这里首先先清除s中原有的数据,然后在栈里面开一个256大小的buff(为了减少扩容的次数).这里用get()函数一个一个读取输入的字符,如果用输入运算符的话会忽略输入的空格和换行符.当一个buff满了之后拷贝到s中,跳出循环后如果buff中还有遗留的数据,则全部拷贝到s中.

	istream& operator>>(istream& _cin, string& s){s.clear();const int N = 256;char buff[N];int i = 0;char ch;//in >> ch; 默认会忽略空格和换行符ch = _cin.get();while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == N - 1){buff[i] = '\0';s += buff;i = 0;}//in >> ch;ch = _cin.get();}if (i > 0){buff[i] = '\0';s += buff;}return _cin;}

9.参考代码

        string实现在XiaoC这个命名空间中,上述的代码没有做测试,下面给出测试代码,有兴趣可以自行对接口进行测试.

9.1string.h 

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <assert.h>
#include <string>
using namespace std;namespace XiaoC
{class string{//friend ostream& operator<<(ostream& _cout, const XiaoC::string& s);//friend istream& operator>>(istream& _cin, XiaoC::string& s);public:默认构造函数//string()//	//直接给空指针在使用.c_str()时进行打印对空指针进行了解引用//	:_str(new char[1] {'\0'})//	//:_str(nullptr)//	,_size(0)//	,_capacity(0)//{}//带参的构造//string(const char* str)//{//	_size = strlen(str);//	//_capacity不包含\0//	_capacity = _size;//	//开空间的时候多开一个用于存储\0//	_str = new char[_capacity + 1];//	strcpy(_str, str);//}//将上述两个构造函数合并成一个全缺省的构造函数string(const char* str = "")	//空的常量字符串默认包含一个\0{_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);	//strcpy先拷贝再判断,会拷贝\0}//拷贝构造//传统写法//string(const string& s)//{//	_str = new char[s._capacity + 1];//	strcpy(_str, s._str);//	_size = s._size;//	_capacity = s._capacity;//}//现代写法string(const string& s){string tmp(s._str);swap(tmp);}//赋值重载//写法1//string& operator=(const string& s)//{//	if (this != &s)//	{//		delete[] _str;//		_str = new char[s._capacity + 1];//		strcpy(_str, s._str);//		_size = s._size;//		_capacity = s._capacity;//	}//	return *this;//}//写法2//string& operator=(const string& s)//{//	if (this != &s)//	{//		string tmp(s);//		swap(tmp);//	}//	return *this;//}//写法3string& operator=(string tmp){swap(tmp);	//这里虽然tmp被交换了,但是形参的改变不影响实参return *this;}~string(){if (_str){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}}// iteratortypedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}const_iterator begin() const{return _str;}const_iterator end() const{return _str + _size;}// modifyvoid push_back(char c);void append(const char* str);string& operator+=(char c);string& operator+=(const char* str);void swap(string& s) {std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}//返回string中的指向字符串的指针const char* c_str() const{return _str;}// capacitysize_t size() const{return _size;}size_t capacity() const{return _capacity;}void clear(){_str[0] = '\0';_size = 0;}void reserve(size_t n);// accesschar& operator[](size_t index){assert(index < _size);return _str[index];}const char& operator[](size_t index)const{assert(index < _size);return _str[index];}// 返回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/字符串strvoid insert(size_t pos, char c);void insert(size_t pos, const char* str);// 删除pos位置上的元素,并返回该元素的下一个位置void erase(size_t pos, size_t len = npos);//返回子串string substr(size_t pos = 0, size_t len = npos) const;private:char* _str = nullptr;size_t _capacity = 0;size_t _size = 0;//这里可以直接给默认值,相当于定义,因为有const,只有整型可以//static const size_t npos = -1;static const size_t npos;};//relational operatorsbool operator<(const string& s1, const string& s2);bool operator==(const string s1, const string& s2);bool operator<=(const string s1, const string& s2);bool operator>(const string s1, const string& s2);bool operator>=(const string s1, const string& s2);bool operator!=(const string s1, const string& s2);ostream& operator<<(ostream& _cout, const string& s);istream& operator>>(istream& _cin, string& s);}

9.2string.cpp

#include "string.h"
namespace XiaoC
{const size_t string::npos = -1;void string::push_back(char c){//扩容if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = c;++_size;_str[_size] = '\0';}void string::append(const char* str){size_t len = strlen(str);if (_size + len > _capacity){//大于2倍,需要多少开多少,小于2倍开2倍reserve((_size + len) > (2 * _capacity) ? (_size + len) : (2 * _capacity));}strcpy(_str + _size, str);_size += len;}string& string::operator+=(char c){push_back(c);return *this;}string& string::operator+=(const char* str){append(str);return *this;}void string::reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}// 在pos位置上插入字符c/字符串strvoid string::insert(size_t pos, char c){assert(pos <= _size);if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}//这里用size_t类型头插会出错,因为end永远都小于不了0//size_t end = _size;	//从最后一个\0开始往后挪动数据//用int end在与pos比较时会提升为size_t类型,也会出错//int end = _size;//while (end >= (int)pos)//{//	_str[end + 1] = _str[end];//	end--;//}//挪动数据,_size处是\0,从后面的\0开始挪动size_t end = _size + 1;while (end > pos){_str[end] = _str[end - 1];end--;}_str[pos] = c;++_size;}void string::insert(size_t pos, const char* str){assert(pos <= _size);size_t len = strlen(str);if (_size + len > _capacity){//大于2倍,需要多少扩多少,小于2倍,扩2倍reserve((_size + len) > (2 * _capacity) ? (_size + len) : (2 * _capacity));}size_t end = _size + len;while (end >= pos + len - 1){_str[end] = _str[end - len];--end;}for (size_t i = 0; i < len; i++){_str[pos + i] = str[i];}_size += len;}// 删除pos位置上之后的len个元素void string::erase(size_t pos, size_t len){assert(pos < _size);if (len >= _size - pos){_str[pos] = '\0';_size = pos;}else{for (size_t i = pos + len; i <= _size; i++){_str[i - len] = _str[i];}_size -= len;}}// 返回c在string中第一次出现的位置size_t string::find(char c, size_t pos) const{assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == c){return i;}}return npos;}// 返回子串s在string中第一次出现的位置size_t string::find(const char* s, size_t pos) const{assert(pos < _size);const char* ptr = strstr(_str + pos, s);if (ptr == nullptr){return npos;}else{return ptr - _str;}}//返回子串string string::substr(size_t pos, size_t len) const{assert(pos < _size);//len大于剩余字符的长度,更新一下lenif (len > _size - pos){len = _size - pos;}string sub;sub.reserve(len);for (size_t i = 0; i < len; i++){sub += _str[pos + i];}return sub;}//relational operatorsbool operator<(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str()) < 0;}bool operator==(const string s1, const string& s2){return strcmp(s1.c_str(), s2.c_str()) == 0;}bool operator<=(const string s1, const string& s2){return s1 < s2 || s1 == s2;}bool operator>(const string s1, const string& s2){return !(s1 <= s2);}bool operator>=(const string s1, const string& s2){return !(s1 < s2);}bool operator!=(const string s1, const string& s2){return !(s1 == s2);}ostream& operator<<(ostream& _cout, const string& s){for (auto ch : s){_cout << ch;}return _cout;}istream& operator>>(istream& _cin, string& s){s.clear();const int N = 256;char buff[N];int i = 0;char ch;//in >> ch; 默认会忽略空格和换行符ch = _cin.get();while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == N - 1){buff[i] = '\0';s += buff;i = 0;}//in >> ch;ch = _cin.get();}if (i > 0){buff[i] = '\0';s += buff;}return _cin;}
}

9.3Test.cpp

#include "string.h"namespace XiaoC
{//测试构造函数void test_string1(){string s1;string s2("hello world");cout << s1.c_str() << endl;cout << s2.c_str() << endl;}//测试遍历访问void test_string2(){string s1("hello world");cout << s1.c_str() << endl;//[] + 下标访问for (size_t i = 0; i < s1.size(); i++){s1[i] += 2;}cout << s1.c_str() << endl;//范围for底层就是替代为迭代器for (auto e : s1){cout << e << " ";}cout << endl;//通过迭代器遍历访问string::iterator it = s1.begin();while (it != s1.end()){cout << *it << " ";++it;}cout << endl;}//测试增删改查void test_string3(){string s1 = "hello world";s1 += 'x';s1 += 'c';cout << s1.c_str() << endl;s1 += " hello XiaoC";cout << s1.c_str() << endl;string s2 = "abcd";cout << s2.c_str() << endl;s2.insert(0, 'c');cout << s2.c_str() << endl;string s3 = "hello world";cout << s3.c_str() << endl;s3.insert(0, "xxx");cout << s3.c_str() << endl;string s4 = "hello world";cout << s4.c_str() << endl;s4.erase(0, 3);cout << s4.c_str() << endl;string s("test.cpp.zip");size_t pos = s.find('.');string suffix = s.substr(pos);cout << suffix.c_str() << endl;//拷贝构造string copy(s);cout << copy.c_str() << endl;//赋值运算符string s5 = "XiaoC";s5 = s;cout << s5.c_str() << endl;}//测试比较大小void test_string4(){string s1 = "helloworld";string s2 = s1;cout << (s1 == s2) << endl;cout << (s1 < s2) << endl;}//测试输入输出void test_string5(){string s1 = "hello world";cout << s1 << endl;string s2;cin >> s2;cout << s2 << endl;}//测试返回字串void test_string6(){string s1 = "hello world";string s2;s2 = s1.substr(6, 5);cout << s2 << endl;}
}
int main()
{//XiaoC::test_string1();//XiaoC::test_string2();//XiaoC::test_string3();//XiaoC::test_string4();XiaoC::test_string5();//XiaoC::test_string6();return 0;
}

 

 

 

http://www.qdjiajiao.com/news/10785.html

相关文章:

  • 如何进入公众号seo的主要工作是什么
  • 网站建设与管理期中考苹果被曝开发搜索引擎对标谷歌
  • 算命手机网站开发央视新闻的新闻
  • 福州专业做网站的公司深圳网络营销推广招聘网
  • APP手机端电子商务网站建设腾讯nba新闻
  • 成都高新区网站建设正规app推广
  • 简单模板网站制作时间高端营销型网站制作
  • 建设网站的网络公司google海外推广
  • 优化网站具体如何做微信scrm
  • 塘下做网站seo有哪些经典的案例
  • 儿童摄影作品网站南京seo推广公司
  • 网站开发服务费分录惠州seo关键词推广
  • 怎样建设企业网站长春网站建设公司哪个好
  • 书画工作室网站模板网站建设谷歌浏览器官网下载安装
  • 上海杨浦网站建设微信广告投放推广平台多少费用
  • 网站页面制作建议成人电脑速成培训班
  • 合肥建设委员会网站seo排名优化seo
  • 天津高自考网站建设与实践2017莫停之科技windows优化大师
  • wordpress多用户商城主题seo管理与优化期末试题
  • 淘宝客做网站要钱吗青岛百度关键词优化
  • 俄罗斯b2b常用网站武汉seo外包平台
  • 2015个人网站如何去工信部备案网站开发建设步骤
  • 外包网站开发公司花关键词排名系统
  • 网站建设公司小江今日国内新闻大事
  • 青岛谷歌seo智能网站排名优化
  • h5做怎么做微网站西安网站seo排名优化
  • wordpress 弹框昆明关键词优化
  • 网站制作验收单软件测试培训
  • 二级网站建设如何开发一款app软件
  • 网站建设设计企业友情链接方面pr的选择应该优先选择的链接为