【C++】—— string模拟实现

前言:

        学习了string的使用,总感觉了解不是很深厚;自己模拟实现string类来帮助自己理解。

        这里只是实现了一部分内容(并没有实现完整的string类)。

先来实现string类里面的成员变量:

#include<iostream>
namespace HL
{class string{public:private:char* _str;size_t _size;size_t _capacity;const static size_t npos;};const size_t HL::string::npos = -1;
}

一、string默认成员函数(构造、析构、赋值运算符重载)

        1.1、构造函数

1> 默认构造

        默认构造函数就是不需要传参的构造函数;这里实现就开辟一个字符的空间存放 '\0'即可(_capacity不包括 '\0' )。

string(){_str = new char[1];_str[0] = '\0';_size = 0;_capacity = 0;}

2> 拷贝构造

        拷贝构造,在实现时需要注意:是深拷贝,而不是浅拷贝(值拷贝)。

深拷贝(深拷贝简单来说就是,要开辟一块新的空间,把原空间里的值拷贝到新的空间里)。

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

3> 其他构造

        其他构造函数就有很多了,这里就实现以下这几个:

        string (const char* s);

		string(const char* s){size_t len = strlen(s);_str = new char[len + 1];memcpy(_str, s, len + 1);_size = len;_capacity = len;}

        string (const char* s, size_t n);

		string(const char* s, size_t n){size_t len = strlen(s);if (n > len){n = len;}_str = new char[n + 1];memcpy(_str, s, n);_str[n] = '\0';_size = n;_capacity = n;}

        string (size_t n, char c);

		string(size_t n, char c){_str = new char[n + 1];for (size_t i = 0; i < n; i++){_str[i] = c;}_str[n] = '\0';_size = n;_capacity = n;}

        1.2、析构函数

        析构函数比较简单,释放开辟的资源即可;

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

        1.3、赋值运算符重载     

        赋值运算符有3个重载,这里就一一实现:

        string& operator= (const string& str );

实现这个有很多种方法,

        可以释放原空间,再开辟新的空间,将数据拷贝到新的空间中去

		string& operator=(const string& str){delete[] _str;_str = new char[str._capacity];memcpy(_str, str._str, str._size + 1);_size = str._size;_capacity = str._capacity;return *this;}

可以调用拷贝构造,构造一个tmp、再将tmp与*this 中的值进行交换(要实现交换函数)

template <typename T>
void Swap(T& x, T& y)
{T tmp = x;x = y;y = tmp;
}
string& operator= (const string& str)
{string tmp(str);Swap(_str, tmp._str);Swap(_size, tmp._size);Swap(_capacity, tmp._capacity);return *this;
}

这里如果已经实现string类swap成员函数,就可以直接调用。

        string& operator= (const char* s );        

		/*string& operator= (const char* s){size_t len = strlen(s);delete[] _str;_str = new char[len + 1];memcpy(_str, s, len + 1);_size = _capacity = len;return *this;}*/string& operator= (const char* s){string tmp(s);Swap(_str, tmp._str);Swap(_size, tmp._size);Swap(_capacity, tmp._capacity);return *this;}

        string& operator= (char c );

		string& operator= (char c){delete[] _str;_str = new char[2];_str[0] = c;_str[1] = '\0';_size = _capacity = 1;return *this;}

二、元素访问与迭代器

        2.1、迭代器

        迭代器,虽然在string类中使用的不是很多,但在后面的容器中有大用处。

        (在string类中就可以简单的理解成指针)。

		//迭代器typedef 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);}

        实现了迭代器之后,范围for这个语法糖就可以使用了(底层就是迭代器)。        

        2.2、下标访问元素

        实现下标访问,就是 [ ]运算符重载。

		//下标访问 [ ]char& operator[] (size_t pos){assert(pos >= _size);return *(_str + pos);}const char& operator[] (size_t pos) const{assert(pos >= _size);return *(_str + _size);}

        at函数和 [ ] 运算符重载原理一样,这里就不重复写了。

三、增删查改

        在实现增之前,要先实现一个函数,就是调整空间大小的(扩容来用)。

		//扩容void reserve(size_t n){if (n > _capacity){char* s = new char[n + 1];memcpy(s, _str, _size);delete[] _str;_str = s;_capacity = n;}}


        增删这里就实现这些成员函数。

        1、push_back  、append 、operator+=

