【C++】string模拟

string讲解:【C++】String类-CSDN博客

基本框架

#pragma once
#include <iostream>
using namespace std;
​
namespace wzf
{class string{public:// 默认构造函数string(): _str(new char[1]), _size(0), _capacity(0){_str[0] = '\0'; // 在没有内容时仍要有终止符'\0'}
​// 构造函数,接收一个 C 风格字符串// 注意:假设传入的字符串以终止符'\0'结尾,否则可能导致程序崩溃string(const char *str): _size(strlen(str)){_capacity = _size;//new 一个capacity+1的空间_str = new char[_capacity + 1]; // +1 是为了容纳终止符'\0'strcpy(_str, str);//拷贝}
/*td::string 类型使用内部管理字符串的长度,并且在内部存储中维护了字符串的长度信息,不需要依赖 null 字符来表示字符串的结束,而在 C 语言中,字符串是作为 null 结尾的字符数组进行存储的,每个字符串最后都以一个值为 0 的字符 ‘\0’ 结尾
*/// 返回字符串的 C 风格表示const char *c_str(){return _str;}//返回字符串长度size_t size() const{return _size;}size_t capcacity() const{return _capacity;}
​
​private:char *_str;     // 存储字符串的字符数组指针size_t _size;   // 字符串的长度(不包括终止符'\0')size_t _capacity;   // 字符数组的容量};
}

将string()与string(const)进行复用:

string(const char *str=nulptr);//❌
string应该是遇到'\0'停止否则会崩
string(const char* str='\0');//❌
默认参数值是 '\0',即空字符。
然而,由于 str 是 const char* 类型,而不是 char 类型,因此在这种情况下,'\0' 被解释为一个整数 0,
而不是一个空字符。这可能导致编译错误或未定义行为。
string(const char *str="\0")// ≠‘\0’
一个空字符串也是一个有效的字符串,它不需要以 '\0' 的形式进行显式表示,也就是说,一个空字符串已经包含了一个空字符。

因此,当我们在下面的类构造函数中将空字符串 "" 传递给 const char* 类型的形参 str 时 , 编译器会自动将其转换为一个空字符 '\0'。->

string(const char *str = "") // 可以不写 "\0": _size(strlen(str))
{_capacity = _size== 0 ? 3 : _size;_str = new char[_capacity + 1]; //+1-> '\0'strcpy(_str, str);
}

成员函数重载 operator[]

对[ ]进行重载,以便直接用[]进行调用

//给const对象调用
const char &operator[](size_t pos) const
{assert(pos < _size);return _str[pos];
}
//给普通对象,构成函数重载
char &operator[](size_t pos)
{assert(pos < _size);return _str[pos];
}

对此处const使用有疑问的可转看改文章,文章中详细讲解了const在类中的用法: 【C++】const与类(const修饰函数的三种位置)-CSDN博客

成员函数重载 operator= //string s3=s1

string &operator=(const string &s) // string& 为返回类型,表示返回值是当前实例的引用
{if (this != &s) //s1≠s1 避免自我赋值{char *tmp = new char[s._capacity + 1]; // 申请新的字符数组strcpy(tmp, s._str); // 复制待赋值字符串// 释放原来的空间,销毁原来空间,防止s1空间小于s2,或s1>s2造成空间浪费,避免内存泄漏和空间浪费 delete[] _str; _str = tmp; // 更新字符串指针_size = s._size; // 更新字符串长度_capacity = s._capacity; // 更新字符串容量}return *this; // 返回当前实例的引用
}

测试:

void test_string2()
{string s1;string s2("Hello Word");/*string s3(s2); // 拷贝构造(浅拷贝/值拷贝) 用系统自动生成的拷贝构造1.两个用的是同一个空间. 2.会析构两次*/// 深拷贝:string s3(s2);
​cout << s2.c_str() << endl;cout << s3.c_str() << endl;s2[0]++;cout << s2.c_str() << endl;cout << s3.c_str() << endl;cout << "===" << endl;
​s1 = s3; // 调用 s1 的 operator= 函数,将 s2 赋值给 s1cout << s3.c_str() << endl;cout << s1.c_str() << endl;
}

拷贝构造:

深浅拷贝的区别:

浅拷贝是指在进行复制操作时,只复制对象的引用或指针,而不复制对象本身。这意味着原对象和拷贝对象共享同一份数据,当其中一个对象修改了数据时,另一个对象也会受到影响

深拷贝是指在进行复制操作时,完全复制对象和对象的数据,创建一个新的对象并复制数据。这意味着原对象和拷贝对象拥有各自独立的数据,彼此之间互不影响

 

// 深拷贝 s3
string(const string &s): _size(s._size), _capacity(s._capacity)
{_str = new char[s._capacity + 1];strcpy(_str, s._str);
}

测试:

void test_string1()
{string s1;string s2("HelloWord");
​cout << s1.c_str() << endl;cout << s2.c_str() << endl;
​s2[0]++;cout << s1.c_str() << endl;cout << s2.c_str() << endl;
}

迭代器

begin() && end()

 

typedef char* iterator; // 定义了名为 iterator 的 char* 类型别名
typedef const char* const_iterator; // 定义了名为 const_iterator 的 const char* 类型别名
​
iterator begin() // 返回指向首字符的迭代器
{return _str;
}
​
iterator end() // 返回指向尾字符(终止符)后面的迭代器
{return _str + _size;
}
​
const_iterator rbegin() const // 返回指向尾字符(终止符)的迭代器
{return _str;
}
​
const_iterator rend() const // 返回指向首字符前面位置的迭代器
{return _str + _size;
}

调用:

string::iterator it=s1.begin();
while (it!=s1.end())
{cout<<*it<<" ";++it;
}
cout<<endl;
​
const_iterator rit = s.begin();
while (rit != s.end())
{cout << *rit << " ";++rit;
}

运算符重载

字符串比较的是相对应字符相应的asscall值

// 不改变数据的都建议加上const
bool operator>(const string &s) const
{return strcmp(_str, s._str) > 0;
}
​
bool operator==(const string &s) const
{return strcmp(_str, s._str) == 0;
}
​
bool operator>=(const string &s) const
{return *this > s || *this == s;
}
​
bool operator<(const string &s) const
{return !(*this >= s);
}
bool operator<=(const string &s) const
{return !(*this > s);
}
​
bool operator!=(const string &s) const
{return !(*this == s);
}

测试:

string s1("Hello Word");
string s2("Hello Word");
string s3("Iello Word");
​
cout<<(s1==s2)<<endl;//1
cout<<(s1>=s3)<<endl;//0
cout<<(s1<=s3)<<endl;//1
cout<<(s1!=s3)<<endl;//1

+= :

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

测试:

string s2("HelloWord");
s2 += ' ';
s2 += "xxxxxxxxxx";
​
cout << s2.c_str() << endl;

遍历string

