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

谷歌自建站和优化重庆企业站seo

谷歌自建站和优化,重庆企业站seo,网站建设模板怎么用,企业网络规划开题报告目录 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.shuangfujiaoyu.com/news/36771.html

相关文章:

  • 优速网站建设国内建站平台
  • 网站费计入什么科目全网推广
  • 公司门户网站是什么网络营销模式包括哪些
  • 做网站页面多少钱品牌推广策划书范文案例
  • 公司网站建设合同模板网络推广哪个好
  • 福田大型商城网站建设微博上如何做网站推广
  • 印刷报价网站源码下载站长工具百度百科
  • 上海建筑 公司网站网页设计与制作步骤
  • 那个网站卖做防水的烤枪企业网站是什么
  • 青浦网络公司网站百度热度指数排行
  • 招聘网站免费平台百度广告推广怎么做
  • 安徽华建建设工程公司网站中国进入一级战备2023
  • 无忧网站建设服务百度指数手机版
  • wordpress公式 插件seo实战培训班
  • 优质做网站费用媒体宣传推广方案
  • 网站 在线支付功能网站排名优化培训哪家好
  • 现在为什么网站都打不开了怎么办啊东莞好的网站国外站建设价格
  • 上海网站营销怎么样刷网站软件
  • 郑州达云通网站建设公司网站免费优化软件
  • 马克斯网站建设爱站网关键词查询系统
  • 杨浦专业做网站百度霸屏培训
  • 网站点击排名优化网络推广员
  • 企业响应网站南宁关键词优化软件
  • 深圳建科院公司网站沈阳seo排名公司
  • 天津市哪里有做网站广告的整站外包优化公司
  • 网站开发外包网站推广普通话的手抄报
  • 青海做高端网站建设的公司企业如何进行品牌推广
  • 做网站是不是也是暴利白帽seo公司
  • 广州建网站多少钱小程序开发制作
  • 营销型网站的基本模板厦门seo优化公司