append重载比较多,这里就实现其中的几个。

		//扩容void reserve(size_t n){if (n > _capacity){char* s = new char[n + 1];memcpy(s, _str, _size);delete[] _str;_str = s;_capacity = n;}}//增void push_back(char c){if (_size >= _capacity){reserve((_capacity == 0) ? 4 : 2 * _capacity);}_str[_size] = c;_size++;_str[_size] = '\0';}void append(const string& str){size_t n = _size + str._size;if (n > _capacity){reserve(n);}for (int i = 0; i < str._size; i++){_str[_size + i] = str._str[i];}_size += str._size;_str[_size] = '\0';}void append(const char* s){size_t len = strlen(s);int n = _size + len;if (n > _capacity){reserve(n);}for (int i = 0; i < len; i++){_str[_size + i] = s[i];}_size = n;_str[_size] = '\0';}void append(size_t n, char c){if (_size + n > _capacity){reserve(_size + n);}for (int i = 0; i < n; i++){_str[_size + i] = c;}_size += n;_str[_size] = '\0';}string& operator+=(const string& str){this->append(str);return *this;}string& operator+=(const char* s){this->append(s);return *this;}string& operator+=(char c){this->push_back(c);return *this;}

        2、insert、erase

        insert重载也比较多,比较冗余;这里也只实现其中的一部分;

        erase这里只实现一个

//insert 、erase
void insert(size_t pos, const string& str)
{assert(pos >= 0 && pos < _size);size_t len = str._size;size_t n = _size + len;if (n > _capacity){reserve(n);}//挪动数据for (size_t i = n; i >= pos + len; i--){_str[i] = _str[i - len];}memcpy(_str + pos, str._str, str._size);_size += str._size;_str[_size] = '\0';
}
void insert(size_t pos, const char* s)
{assert(pos >= 0 && pos < _size);size_t len = strlen(s);size_t n = _size + len;if (n > _capacity){reserve(n);}//挪动数据for (size_t i = n; i >= pos + len; i--){_str[i] = _str[i - len];}memcpy(_str + pos, s, len);_size += len;_str[_size] = '\0';
}
void insert(size_t pos, size_t n, char c)
{assert(pos >= 0 && pos < _size);if (_size + n > _capacity){reserve(_size + n);}//挪动数据for (size_t i = _size+n; i >= pos + n; i--){_str[i] = _str[i - n];}for (size_t i = 0; i < n; i++){_str[pos + i] = c;}_size += n;_str[_size] = '\0';
}
void erase(size_t pos, size_t len = npos)
{assert(pos >= 0 && pos < _size);if (len == npos){_str[0] = '\0';_size = 0;return;}for (size_t i = pos; (len + i) < _size; i++){_str[i] = _str[i + len];}_size -= len;_str[_size] = '\0';
}

        3、find

		//findsize_t find(const string& str, size_t pos = 0){assert(pos >= 0 && pos < _size);char* tmp = strstr(_str + pos, str._str);if (tmp == nullptr){return -1;}return tmp - _str;}size_t find(const char* s, size_t pos = 0){assert(pos >= 0 && pos < _size);char* tmp = strstr(_str + pos, s);if (tmp == nullptr){return -1;}return tmp - _str;}size_t find(char c, size_t pos = 0){assert(pos >= 0 && pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == c){return i;}}return -1;}

        4、swap

        swap作为string的成员函数,交换两个string类类型的对象。

		//swapvoid swap(string& str){Swap(_str, str._str);Swap(_size, str._size);Swap(_capacity, str._capacity);}

        这里swap函数内部也可以调用库里面的swap模版(这里我自己写了一个模版Swap)

有了swap函数,上面赋值运算符重载中就可以这样写了:

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

四、字符串操作函数

        1、c_str

        c_str()函数返回string类对象中的字符串;

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

        2、substr

        获得,sting对象中字符串的子串。

//substr
string substr(size_t pos = 0, size_t len = npos) const
{assert(pos >= 0 && pos < _size);size_t n = 0;if (len == npos || pos + len > _size){n = _size - pos;}else{n = len;}string ret;for (size_t i = 0; i < n; i++){ret += _str[pos + i];}return ret;
}

五、其他成员函数

        

        这里max_size是返回容器可以容纳的最大元素的数量,这里就不进行实现了。

reserve在增加元素前已经实现了。(扩容)

