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

网站的中文域名是什么百度官网下载电脑版

网站的中文域名是什么,百度官网下载电脑版,网站建设自,中企动力潍坊分公司目录 一:string类 二:构造函数、拷贝构造函数及析构函数 1、构造函数 2、拷贝构造函数 3、析构函数 三、实现string中对容量操作的成员函数 1、size 2、capacity 3、reserve 4、resize 5、clear 6、empty 四、string类中对象的增删查改操作 …

目录

一:string类

二:构造函数、拷贝构造函数及析构函数

1、构造函数

2、拷贝构造函数

3、析构函数

三、实现string中对容量操作的成员函数

1、size

2、capacity

3、reserve

4、resize

5、clear

6、empty

四、string类中对象的增删查改操作

1、push_back

2、append

3、c_str

4、find

5、substr

6、insert

7、erase

五、string中重要的运算符重载

1、赋值运算符的重载

2、流插入 <<

3、流提取 >>

4、下标访问 []

5、加等一个字符 +=

6、加等字符串 +=

7、大于 >

8、等于 ==

9、小于 <

10、大于等于 >=

11、小于等于 <=

12、不等于 !=

六、迭代器

最后完整代码

string.h

string.c

test.c


一:string类

首先先定义一个string类

class string
{
public:private:char* _str = nullptr;size_t _size = 0;size_t _capacity = 0;
};

string的底层是一个个字符,所以定义一个_str 记录字符,_size用来记录这个字符串的长度,_capacity用来记录开了多少空间。


二:构造函数、拷贝构造函数及析构函数

1、构造函数

string的构造函数分为无参构造和有参构造,通过无参构造的对象会默认生成一个空字符串,因此我们可以带一个缺省值,在没有参数传递时就直接构造一空字符串

string(const char* str = ""):_str(new char[strlen(str) + 1]), _size(strlen(str)), _capacity(strlen(str))
{strcpy(_str, str);  //将str中的内容拷贝给_str
}

在开空间时,我们需要多开一个空间,因为strlen算出的大小不包括 '\0' ,因此我们需要给 '\0' 留一个空间。


2、拷贝构造函数

拷贝构造函数是默认成员函数,如果不写编译器会自动生成,对于内置类型完成浅拷贝,对于自定义类型调用其构造函数完成拷贝。对于string来说,如果不自己写拷贝构造函数会导致浅拷贝问题。

浅拷贝会使得两个对象指向同一块空间,两个对象在析构时都会调用自己的析构函数,这样同一块空间就会被析构两次;浅拷贝一个对象的数据改变,另一个对象的数据也改变,因为它们指向同一块空间地址。 一个对象被删除后,另一个对象无效

//浅拷贝实例
class ShallowCopyExample {
public:int* data;ShallowCopyExample(int value) {data = new int(value);}// 默认的拷贝构造函数是浅拷贝ShallowCopyExample(const ShallowCopyExample& other) = default;~ShallowCopyExample() {delete data;}
};int main() {ShallowCopyExample obj1(10);ShallowCopyExample obj2 = obj1;  // 浅拷贝// 问题:obj1和obj2的data指针指向同一内存// 当其中一个对象析构后,另一个对象的指针就悬空了
}

拷贝构造函数

string(const string& str):_str(new char[str._capacity+1]),_size(str._size),_capacity(str._capacity)
{strcpy(_str, str._str);
}

上面的这种写法是比较常见的一种写法,但是我们还有一种更加简便的写法。我们可以通过已经实现了的构造函数传一个常量字符串,即下面的str._str,来创建一个临时对象,然后将这个临时对象的成员与自己交换,这样也完成了拷贝构造。

void swap(string& s)
{std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);
}
string(const string& str):_str(nullptr), _size(0), _capacity(0)
{//创建一个临时对象string tmp(str._str);swap(tmp);
}

但是,为了写成这个拷贝构造函数我们还写了一个swap函数,这这么就简便了呢?

那是因为通过查阅标准库我们发现swap函数也是一个string类中提供了的函数,因此我们不仅简便了拷贝构造函数的写法,还又完成了一个函数的实现。并且,因为tmp是一个局部对象,因此在出作用域后就会自动调用析构函数,所以交换后还可以清理掉原来的空间,一举两得。

3、析构函数

我们可以使用delete直接释放掉_str的空间

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