  1. 用下标的方式遍历

void _Print(const string &s)
{for (size_t i = 0; i < s.size(); i++){cout << s[i] << " ";}cout << endl;
}

调用:

_print(s1);
  1. 用迭代器

string::iterator it = s1.begin();
while (it != s1.end())
{cout << *it << " ";++it;
}
cout << endl;

string类对象的修改操作

reserve 开空间

void reserve(size_t n)
{if (n > _capacity){char *tmp = new char[n + 1]; //+1是为了存放"\0"strcpy(tmp, _str);           // 拷贝delete[] _str;               // 销毁_str空间_str = tmp;_capacity = n;}
}

push_back 头插

void push_back(char ch)
{if (_size + 1 > _capacity){reserve(_capacity * 2);}_str[_size] = ch; // 将字符插入++_size;_str[_size] = '\0';
}

append 头插

void append(char *str)
{size_t len = strlen(str); // 计算要插入字符的长度
​if (_size + len > _capacity){reserve(_size + len);}  
​strcpy(_str + _size, str); // _str 指针所指向的内存块中找到要插入字符串的位置(+_size)_size += len;
}

insert 任意位置插入

// 任意位置插入  //string& 可用于获取对象
string &insert(size_t pos, char ch)//与void &insert(size_t pos, char ch)效果差不多,
{assert(pos <= _size);if (_size + 1 > _capacity){reserve(2 * _capacity);}size_t end = _size + 1; // 防止size_t end=-1->整形最大值while (end > pos){_str[end] = _str[end - 1];--end;}_str[pos] = ch;++_size;return *this;
}
​
string &insert(size_t pos, const char *str)
{assert(pos <= _size);size_t len = strlen(str);
​if (_size + len > _capacity){reserve(_size + len);}
​// 挪动数据
​// 方法一size_t end = _size + len;while (end > pos + len - 1){_str[end - len] = _str[end];--end;}/*//方法二size_t n=_size+1;size_t end=_size;for (size_t i = 0; i < n; ++i){_str[end+len]=_str[end];--end;}*/// 拷贝插入strncpy(_str + pos, str, end);_size += len;
​return *this;
}
push_back复用insert
void push_back(char ch)
{insert(_size,ch);
}
append复用insert
void append(const char *str)
{insert(_size,str);
}

erase删除

在private出定义静态变量 npos

static size_t npos;

类外进行赋值:

size_t string::npos = -1;

或者是直接在private里定义:

static const size_t npos=-1;//该语法只支持整形

// 任意位置删除
string &erase(size_t pos, size_t len = npos)
{ assert(pos<_size);
​if (len == npos || pos + len >= _size){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;
}

resize缩容

void resize(size_t n, char ch = '\0')
{if (n < _size) // 当 n 小于当前字符串长度时,删除多余的字符,即保留前 n 个字符{_size = n;_str[_size] = '\0'; // 更新字符串结束符}else if (n > _size) //当 n 大于当前字符串长度时,根据情况填充待求个字符,直到字符串长度为 n 为止{if (n > _capacity) // 如果需要的容量超出已分配的容量,则进行扩容操作{reserve(n);}
​size_t i = _size;while (i < n) // 将新插入的字符填充到字符串中,直到字符串长度为 n 为止{_str[i] = ch;++i;}
​_size = n; // 更新字符串长度_str[_size] = '\0'; // 更新字符串结束符}
}

find 查找

// 在字符串中查找字符 ch,从 pos 位置开始查找
// 如果找到,返回该字符在字符串中的下标
// 如果没找到,返回 npos
size_t find(char ch, size_t pos = 0)
{assert(pos < _size); // 断言:pos 不能大于字符串长度
​for (size_t i = pos; i < _size; ++i) // 从 pos 位置开始查找{if (_str[i] == ch) // 如果找到字符 ch,返回该字符在字符串中的下标{return i;}}
​return npos; // 没找到,返回 npos
}
​
// 在字符串中查找字符串 str,从 pos 位置开始查找
// 如果找到,返回该字符串在原字符串中的第一个字符的下标
// 如果没找到,返回 npos
size_t find(const char* str, size_t pos = 0)
{assert(pos < _size); // 断言:pos 不能大于字符串长度
​char* p = strstr(_str + pos, str); // 在字符串中查找字符串 str,并返回第一次出现该字符串的指针if (p == nullptr) // 如果没找到,返回 npos{return npos;}else // 找到,则返回该字符串在原字符串中的第一个字符的下标{return p - _str;}
}

clear清除

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

swap交换

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

流插入

// 流插入
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 = in.get(); // 获取一个字符char buff[128];size_t i = 0;
​while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127) // 若已存满{buff[127] = '\0'; // 在末尾添加字符串结束符s += buff; // 添加到输出字符串i = 0; // 重置计数器,从buff[0]开始}
​ch = in.get(); // 读入下一个字符}
​if (i != 0) // 防止循环结束还有数据没有增加到buff中{buff[i] = '\0'; // 在末尾添加字符串结束符s += buff; // 添加到输出字符串}
​return in;
}

测试:

string s1("0123456789");
cout << s1.c_str() << endl;
cout << s1 << endl;
​
cin >> s1;
cout << s1 << endl;

示例代码:

string.cpp

#include "string.h"
​
int main()
{try // char* tmp = new char[s._capacity + 1];是否开辟异常{wzf::test_string9();}catch (const std::exception &e){std::cerr << e.what() << '\n';}
​return 0;
}

string.h

#pragma once
#include <iostream>
#include <assert.h>
​
using namespace std;
​
namespace wzf
{class string{public: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;}
​string(const char *str = "") // 可以不写 "\0": _size(strlen(str)){_capacity = _size == 0 ? 3 : _size;_str = new char[_capacity + 1]; //+1-> '\0'strcpy(_str, str);}
​// 深拷贝 s3string(const string &s): _size(s._size), _capacity(s._capacity){_str = new char[s._capacity + 1];strcpy(_str, s._str);}
​// 赋值重载string &operator=(const string &s) // string&为返回类型{if (this != &s) // s1≠s1{char *tmp = new char[s._capacity + 1];strcpy(tmp, s._str);delete[] _str; // 销毁原来空间,防止s1空间小于s2,或s1>s2造成空间浪费_str = tmp;_size = s._size;_capacity = s._capacity;}
​return *this; // s1}// 析构~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}
​const char *c_str(){return _str;}
​size_t size() const{return _size;}
​size_t capcacity() const{return _capacity;}
​// 给const对象调用const char &operator[](size_t pos) const{assert(pos < _size);return _str[pos];}// 给普通对象,构成函数重载char &operator[](size_t pos){assert(pos < _size);return _str[pos];}
​// 不改变数据的都建议加上constbool operator>(const string &s) const{return strcmp(_str, s._str) > 0;}
​bool operator==(const string &s) const{return strcmp(_str, s._str) == 0;}
​bool operator>=(const string &s) const{return *this > s || *this == s;}
​bool operator<(const string &s) const{return !(*this >= s);}bool operator<=(const string &s) const{return !(*this > s);}
​bool operator!=(const string &s) const{return !(*this == s);}
​string &operator+=(char ch){push_back(ch);return *this;}
​string &operator+=(const char *str){append(str);return *this;}
​// 缩容void resize(size_t n, char ch = '\0'){if (n < _size){// 删除数据 -- 保留前n个_size = n;_str[_size] = '\0';}else if (n > _size) // n=_size不处理{if (n > _capacity){reserve(n);}
​size_t i = _size;while (i < n) // 从size位置开始填字符{_str[i] = ch;++i;}_size = n;_str[_size] = '\0';}}
​// 开空间void reserve(size_t n){if (n > _capacity){char *tmp = new char[n + 1]; //+1是为了存放"\0"strcpy(tmp, _str);           // 拷贝delete[] _str;               // 销毁_str空间_str = tmp;_capacity = n;}}
​void push_back(char ch){// if (_size + 1 > _capacity)// {//     reserve(_capacity * 2);// }// _str[_size] = ch; // 将字符插入// ++_size;// _str[_size] = '\0';insert(_size, ch);}
​void append(const char *str){// size_t len = strlen(str); // 计算要插入字符的长度
​// if (_size + len > _capacity)// {//     reserve(_size + len);// }
​// strcpy(_str + _size, str); // _str 指针所指向的内存块中找到要插入字符串的位置(+_size)// _size += len;
​insert(_size, str);}
​// 任意位置插入string &insert(size_t pos, char ch) // 与void &insert(size_t pos, char ch)效果差不多,string& 可用于获取对象{assert(pos <= _size);if (_size + 1 > _capacity){reserve(2 * _capacity);}size_t end = _size + 1; // 防止size_t end=-1->整形最大值while (end > pos){_str[end] = _str[end - 1];--end;}_str[pos] = ch;++_size;return *this;}
​string &insert(size_t pos, const char *str){assert(pos <= _size);size_t len = strlen(str);
​if (_size + len > _capacity){reserve(_size + len);}
​// 挪动数据
​// 方法一size_t end = _size + len;while (end > pos + len - 1){_str[end - len] = _str[end];--end;}/*//方法二size_t n=_size+1;size_t end=_size;for (size_t i = 0; i < n; ++i){_str[end+len]=_str[end];--end;}*/// 拷贝插入strncpy(_str + pos, str, end);_size += len;
​return *this;}
​// 任意位置删除string &erase(size_t pos, size_t len = npos){assert(pos < _size);if (len == npos || pos + len >= _size){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;}
​size_t find(char ch, size_t pos = 0){assert(pos < _size);
​for (size_t i = pos; i < _size; ++i){if (_str[i] == ch){return i;}}return npos;}
​size_t find(const char *str, size_t pos = 0){assert(pos < _size);
​char *p = strstr(_str + pos, str);if (p == nullptr){return npos;}else{return p - _str;}}
​// 交换void swap(string &s){std::swap(_str, s._str);std::swap(_capacity, s._capacity);std::swap(_size, s._size);}
​void Print(const string &s){for (size_t i = 0; i < s.size(); i++){cout << s[i] << " ";}cout << endl;
​const_iterator rit = s.begin();while (rit != s.end()){cout << *rit << " ";++rit;}}
​void clear(){_str[0] = '\0';_size = 0;}
​private:char *_str;size_t _size;size_t _capacity;
​static size_t npos;};
​size_t string::npos = -1;
​// 流插入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 = in.get(); // 获取一个字符char buff[128];size_t i = 0;
​while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127) // 若已存满{buff[127] = '\0';s += buff;i = 0; // 再次从buff[0]开始}
​ch = in.get();}
​if (i != 0) // 防止循环结束还有数据没有进行增加{buff[i] = ch;buff[i + 1] = '\0';s += buff;}
​return in;}
​void test_string1(){string s1;string s2("HelloWord");
​cout << s1.c_str() << endl;cout << s2.c_str() << endl;
​s2[0]++;cout << s1.c_str() << endl;cout << s2.c_str() << endl;}void test_string2(){string s1;string s2("Hello Word");/*string s3(s2); // 拷贝构造(浅拷贝/值拷贝) 用系统自动生成的拷贝构造1.两个用的是同一个空间. 2.会析构两次*/// 深拷贝:string s3(s2);
​cout << s2.c_str() << endl;cout << s3.c_str() << endl;s2[0]++;cout << s2.c_str() << endl;cout << s3.c_str() << endl;cout << "===" << endl;
​s1 = s3; // 调用 s1 的 operator= 函数,将 s2 赋值给 s1cout << s3.c_str() << endl;cout << s1.c_str() << endl;}
​void test_string3(){string s1("Hello Word");for (size_t i = 0; i < s1.size(); i++){s1[i]++;}cout << endl;
​for (size_t i = 0; i < s1.size(); i++){cout << s1[i] << " ";}cout << endl;
​// Print(s1);
​string::iterator it = s1.begin();while (it != s1.end()){cout << *it << " ";++it;}cout << endl;}
​void test_string4(){string s1("Hello Word");string s2("Hello Word");string s3("Iello Word");
​cout << (s1 == s2) << endl;cout << (s1 >= s3) << endl;cout << (s1 <= s3) << endl;cout << (s1 != s3) << endl;}void test_string5(){string s1("HelloWord");s1.push_back(' ');s1.append("*******************");cout << s1.c_str() << endl<< endl;
​string s2("HelloWord");s2 += ' ';s2 += "xxxxxxxxxx";
​cout << s2.c_str() << endl<< endl;
​string s3;s3 += 'a';s3 += 'a';s3 += 'a';cout << s3.c_str() << endl;}void test_string6(){string s1("HelloWord");s1.insert(5, 'x');cout << s1.c_str() << endl;}void test_string7(){string s1;s1.resize(20, 'x');cout << s1.c_str() << endl;
​s1.resize(30, 'y');cout << s1.c_str() << endl;
​s1.resize(10);cout << s1.c_str() << endl;}void test_string8(){string s1("0123456789");
​cout << s1.c_str() << endl;
​s1.erase(2, 3);cout << s1.c_str() << endl;
​s1.erase(4, 30);cout << s1.c_str() << endl;s1.erase(2);cout << s1.c_str() << endl;}void test_string9(){string s1("0123456789");cout << s1.c_str() << endl;cout << s1 << endl;
​cin >> s1;cout << s1 << endl;}
}