//其他成员函数
size_t size() const
{return _size;
}
size_t length()const
{return _size;
}
size_t capacity()const
{return _capacity;
}
void clear()
{_str[0] = '\0';_size = 0;
}
bool empty()const
{return _size == 0;
}
void resize(size_t n)
{if (n > _capacity){reserve(n);}_size = n;_str[_size] = '\0';
}
void resize(size_t n, char c)
{if (n > _capacity){reserve(n);}for (size_t i = _size; i < n; i++){_str[i] = c;}_size = n;_str[_size] = '\0';
}

        

六、流插入、流提取

        因为成员函数有一个隐藏的this指针,会和istream 和istream 类对象抢占第一个参数的位置,所以我们不能将流插入和流提取写成string类的成员函数。

        string中实现了访问元素方成员函数,就可以不将流插入、流提取写成string类的友元函数。

        1、流插入运算符重载

	std::ostream& operator<<(std::ostream& out, const HL::string& str){//for (int i = 0; i < str.size(); i++)//{//	out << str[i];//}//return out;for (auto ch : str){out << ch;}return out;}

        2、流提取运算符重载

        1、 s.clear()清理缓冲区(上次cin流提取的剩余);

        2、 创建一个数组,防止多次去开空间(输入到128或者输入结束(‘ ’或者‘\n’)才添加到str中)。

        3、下面的代码处理缓冲区的空格。

        char ch;
        ch = in.get();
        while (ch == ' ' || ch == '\n')
        {
            ch = in.get();
        }

        4、最后循环里if是遇到空格或者换行结束,将s中输入添加到s中,末尾添加'\0'。

       

std::istream& operator>>(std::istream& in, HL::string& str)
{char s[128] = { 0 };char ch;ch = in.get();while (ch == ' ' || ch == '\n'){ch = in.get();}str.clear();int i = 0;while (ch != '\n'){s[i] = ch;i++;if (i == 127){s[i] = '\0';str += s;i = 0;}ch = in.get();}if (i){str += s;}return in;
}

HL :: string 源码
 

#pragma once
#include<iostream>
#include<cassert>template <typename T>
void Swap(T& x, T& y)
{T tmp = x;x = y;y = tmp;
}
namespace HL
{class string{friend std::ostream& operator<<(std::ostream& out, const HL::string& str);friend std::istream& operator>>(std::istream& in, HL::string& str);public://构造函数/*string(){_str = new char[1];_str[0] = '\0';_size = 0;_capacity = 0;}string(char ch){_str = new char[1];_str[0] = ch;_size = 0;_capacity = 0;}*/string(char ch = '\0'){_str = new char[2];_str[0] = ch;_str[1] = '\0';_size = 1;_capacity = 1;}string(const char* s){size_t len = strlen(s);_str = new char[len + 1];memcpy(_str, s, len + 1);_size = len;_capacity = len;}string(const char* s, size_t n){size_t len = strlen(s);if (n > len){n = len;}_str = new char[n + 1];memcpy(_str, s, n);_str[n] = '\0';_size = n;_capacity = n;}string(const string& str){_str = new char[str._capacity + 1];memcpy(_str, str._str, str._size + 1);_size = str._size;_capacity = str._capacity;}string(size_t n, char c){_str = new char[n + 1];for (size_t i = 0; i < n; i++){_str[i] = c;}_str[n] = '\0';_size = n;_capacity = n;}~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}/*string& operator=(const string& str){delete[] _str;_str = new char[str._capacity];memcpy(_str, str._str, str._size + 1);_size = str._size;_capacity = str._capacity;return *this;}*//*string& operator= (const string& str){string tmp(str);Swap(_str, tmp._str);Swap(_size, tmp._size);Swap(_capacity, tmp._capacity);return *this;}*/string& operator= (const string& str){string tmp(str);swap(tmp);return *this;}/*string& operator= (const char* s){size_t len = strlen(s);delete[] _str;_str = new char[len + 1];memcpy(_str, s, len + 1);_size = _capacity = len;return *this;}*/string& operator= (const char* s){string tmp(s);Swap(_str, tmp._str);Swap(_size, tmp._size);Swap(_capacity, tmp._capacity);return *this;}string& operator= (char c){delete[] _str;_str = new char[2];_str[0] = c;_str[1] = '\0';_size = _capacity = 1;return *this;}//string& operator= (char c)//{//	string tmp(c);//	Swap(_str, tmp._str);//	Swap(_size, tmp._size);//	Swap(_capacity, tmp._capacity);//	return *this;//}//迭代器typedef 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);}//下标访问 [ ]char& operator[] (size_t pos){assert(pos >= 0 && pos < _size);return *(_str + pos);}const char& operator[] (size_t pos) const{assert(pos >= 0 && pos < _size);return *(_str + _size);}//扩容void reserve(size_t n){if (n > _capacity){char* s = new char[n + 1];memcpy(s, _str, _size);delete[] _str;_str = s;_capacity = n;}}//增void push_back(char c){if (_size >= _capacity){reserve((_capacity == 0) ? 4 : 2 * _capacity);}_str[_size] = c;_size++;_str[_size] = '\0';}void append(const string& str){size_t n = _size + str._size;if (n > _capacity){reserve(n);}for (int i = 0; i < str._size; i++){_str[_size + i] = str._str[i];}_size += str._size;_str[_size] = '\0';}void append(const char* s){size_t len = strlen(s);size_t n = _size + len;if (n > _capacity){reserve(n);}for (int i = 0; i < len; i++){_str[_size + i] = s[i];}_size = n;_str[_size] = '\0';}void append(size_t n, char c){if (_size + n > _capacity){reserve(_size + n);}for (int i = 0; i < n; i++){_str[_size + i] = c;}_size += n;_str[_size] = '\0';}string& operator+=(const string& str){this->append(str);return *this;}string& operator+=(const char* s){this->append(s);return *this;}string& operator+=(char c){this->push_back(c);return *this;}//insert 、erasevoid insert(size_t pos, const string& str){assert(pos >= 0 && pos < _size);size_t len = str._size;size_t n = _size + len;if (n > _capacity){reserve(n);}//挪动数据for (size_t i = n; i >= pos + len; i--){_str[i] = _str[i - len];}memcpy(_str + pos, str._str, str._size);_size += str._size;_str[_size] = '\0';}void insert(size_t pos, const char* s){assert(pos >= 0 && pos < _size);size_t len = strlen(s);size_t n = _size + len;if (n > _capacity){reserve(n);}//挪动数据for (size_t i = n; i >= pos + len; i--){_str[i] = _str[i - len];}memcpy(_str + pos, s, len);_size += len;_str[_size] = '\0';}void insert(size_t pos, size_t n, char c){assert(pos >= 0 && pos < _size);if (_size + n > _capacity){reserve(_size + n);}//挪动数据for (size_t i = _size+n; i >= pos + n; i--){_str[i] = _str[i - n];}for (size_t i = 0; i < n; i++){_str[pos + i] = c;}_size += n;_str[_size] = '\0';}void erase(size_t pos, size_t len = npos){assert(pos >= 0 && pos < _size);if (len == npos){_str[0] = '\0';_size = 0;return;}for (size_t i = pos; (len + i) < _size; i++){_str[i] = _str[i + len];}_size -= len;_str[_size] = '\0';}//findsize_t find(const string& str, size_t pos = 0){assert(pos >= 0 && pos < _size);char* tmp = strstr(_str + pos, str._str);if (tmp == nullptr){return -1;}return tmp - _str;}size_t find(const char* s, size_t pos = 0){assert(pos >= 0 && pos < _size);char* tmp = strstr(_str + pos, s);if (tmp == nullptr){return -1;}return tmp - _str;}size_t find(char c, size_t pos = 0){assert(pos >= 0 && pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == c){return i;}}return -1;}//swapvoid swap(string& str){Swap(_str, str._str);Swap(_size, str._size);Swap(_capacity, str._capacity);}//c_strconst char* c_str() const{return _str;}	char* c_str(){return _str;}//substrstring substr(size_t pos = 0, size_t len = npos) const{assert(pos >= 0 && pos < _size);size_t n = 0;if (len == npos || pos + len > _size){n = _size - pos;}else{n = len;}string ret;for (size_t i = 0; i < n; i++){ret += _str[pos + i];}return ret;}//其他成员函数size_t size() const{return _size;}size_t length()const{return _size;}size_t capacity()const{return _capacity;}void clear(){_str[0] = '\0';_size = 0;}bool empty()const{return _size == 0;}void resize(size_t n){if (n > _capacity){reserve(n);}_size = n;_str[_size] = '\0';}void resize(size_t n, char c){if (n > _capacity){reserve(n);}for (size_t i = _size; i < n; i++){_str[i] = c;}_size = n;_str[_size] = '\0';}private:char* _str;size_t _size;size_t _capacity;const static size_t npos;};const size_t HL::string::npos = -1;std::ostream& operator<<(std::ostream& out, const HL::string& str){//for (int i = 0; i < str.size(); i++)//{//	out << str[i];//}//return out;for (auto ch : str){out << ch;}return out;}std::istream& operator>>(std::istream& in, HL::string& str){char s[128] = { 0 };char ch;ch = in.get();while (ch == ' ' || ch == '\n'){ch = in.get();}str.clear();int i = 0;while (ch != '\n'){s[i] = ch;i++;if (i == 127){s[i] = '\0';str += s;i = 0;}ch = in.get();}if (i){str += s;}return in;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/879968.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PyCharm的使用

PyCharm的入门使用教程 下载和安装PyCharm&#xff1a; 首先&#xff0c;访问JetBrains官方网站&#xff08;https://www.jetbrains.com/pycharm/&#xff09;下载PyCharm的最新版本。根据您的操作系统选择合适的版本进行下载。 安装完成后&#xff0c;打开PyCharm。 创建新…

记录一次显卡驱动安装

1. 驱动安装 1.1. 查看适合的版本 apt-get update ubuntu-drivers devices输出结果&#xff1a; 1.2. 安装合适的驱动版本 根据上面输出的内容 apt-get install nvidia-driver-545完成后重启 reboot查看新的驱动 nvidia-smi2. 安装/升级cuda 在nvidia-smi中显示的CUDA…

hive分区详细教程

为什么要分区&#xff1f; 为了提高sql的查询效率 比如&#xff1a; select * from orders where create_date20230826; 假如数据量比较大&#xff0c;这个sql就是全表扫描&#xff0c;速度肯定慢。 可以将数据按照天进行分区&#xff0c;一个分区就是一个文件夹&#xff0c;当…

中序遍历二叉树全过程图解

文章目录 中序遍历图解总结 中序遍历图解 首先看下中序遍历的代码&#xff0c;其接受一个根结点root作为参数&#xff0c;判断根节点是否为nil&#xff0c;不为nil则先递归遍历左子树。 func traversal(root *TreeNode,res *[]int) {if root nil {return}traversal(root.Lef…

华为HarmonyOS地图服务 5 - 利用UI控件和手势进行地图交互

场景介绍 本章节将向您介绍如何使用地图的手势。 Map Kit提供了多种手势供用户与地图之间进行交互,如缩放、滚动、旋转和倾斜。这些手势默认开启,如果想要关闭某些手势,可以通过MapComponentController类提供的接口来控制手势的开关。 接口说明 以下是地图的控件和手势相…

【LLM多模态】文生视频评测基准VBench

note VBench的16个维度自动化评估指标代码实践&#xff08;待完成&#xff09;16个维度的prompt举例人类偏好标注&#xff1a;计算VBench评估结果与人类偏好之间的相关性、用于DPO微调 文章目录 note一、相关背景二、VBench评测基准概述&#xff1a;论文如何解决这个问题&…

Java免税购物商城:Spring Boot技术实现

第二章 系统开发关键技术 2.1 JAVA技术 Java主要采用CORBA技术和安全模型&#xff0c;可以在互联网应用的数据保护。它还提供了对EJB&#xff08;Enterrise JavaBeans&#xff09;的全面支持&#xff0c;java servlet AI&#xff0c;JS&#xff08;java server ages&#xff09…

RNN的反向传播

目录 1.RNN网络&#xff1a;通过时间反向传播(through time back propagate TTBP) 2.RNN梯度分析 2.1隐藏状态和输出 2.2正向传播&#xff1a; 2.3反向传播&#xff1a; 2.4问题瓶颈&#xff1a; 3.截断时间步分类&#xff1a; 4.截断策略比较 5.反向传播的细节 ​编辑…

植物病害识别系统Python+卷积神经网络算法+图像识别+人工智能项目+深度学习项目+计算机课设项目+Django网页界面

一、介绍 植物病害识别系统。本系统使用Python作为主要编程语言&#xff0c;通过收集水稻常见的四种叶片病害图片&#xff08;‘细菌性叶枯病’, ‘稻瘟病’, ‘褐斑病’, ‘稻瘟条纹病毒病’&#xff09;作为后面模型训练用到的数据集。然后使用TensorFlow搭建卷积神经网络算…

【后端开发】JavaEE初阶—线程的理解和编程实现

前言&#xff1a; &#x1f31f;&#x1f31f;本期讲解多线程的知识哟~~~&#xff0c;希望能帮到屏幕前的你。 &#x1f308;上期博客在这里&#xff1a;【后端开发】JavaEE初阶——计算机是如何工作的&#xff1f;&#xff1f;&#xff1f;-CSDN博客 &#x1f308;感兴趣的小伙…

Tomcat中BIO和NIO的区别(Tomcat)

BIO Tomcat中BIO的模型和理论很简单&#xff0c;例图如下 1.Acceptor线程死循环阻塞接收客户端的打过来的socket请求 2.接收到请求之后打包成一个SocketProcessor&#xff08;Runnable&#xff09;&#xff0c;扔到线程池中读取/写入数据 参数配置 1.Acceptor默认线程是1&#…

【Godot4.x】Mesh相关知识总结

概述 很早之前发布过一篇关于几何体程序生成的文章&#xff0c;当时对于三角面和网格的构造其实还没有特别深入的认识&#xff0c;直到自己脑海里想到用二维数组和点更新的方式构造2D类型的多边形Mesh结构&#xff0c;也意识到在Godot中其实Mesh不仅是3D网格&#xff0c;也可以…

分子动力学工具篇二:Sobtop的安装与使用

文章目录 1. Sobtop的介绍1. Sobtop 的功能和特点2.主要应用场景 2.3.常见问题及解决方法 1. Sobtop的介绍 Sobtop 是一个用于自动生成分子拓扑文件的工具&#xff0c;特别是为 GROMACS 分子动力学模拟准备拓扑结构和参数。它的设计目标是通过自动化过程生成小分子、聚合物或其…

msvcp140.dll0丢失的解决方法,总结6种靠谱的解决方法

再使用计算机的过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp140.dll丢失”。这个问题可能会影响到我们的正常使用&#xff0c;因此需要及时解决。经过一段时间的学习和实践&#xff0c;我总结了以下六种靠谱的解决方法&#xff0c;希望对大家…

Flask-WTF的使用

组织一个 Flask 项目通常需要遵循一定的结构&#xff0c;以便代码清晰、可维护。下面是一个典型的 Flask 项目结构&#xff1a; my_flask_app/ │ ├── app/ │ ├── __init__.py │ ├── models.py │ ├── views.py │ ├── forms.py │ ├── templat…

【HTTP】构造HTTP请求和状态码

状态码 用于响应中&#xff0c;表示响应的结果如何 正确&#xff1f;错误&#xff1f;什么原因&#xff1f; HTTP 中的状态码都是标准约定好的 200 OK 成功了&#xff0c;一切顺利 在抓包到的响应中 404 Not Found 访问的资源&#xff08;URL 中的路径&#xff09;没找…

数据结构之线性表——LeetCode:707. 设计链表,206. 反转链表,92. 反转链表 II

707. 设计链表 题目描述 707. 设计链表 你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果是双向链表&#xff0c;则…

小程序——生命周期

文章目录 运行机制更新机制生命周期介绍应用级别生命周期页面级别生命周期组件生命周期生命周期两个细节补充说明总结 运行机制 用一张图简要概述一下小程序的运行机制 冷启动与热启动&#xff1a; 小程序启动可以分为两种情况&#xff0c;一种是冷启动&#xff0c;一种是热…

低代码门户技术:构建高效应用的全新方式

什么是低代码门户技术&#xff1f; 低代码门户技术是一种利用低代码平台构建企业门户网站或应用的技术。门户通常是企业内部和外部用户访问信息和应用的集中平台。低代码门户技术通过图形化界面和预置组件&#xff0c;允许用户快速搭建和定制这些门户平台&#xff0c;而无需深…

CefSharp_Vue交互(Element UI)_WinFormWeb应用(3)---通过页面锁屏和关机(含示例代码)

一、预览 实现功能:通过vue标题栏按钮锁屏和关机 1.1 预览 1.2 代码 锁屏代码csharp LockWorkStation() 关机代码chsharp 注意vue代码参数和此参数一致(0/1/2) 方法ExitWindowsEx()