三、实现string中对容量操作的成员函数

1、size

size返回字符串有效字符的长度。我们可以直接返回其成员变量中的_szie。

size_t size() const
{return _size;
}

2、capacity

capacity返回空间总大小。我们可以直接返回其成员变量中的_capacity。

size_t capacity() const
{return _capacity;
}

3、reserve

reserve为字符串预留空间

void reserve(size_t n)
{if (n > _capacity){//创建一个临时变量,开n + 1个空间char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str; //将原空间删除_str = tmp; // 将临时变量的空间给str_capacity = n;  // 预留多少字符给_capacity}
}

4、resize

resize 的功能是将有效字符的个数改成 n 个,多出的空间用字符 ch 填充。

_size < n < _capacity  先预留n大小的空间,直接用字符 填充 n - size 之间的位置,记住要在最后加上'\0'。

_size > n 直接将 n 的位置置换成'\0'。

n > _capacity 先预留 n 大小的空间,剩下的空间用字符 ch 填充,记住要在最后加上'\0'。

void resize(size_t n, char ch)
{if (n > _size){//先检查要不要扩容reserve(n);for (size_t i = _size; i < n; i++){_str[i] = ch;}_size = n;_str[_size] = '\0';}else{_str[_size] = '\0';_size = n;}
}

5、clear

作用是清空有效字符

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

6、empty

empty的作用是检测字符串释放为空字符串,是返回true,否则返回false。

bool empty() const
{return _size == 0;
}

四、string类中对象的增删查改操作

1、push_back

在字符串后面插字符c

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

2、append

在字符串后面追加一个字符串

void string::append(const char* str)
{//先计算追加字符的个数size_t len = strlen(str);//如果 len + _size > _capacity 就需要扩容if (_capacity < len + _size){//重新申请预留空间reserve(len + _size);}//从_str + _size出位置开始复制strcpy(_str + _size, str);_size += len;
}

3、c_str

返回一个C风格的字符串

char* string::c_str() const
{return _str;
}

C风格字符串和string类字符串的区别

void test2()
{string s1("hello");s1 += '\0';s1 += "dafdsaf";cout << s1 << endl;cout << s1.c_str() << endl;
}

上述代码的执行结果是:

C风格字符串以 \0 结尾, 但是string类字符串不一定以 \0 结尾,依赖size()/lenth()。

4、find

在字符串中寻找一个字符,返回第一次出现的下标

npos是string类的静态成员变量,静态成员变量要在类外定义的。我们一般将它设为公共权限,并赋值为-1。

size_t string::find(const char sub, size_t pos) const
{assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == sub)return i;}return npos;
}

在字符串中找字符串

size_t string::find(const char* sub, size_t pos) const
{assert(pos < _size);const char* ptr = strstr(_str + pos, sub);if (ptr == nullptr){return npos;}else{//指针-指针就是指针之间的距离 return ptr - _str;}
}

5、substr

它的作用是在str中从pos位置开始,截取n个字符,然后将其返回。如果不传len,则默认截取从pos开始到结尾的全部字符。 如果 pos + n > _size, 说明要截取的字符大于str的长度,则截取从pos开始到结尾的全部字符。

string substr(size_t pos = 0, size_t len = npos) const;string string::substr(size_t pos, size_t len) const
{assert(pos < _size);size_t reallen = len;//如果从pos开始截取n个字符大于_size的长度,则截取这之间的全部字符if (reallen == npos || reallen + pos > _size){reallen = _size - pos;}string sub;for (size_t i = pos; i < reallen + pos; i++){sub += _str[i];}return sub;
}

6、insert

在指定位置前插入一个字符

string& insert(size_t pos, char ch);string& string::insert(size_t pos, char ch)
{assert(pos <= _size);if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}size_t end = size() + 1;while (end > pos){//把pos后面的字符往后挪_str[end] = _str[end - 1];end--;}_str[pos] = ch;_size++;return *this;
}

在指定位置前插入一个字符串


string& string::insert(size_t pos, const char* ch)
{assert(pos <= _size);//计算要插入的长度size_t len = strlen(ch);//如果要插入的长度加上原本的长度大于_capacity就需要扩容if (_size + len > _capacity){reserve(_size + len);}size_t end = _size + len;while (pos + len <= end){_str[end] = _str[end - len];end--;}//从pos位置开始复制要插入长度个字符strncpy(_str + pos, ch, len);_size += len;return *this;
}

7、erase

从pos开始删除n个字符

void erase(size_t pos, size_t len = npos);void string::erase(size_t pos, size_t len)
{assert(pos < _size);if (len == npos || len >= _size){_str[pos] = '\0';_size = pos;}else{//从pos位置开始复制strcpy(_str + pos, _str + pos + len);//_size减了,对应_str字符数也少了_size -= len;}
}

五、string中重要的运算符重载

1、赋值运算符的重载

编译器默认生成的赋值重载也会导致浅拷贝,所以我们需要实现深拷贝。

string& string::operator==(const string& str)
{//如果两个不是指向同一块空间if (this != &str){//创建一个临时数组char* tmp = new char[str._capacity + 1];strcpy(tmp, str._str);delete[] _str;_str = tmp;_size = str._size;_capacity = str._capacity;}return *this;
}

和拷贝构造函数一样,我们也可以用简便写法来实现赋值运算符的重载

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

2、流插入 <<

流插入和流提取都要在类外定义

ostream& operator<<(ostream& out, const string& s)
{for (size_t i = 0; i < s.size(); i++){out << s[i];}return out;
}

3、流提取 >>

	istream& operator>>(istream& in, string& s){s.clear();char ch;ch = in.get();const size_t N = 32;char buff[N];size_t i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == N - 1){buff[i] = '\0';s += buff;i = 0;}ch = in.get();}buff[i] = '\0';s += buff;}