感谢收看,创作不易,喜欢的话留下一个免费的赞吧🥰

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

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

相关文章

计算机体系结构----基本概念(一)

本文仅供学习&#xff0c;不作任何商业用途&#xff0c;严禁转载。绝大部分资料来自----计算机系统结构教程(第二版)张晨曦等 计算机体系结构----基本概念 计算机系统设计的定量原理1. Amdahl定律&#xff08;阿姆达尔定律&#xff09;2. CPU性能公式3. 程序的局部性原理 计算…

计算机组成原理期中题库

计算机组成原理题目集 2.1 下面是关于计算机中存储器容量单位的叙述&#xff0c;其中错误的是 A. 最基本的计量单位是字节&#xff08;Byte&#xff09;&#xff0c;一个字节等于8bit B. 一台计算机的编址单位、指令字长和数据字长都一样&#xff0c;且是字节的整数倍 C. 最小…

C++ 学习之函数成员指针的一个小细节

看看下面的代码&#xff0c;你能看出错误吗 class A { public:void fun(){}}; int main() {A a;void (A:: * p)() &A::fun;(*p)(); } 这段代码在调用成员函数时存在问题。正确的方式是使用对象来调用成员函数&#xff0c;而不是通过指针。以下是修正后的代码&#xff1a…

JAVA基础进阶(十一)