4、下标访问 []

普通对象:可读可写

char& string::operator[](size_t pos)
{assert(pos < _size);return _str[pos];
}

const对象:可读不可写

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

5、加等一个字符 +=

我们可以直接复用push_back来实现一个字符的加等

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

6、加等字符串 +=

我们可以直接复用append来实现字符串的加等

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

7、大于 >

bool string::operator>(const string& s) const
{return strcmp(_str, s._str) > 0;
}

strcmp通过比较两个字符串,如果s1 > s2,返回大于1的值;如果s1 < s2,返回小于1的值;如果s1 == s2,返回0;

8、等于 ==

bool string::operator==(const string& s) const
{return strcmp(_str, s._str) == 0;
}

9、小于 <

bool string:: operator<(const string& s) const
{return !(_str > s._str) && !(_str == s._str);
}

10、大于等于 >=

bool string::operator>=(const string& s) const
{return !(_str < s._str);
}

11、小于等于 <=

bool string::operator<=(const string& s) const
{return !(_str > s._str);
}

12、不等于 !=

bool string::operator!=(const string& s) const
{return !(_str == s._str);
}

六、迭代器

迭代器作为STL的六大组件之一,它的作用十分重要。而在string中迭代器的本质就是一个char*或const char*的指针。

typedef char* iterator;
typedef const char* const_iterator;
iterator begin()
{return _str;
}
const_iterator begin() const
{return _str;
}
iterator end()
{return _str + _size;
}
const_iterator end() const
{return _str + _size;
}

最后完整代码

string.h

#pragma once#include <iostream>
#include <assert.h>
//#include <string>
#include <string.h>
using namespace std;namespace meng
{class string{public:typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}const_iterator begin() const{return _str;}iterator end(){return _str + _size;}const_iterator end() const{return _str + _size;}string& operator+=(char str);string& operator+=(const char* str);string& operator=(const string& str);char& operator[](size_t pos);char& operator[](size_t pos) const;bool operator>(const string& s) const;bool operator<(const string& s) const;bool operator==(const string& s) const;bool operator>=(const string& s) const;bool operator<=(const string& s) const;bool operator!=(const string& s) const;////string(const char* str = ""):_str(new char[strlen(str) + 1]), _size(strlen(str)), _capacity(strlen(str)){strcpy(_str, str);  //将str中的内容拷贝给_str}void swap(string& s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}string(const string& str):_str(nullptr), _size(0), _capacity(0){//创建一个临时对象string tmp(str._str);swap(tmp);}~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}size_t size() const{return _size;}size_t capacity() const{return _capacity;}void reserve(size_t n);void resize(size_t n, char ch);void clear(){_str[0] = '\0';_size = 0;}bool empty() const{return _size == 0;}void push_back(char ch);void append(const char* str);char* c_str() const;//找一个字符串size_t find(const char* sub, size_t pos = 0) const;size_t find(const char sub, size_t pos = 0) const;string substr(size_t pos = 0, size_t len = npos) const;//insert//在指定位置前插入一个字符string& insert(size_t pos, char ch);//插入一个字符串string& insert(size_t pos, const char* ch);void erase(size_t pos, size_t len = npos);private:char* _str = nullptr;size_t _size = 0;size_t _capacity = 0;static const size_t npos;};ostream& operator<<(ostream& out, const string& s);istream& operator>>(istream& in, string& s);
}

string.c

#define _CRT_SECURE_NO_WARNINGS#include "string.h"namespace meng
{const size_t string::npos = -1;//运算符的重载string& string::operator+=(char str){push_back(str);return *this;}string& string::operator+=(const char* str){append(str);return *this;}//string& string::operator=(const string& str)//{//	//如果两个不是指向同一块空间//	if (this != &str)//	{//		//创建一个临时数组//		char* tmp = new char[str._capacity + 1];//		strcpy(tmp, str._str);//		delete[] _str;//		_str = tmp;//		_size = str._size;//		_capacity = str._capacity;//	}//	return *this;//}string& string::operator=(const string& str){if (this != &str){string tmp(str);swap(tmp);}return *this;}char& string::operator[](size_t pos){assert(pos < _size);return _str[pos];}char& string::operator[](size_t pos) const{assert(pos < _size);return _str[pos];}bool string::operator>(const string& s) const{return strcmp(_str, s._str) > 0;}bool string:: operator<(const string& s) const{return !(_str > s._str) && !(_str == s._str);}bool string::operator==(const string& s) const{return strcmp(_str, s._str) == 0;}bool string::operator>=(const string& s) const{return !(_str < s._str);}bool string::operator<=(const string& s) const{return !(_str > s._str);}bool string::operator!=(const string& s) const{return !(_str == s._str);}ostream& operator<<(ostream& out, const string& s){for (size_t i = 0; i < s.size(); i++){out << s[i];}return out;}istream& operator>>(istream& in, string& s){s.clear();char ch;ch = in.get();const size_t N = 32;char buff[N];size_t i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == N - 1){buff[i] = '\0';s += buff;i = 0;}ch = in.get();}buff[i] = '\0';s += buff;}////void string::reserve(size_t n){if (n > _capacity){//创建一个临时变量,开n + 1个空间char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str; //将原空间删除_str = tmp; // 将临时变量的空间给str_capacity = n;  // 预留多少字符给_capacity}}void string::resize(size_t n, char ch){if (n > _size){//先检查要不要扩容reserve(n);for (size_t i = _size; i < n; i++){_str[i] = ch;}_size = n;_str[_size] = '\0';}else{_str[_size] = '\0';_size = n;}}void string::push_back(char ch){if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_size++;_str[_size] = '\0';}void string::append(const char* str){//先计算追加字符的个数size_t len = strlen(str);//如果 len + _size > _capacity 就需要扩容if (_capacity < len + _size){//重新申请预留空间reserve(len + _size);}//从_str + _size出位置开始复制strcpy(_str + _size, str);_size += len;}char* string::c_str() const{return _str;}size_t string::find(const char sub, size_t pos) const{assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == sub)return i;}return npos;}size_t string::find(const char* sub, size_t pos) const{assert(pos < _size);const char* ptr = strstr(_str + pos, sub);if (ptr == nullptr){return npos;}else{//指针-指针就是指针之间的距离 return ptr - _str;}}string string::substr(size_t pos, size_t len) const{assert(pos < _size);size_t reallen = len;//如果从pos开始截取n个字符大于_size的长度,则截取这之间的全部字符if (reallen == npos || reallen + pos > _size){reallen = _size - pos;}string sub;for (size_t i = pos; i < reallen + pos; i++){sub += _str[i];}return sub;}string& string::insert(size_t pos, char ch){assert(pos <= _size);if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}size_t end = size() + 1;while (end > pos){//把pos后面的字符往后挪_str[end] = _str[end - 1];end--;}_str[pos] = ch;_size++;return *this;}string& string::insert(size_t pos, const char* ch){assert(pos <= _size);//计算要插入的长度size_t len = strlen(ch);//如果要插入的长度加上原本的长度大于_capacity就需要扩容if (_size + len > _capacity){reserve(_size + len);}size_t end = _size + len;while (pos + len <= end){_str[end] = _str[end - len];end--;}//从pos位置开始复制要插入长度个字符strncpy(_str + pos, ch, len);_size += len;return *this;}void string::erase(size_t pos, size_t len){assert(pos < _size);if (len == npos || len >= _size){_str[pos] = '\0';_size = pos;}else{//从pos位置开始复制strcpy(_str + pos, _str + pos + len);//_size减了,对应_str字符数也少了_size -= len;}}}

test.c

#define _CRT_SECURE_NO_WARNINGS#include "string.h"void test()
{string str("hello world");for (auto e : str)cout << e << ' ';cout << endl;//string::iterator it = str.begin()auto it = str.begin();while (it != str.end()){cout << *it << ' ';++it;}cout << endl;for (auto e : str){e += 2;cout << e << ' ';}cout << endl;cout << str << endl;//string::reverse_iterator a = str.rbegin();auto a = str.rbegin();while (a != str.rend()){cout << *a << ' ';++a;}cout << endl;
}namespace meng
{void test1(){string s1("hello world");cout << s1.size() << " " << s1.capacity() << endl;s1.reserve(16);cout << s1.capacity() << endl;//s1.resize(20, 'h');//cout << s1.c_str() << endl;//cout << s1.size() << " " << s1.capacity() << endl;//cout << s1.empty() << endl;s1.push_back('h');cout << s1.c_str() << endl;cout << s1.size() << " " << s1.capacity() << endl;s1.append("xxxxx");cout << s1.size() << " " << s1.capacity() << endl;cout << s1.c_str() << endl;cout << s1.find("xxx", 0) << endl;cout << s1.find('o', 0) << endl;string s2 = s1.substr(4, 5);cout << s2.c_str() << endl;string s3 = s1.insert(3, 'a');cout << s3.c_str() << endl;string s4 = s1.insert(3, "aaaaaa");cout << s4.c_str() << endl;s4.erase(3, 6);cout << s4.c_str() << endl;string s5 = s1; //拷贝构造cout << s5.c_str() << endl;cout << s1 << endl;cout << s4 << endl;cout << (s4 == s1) << endl;cout << (s4 != s1) << endl;cout << (s4 > s1) << endl;cout << (s4 < s1) << endl;}}void test2()
{string s1("hello");s1 += '\0';s1 += "dafdsaf";cout << s1 << endl;cout << s1.c_str() << endl;
}int main()
{//test();meng::test1();//test2();return 0;
}

http://www.dtcms.com/wzjs/342147.html

相关文章:

  • 宿迁做网站哪家好百度搜索网址
  • 那些网站可以做淘宝店铺推广营销和销售的区别
  • openwrt做网站如何推广自己的微信号
  • .net网站制作百度资讯
  • 做ppt图片网站 知乎小程序开发教程全集免费
  • 域名申请好了 要怎么做网站百度招聘官网首页
  • 乌鲁木齐住房和城乡建设厅网站关键词优化师
  • 淄博外贸网站建设公司深企在线
  • 用源码做网站app推广平台网站
  • 财政网站平台建设不足深圳网络推广有几种方法
  • 施甸网站建设跨境电商网站
  • 兰州网站公司百度商务合作电话
  • 做网站需要硬件软件百度智能云
  • 婚庆公司名字大全广东网络优化推广
  • 长治网站制作公司深圳网站营销seo费用
  • wordpress和apache什么是seo搜索引擎优化
  • 北京做网站设计招聘电子商务网站建设论文
  • 重庆seo哪个强衡阳seo快速排名
  • 百度推广网站建设凡科网微信小程序
  • 做网站设计公司百度代运营公司
  • 网站维护要学多久百度怎样免费发布信息
  • 网站建设nuoweb长沙seo平台
  • 苏州建行网站首页优化网址
  • 深圳做网站的公司360推广助手
  • 已经注册了域名怎么做简单的网站永久观看不收费的直播
  • 南宁企业自助建站个人网站制作
  • 合肥 电子商务 网站建设搜易网服务内容
  • 企业网站的开发与运维日常提升seo搜索排名
  • 伊利网站建设水平评价外贸网络营销推广
  • 农机公司网站建设打广告推广怎么做