一、创建线程的三种方式 Java语言中是用Thread类来表示线程&#xff0c;线程的创建和开启都是通过Thread类来实现的。 继承Thread类重写run方法。 调用线程对象的start()方法启动线程&#xff08;启动后还是执行run方法的&#xff09;,而不是调用创建的子类对象的run()方法。…

MSUSB30模拟开关可Pin to Pin兼容FSUSB30/SGM7222

MSUSB30/MSUSB30N 是一款高速、低功耗双刀双掷 USB 模拟开关芯片&#xff0c;其工作电压范围是1.8V 至5.5V。可Pin to Pin兼容FSUSB30/SGM7222。其具有低码间偏移、高通道噪声隔离度、宽带宽的特性。 MSUSB30/MSUSB30N 主要应用范围包括&#xff1a;具有 USB2.0 接口的手持设备…

事件机制?

事件流&#xff1a; 描述的页面接收事件的顺序。先进行事件捕获 到达目标元素 在进行事件冒泡 分为事件捕获和事件冒泡 事件冒泡&#xff1a;从具体元素从内向外依次触发事件 从下面这个小案例可以清楚了解什么是事件冒泡 <!DOCTYPE html> <html lang"en"…

C++ -- 每日选择题 -- Day2

第一题 1. 下面代码中sizeof(A)结果为&#xff08;&#xff09; #pragma pack(2) class A {int i;union U{char str[13];int i;}u;void func() {};typedef char* cp;enum{red,green,blue}color; }; A&#xff1a;20 B&#xff1a;21 C&#xff1a;22 D&#xff1a;24 答案及解析…

智能优化算法应用:基于纵横交叉算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于纵横交叉算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于纵横交叉算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.纵横交叉算法4.实验参数设定5.算法结果6.参考…

【字符串探秘:手工雕刻的String类模拟实现大揭秘】

【本节目标】 1. string类的模拟实现 2.C基本类型互转string类型 3.编码表 &#xff1a;值 --- 符号对应的表 4.扩展阅读 1. string类的模拟实现 1.1 经典的string类问题 上面已经对string类进行了简单的介绍&#xff0c;大家只要能够正常使用即可。在面试中&#xff0c;…

1.网络编程基础知识 - 基础概念、TCP网络通信、UDP网络通信

网络编程 文章目录 网络编程一、概念1.1 网络1.2 IP地址1.2.1 IPv4 介绍1.2.2 IPv6 介绍1.2.3 查看IP地址 1.3 域名和端口1.4 网络协议1.5 TCP与UDP1.6 InetAddress类1.7 Socket 二、TCP网络通信编程2.1 介绍2.2 案例2.2.1 字节流编程案例12.2.2 字节流编程案例22.2.3 字符流编…

5. 文件属性和目录

5. 文件属性和目录 1. Linux 系统的文件类型1.1 普通文件1.2 目录文件1.3 字符设备文件和块设备文件1.4 符号链接文件1.5 管道文件1.6 套接字文件 2. stat 系统调用2.1 struct stat 结构体2.2 st_mode 变量2.3 struct timespec 结构体 3. fstat 和 lstat 函数3.1 fstat 函数3.2…

python中的序列

文章目录 序列类型标准类型运算符标准类型运算符序列类型运算符字符串 序列类型 字符串 列表 元组 由元组构成的列表 标准类型运算符 &#xff08;1&#xff09;按字符串大小比较 标准类型运算符 序列类型运算符 序列类型转换内建函数 注&#xff1a; &#xff08;1&#xff…

深入理解MySQL索引底层数据结构与算法

索引的本质 索引是帮助MySQL高效获取数据的排好序的数据结构 索引的数据结构 二叉树红黑数Hash表B-Tree MySQL索引底层为啥不用二叉树 如图&#xff0c;对单边增长的数据&#xff0c;索引效率没有什么提升 MySQL索引底层为啥不用红黑数 红黑数&#xff1a;二叉平衡树 随…

计算虚拟化之内存

有了虚拟机&#xff0c;内存就变成了四类&#xff1a; 虚拟机里面的虚拟内存&#xff08;Guest OS Virtual Memory&#xff0c;GVA&#xff09;&#xff0c;这是虚拟机里面的进程看到的内存空间&#xff1b;虚拟机里面的物理内存&#xff08;Guest OS Physical Memory&#xf…

STM32CubeIDE(CUBE-MX hal库)----定时器

系列文章目录 STM32CubeIDE(CUBE-MX hal库)----初尝点亮小灯 STM32CubeIDE(CUBE-MX hal库)----按键控制 STM32CubeIDE(CUBE-MX hal库)----串口通信 文章目录 系列文章目录前言一、定时器二、使用步骤三、HAL库实验代码三、标准库代码 前言 STM32定时器是一种多功能外设&#…

[iOS开发]UITableView的性能优化

一些基础的优化 &#xff08;一&#xff09;CPU 1. 用轻量级对象 比如用不到事件处理的地方&#xff0c;可以考虑使用 CALayer 取代 UIView CALayer * imageLayer [CALayer layer]; imageLayer.bounds CGRectMake(0,0,200,100); imageLayer.position CGPointMake(200,200…

Python基础学习之包与模块详解

文章目录 前言什么是 Python 的包与模块包的身份证如何创建包创建包的小练习 包的导入 - import模块的导入 - from…import导入子包及子包函数的调用导入主包及主包的函数调用导入的包与子包模块之间过长如何优化 强大的第三方包什么是第三方包如何安装第三方包 总结关于Python…

智能优化算法应用:基于生物地理学算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于生物地理学算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于生物地理学算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.生物地理学算法4.实验参数设定5.算法结果…

【matlab程序】matlab利用工具包nctool读取grib2、nc、opendaf、hdf5、hdf4等格式数据

【matlab程序】matlab利用工具包nctool读取grib2、nc、opendaf、hdf5、hdf4等格式数据 引用&#xff1a; B. Schlining, R. Signell, A. Crosby, nctoolbox (2009), Github repository, https://github.com/nctoolbox/nctoolbox Brief summary: nctoolbox is a Matlab toolbox…

时间序列预测实战(二十一)PyTorch实现TCN卷积进行时间序列预测(专为新手编写的自研架构)

一、本文介绍 本篇文章给大家带来的是利用我个人编写的架构进行TCN时间序列卷积进行时间序列建模&#xff08;专门为了时间序列领域新人编写的架构&#xff0c;简单不同于市面上大家用GPT写的代码&#xff09;&#xff0c;包括结果可视化、支持单元预测、多元预测、模型拟合效…