【C++】STL--String
这一节主要总结string类的常见接口,以及完成了string类的模拟实现。
目录
标准库的String类
string类常见接口
string类对象的常见构造
string析构函数:~string
string类对象的容量操作
string类对象的访问及遍历操作
string类对象的修改操作
string类非成员函数
string类的模拟实现
经典的string类问题
浅拷贝
深拷贝
传统版写法的String类
现代版写法的String类
string类的模拟实现
标准库的String类
为了符合C++面向对象的特性,引入了string类,string是表示字符串的字符串类。下面说明一下string类的特点:
1.string是表示字符串的字符串类
2.string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数
3.string类独立于所使用的编码来处理字节,如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
提示: 在使用string类时,必须包含#include头文件以及using namespace std;
string类常见接口
string类对象的常见构造
(重点)1.string()
默认构造,构造空的string类对象,即空字符串
(重点)2.string(const string& str)
拷贝构造,使用str拷贝构造string类对象
(重点)3.string(const char* s)
使用C-string来构造string类对象
4.string(const string& str, size_t pos, size_t len=npos)
从str的第pos个位置,取len个字符构造,如果len超过字符串长度,那么只取到字符串末尾,如果len未给出,那么采用默认参数npos(0xFFFFFFFF)
5.string(const char* s, size_t n)
使用C-string的前n个字符来构造string类对象
6.string(size_t n, char c)
string类对象包含n个字符c
void test_string1()
{string s0;string s1("hello world");string s2(s1);string s3(s1, 5, 3);string s4(s1, 5, 10);string s5(s1, 5);string s6(10, '$');cout << s0 << endl;cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;cout << s4 << endl;cout << s5 << endl;cout << s6 << endl;
}
string析构函数:~string
在string类对象生命周期结束时,会被自动调用。
string类对象的容量操作
1.size()和length()
这两个均可以返回字符串有效字符长度,功能一样。可以通过size遍历字符串。有两个功能一样的函数是由于历史原因造成的!
2.max_size()
返回string最大的大小
3.capacity()
返回string类对象的容量大小。
//查看扩容机制
void test_string4()
{string s;size_t sz = s.capacity();cout << "capacity change:" << sz << endl;cout << "making s growing" << endl;for (int i = 0; i < 100; i++){s.push_back('c');if (sz != s.capacity()){sz = s.capacity();cout << "capacity changed" << sz << endl;}}
}
虽然是15、31...,但是没有包括‘\0’,所以实际大小应该是16、32、48...,第一次是2倍扩容,以后每次是1.5倍扩容(VS平台下)。但是在Linux平台下,扩容机制不太一样:
这就说明,STL是一个标准,具体怎么实现由编译器决定!
4.clear()
清除对象的数据,但是不会清空间。
5.shrink_to_fit()
在clear()后,为了释放一些已开辟的空间,可以缩容
6.reserve()
如果提前知道要开辟空间的大小,可以用reserve()为字符串提前预留空间,防止频繁扩容,因为扩容一般是异地扩容,效率低下。
避免了频繁扩容!
还有一个问题,reserve会不会缩容呢?不会的!当reserve()比capacity大,才会扩容!
7. resize()
调整字符串大小。
如果采用第一种,那么默认用‘\0’插入,第二种用指定的char插入。
string类对象的访问及遍历操作
1.operator[],返回pos位置的字符
string s1("hello world");
for (size_t i = 0; i < s1.size(); i++)
{cout << s1[i] << " ";
}
2.迭代器,begin+end,可以通过迭代器的方式遍历字符串,begin获取第一个字符的迭代器,end获取最后一个字符下一个位置的迭代器
string::iterator it1 = s1.begin();while (it1 != s1.end()){cout << *it1 << " ";++it1;}
我们感觉到迭代器很像指针,但是并不是指针!
3.rbegin+rend,支持倒着遍历,循环中用++rit,而不是--rit,对于反向迭代器而言,++就是倒着走
string s1("hello world");
string::reverse_iterator rit = s1.rbegin();
while (rit != s1.rend())
{cout << *rit << " ";++rit;
}
除了正向和反向的正常iterator外,还有正向和反向的const_iterator,是用来为const string构造迭代器,其特点是只能读不能写:
//只读
const string s3("hello world");
string::const_iterator it3 = s3.begin();
while (it3 != s3.end())
{//*it3 += 3;//报错,因为只读cout << *it3 << " ";
}
cout << endl;
//string::const_reverse_iterator
4.用范围for遍历字符串
for (auto s : s1){cout << s << " ";}
但是范围for并没有什么特别之处,其底层是迭代器!
string类对象的修改操作
1.pushback()
在字符串末尾尾插字符
2.append()
在字符串后追加字符串
3.operator+=
在字符串后追加字符串str
4.assign()
用新内容覆盖原字符串
5.insert()
在某一个位置插入字符串
注意:insert()尽量不要使用,因为在使用过程中会挪动数据,效率低。
6.erase()
删除字符
同样,erase()函数能不用就不用。
7.replace()
字符的替换
8.find()
查找某个字符的位置
小练习:将一个字符串中的空格替换成“%20”。
总结一下,insert、erase、replace能少用就少用,因为基本都要挪动数据,效率不高。
9.c_str
返回C格式字符串
在C++程序中,我们有可能会调用C语言的函数,比如fopen函数,但是在程序中文件名可能是string对象,需要转换成C字符串才行。
void test_string()
{string filename("test.cpp");FILE* fout = fopen(filename.c_str(), "r");
}
10.find
找到某一个字符或字符串第一次出现的位置
例如:获取后缀
void test_string()
{string s1("test.cpp");size_t pos = s1.find('.');if (pos != string::npos){string suffix = s1.substr(pos);cout << suffix << endl;}else{cout << "没有后缀" << endl;}
}
11.rfind
从后往前找某一个字符或字符串第一次出现的位置
例如:获取后缀“file.c.tar.zip”的zip
void test_string()
{string s1("test.c.tar.zip");size_t pos = s1.rfind('.');if (pos != string::npos){string suffix = s1.substr(pos);cout << suffix << endl;}else{cout << "没有后缀" << endl;}
}
string类非成员函数
1.operator+
尽量少用,因为传值返回,导致深拷贝效率低
2.operator>>&&operator<<
输入和输出运算符重载
3.getline
获取一行字符串。弥补了cin>>的缺点,cin遇到了空格或者换行就提取结束。
4.== != > >= < <=
大小比较
string类的模拟实现
经典的string类问题
首先来看一个经典关于浅拷贝的问题:
class String
{
public:
/*String()
:_str(new char[1])
{*_str = '\0';}
*/
//String(const char* str = "\0") 错误示范
//String(const char* str = nullptr) 错误示范,使用strlen时会涉及解引用
String(const char* str = "")
{// 构造String类对象时,如果传递nullptr指针,可以认为程序非if (nullptr == str){assert(false);return;}_str = new char[strlen(str) + 1];strcpy(_str, str);
}
~String()
{if (_str){delete[] _str;_str = nullptr;}
}
private:char* _str;
};
// 测试
void TestString()
{String s1("hello bit!!!");String s2(s1);
}
说明:在上面的String类中没有显式定义拷贝构造和赋值运算符重载,因此,当使用s1去构造时s2时,编译器会调用默认构造函数。这样导致的问题是,s1和s2指向同一块内存空间,在释放空间时,同一块空间会被释放两次而引起程序崩溃,这种拷贝方式,称为浅拷贝。
浅拷贝
浅拷贝:也称值拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规。
可以用深拷贝解决浅拷贝问题,也就是:每个对象都有一份独立的资源,不要和其他对象共享。
深拷贝
如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。
传统版写法的String类
namespace ghs
{class string{public:string(const char* str=""):_size(strlen(str)){_str = new char[_size + 1];strcpy(_str, str);_capacity = _size;}string(const string& str){_str = new char[str._capacity + 1];strcpy(_str, str._str);_size = str._size;_capacity = str._capacity;}//s1 = s2string& operator=(const string& 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(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}private:char* _str = nullptr;size_t _size = 0; size_t _capacity = 0;public:static const int npos;};const int string::npos = -1;
}
在传统版的写法中,拷贝构造和赋值构造都是通过自己手动开空间,然后使用strcpy函数拷贝完成的,下面的现代写法在实现上更为简洁:
现代版写法的String类
namespace ghs
{class string{public:string(const char* str=""):_size(strlen(str)){_str = new char[_size + 1];strcpy(_str, str);_capacity = _size;}string(const string& s){string tmp(s._str);swap(tmp);}//s1 = s2//string& operator=(const string& str)//{// string ss(str);// swap(ss);// return *this;//}//上面的再优化,这种更推荐string& operator=(string ss)//传值传参,调用拷贝构造{swap(ss);return *this;}~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}private:char* _str = nullptr;size_t _size = 0; size_t _capacity = 0;public:static const int npos;};const int string::npos = -1;
}
在现代写法中,拷贝构造是通过调用string(const char* str="")构造函数来生成临时的string对象(tmp),再将*this和tmp交换,完成拷贝。在赋值构造中,使用传值传参,其实调用拷贝构造,生成临时对象ss,再将ss和*this交换,完成拷贝。
总结:传统版的现代版的效率一样,只是现代版调用了之前已经实现好的函数,所以看起来更加简洁!
string类的模拟实现
namespace ghs
{class string{public:/*string():_str(nullptr),_size(0),_capacity(0){}*//*string():_str(new char[1]),_size(0),_capacity(0){_str[0] = '\0';}*/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=""):_size(strlen(str)){_str = new char[_size + 1];strcpy(_str, str);_capacity = _size;}//string(const string& str)//{// _str = new char[str._capacity + 1];// strcpy(_str, str._str);// _size = str._size;// _capacity = str._capacity;//}string(const string& s){string tmp(s._str);swap(tmp);}//s1 = s2//string& operator=(const string& 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& operator=(const string& str){string ss(str);swap(ss);return *this;}//上面的再优化,这种更推荐//string& operator=(string ss)//传值传参,调用拷贝构造//{// swap(ss);// return *this;//}const char* c_str()const{return _str;}size_t size()const{return _size;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}void reserve(size_t sz){if (sz > _capacity){char* p = new char[sz + 1];strcpy(p, _str);delete[] _str;_str = p;_capacity = sz;}}void push_back(char ch){//扩容2倍/*if (_size == _capacity){reserve(_capacity == 0 ? 4 : 2 * _capacity);}_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);///*for (size_t i = 0; i < len; i++)//{// push_back(str[i]);//}*///_size += len;insert(_size, str);}string& operator+=(char ch){push_back(ch);return *this;}string& operator+=(const char* str){append(str);return *this;}const char& operator[](size_t pos)const{assert(pos < _size);return _str[pos];}size_t capacity()const{return _capacity;}void insert(size_t pos, char ch){assert(pos <= _size);if (_size == _capacity){reserve(_capacity == 0 ? 4 : 2 * _capacity);}for (size_t end = _size+1; end > pos; end--){_str[end] = _str[end - 1];}_str[pos] = ch;_size++;}void insert(size_t pos, const char* str){assert(pos <= _size);size_t len = strlen(str);if (_size + len > _capacity){reserve(len + _size);}for (size_t end = _size+len; end > pos+len-1; end--){_str[end] = _str[end-len];}/*for (size_t i = 0; i < len; i++){_str[pos + i] = str[i];}*/strncpy(_str + pos, str, len);_size += len;}void erase(size_t pos, size_t len = npos){assert(pos < _size);if (len == npos || len>=_size-pos){_size = pos;_str[_size] = '\0';}else{strcpy(_str + pos, _str + pos + len);_size -= len;}}void resize(size_t n, char ch = '\0'){if (n <= _size){_str[n] = '\0';_size = n;}else{reserve(n);for (size_t i = _size; i < n; i++){_str[i] = ch;}_str[n] = '\0';_size = n;}}void swap(string& s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}size_t find(char ch, size_t pos = 0)const{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)const{assert(pos < _size);char* tmp = strstr(_str+pos, str);if (tmp != nullptr){return tmp - _str;}else{return npos;}}string substr(size_t pos = 0, size_t len = npos){string s;if (len == npos || len >= _size-pos){for (size_t i = pos; i < _size; i++){s += _str[i];}}else{for (size_t i = pos; i < pos + len; i++){s += _str[i];}}return s;}void clear(){_size = 0;_str[_size] = '\0';}/*bool operator==(const string& str){int ret = strcmp(_str, str._str);return ret == 0;}*/~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}private:char* _str = nullptr;size_t _size = 0; size_t _capacity = 0;public:static const int npos;};const int string::npos = -1;void swap(string& x, string& y){x.swap(y);}bool operator==(const string& s1,const string& s2){int ret = strcmp(s1.c_str(), s2.c_str());return ret == 0;}bool operator<(const string& s1, const string& s2){int ret = strcmp(s1.c_str(), s2.c_str());return ret < 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);}ostream& operator<<(ostream& out, const string& str){for (auto ch : str){out << ch; }return out;}istream& operator>>(istream& in, string& str){char ch;str.clear();//in >> ch;ch = in.get();char buff[100];size_t i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 99){buff[99] = '\0';str += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';str += buff;}return in; }istream& getline(istream& in, string& str){char ch;str.clear();char buff[100];//in >> ch;/*ch = in.get();while (ch != '\n'){str += ch;ch = in.get();}*/ch = in.get();size_t i = 0;while (ch != '\n'){buff[i++] = ch;if (i == 99){buff[99] = '\0';str += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';str += buff;}return in;}
}
相关文章:

【C++】STL--String
这一节主要总结string类的常见接口,以及完成了string类的模拟实现。 目录 标准库的String类 string类常见接口 string类对象的常见构造 string析构函数:~string string类对象的容量操作 string类对象的访问及遍历操作 string类对象的修改操作 s…...
深入理解与使用go之中间件--实现
深入理解与使用go之--中间件实现 目录 引子 中间件 定义 原理 简单实现 多个中间件 优化 扩展 gin框架实现 引子 我们在做web开发的时候,经常会遇到下面一些需求: 统计耗时:想程序内部统计某个路由的请求耗时 预处理:接口需要登录鉴权后才能继续进行 错误捕获:当…...

移动端研发技术的进化历程
移动端研发技术 移动端研发技术主要分为原生开发和跨平台开发。本章主要介绍一下移动开发技术的过去、当下和未来,一步一步介绍移动技术的进化历程。 原生开发 原生应用程序是指某一个移动平台(比如iOS或Android)所特有的应用,使…...

ChromeDriver 122 版本为例 国内下载地址及安装教程
ChromeDriver 国内下载地址 https://chromedriver.com/download 靠谱 千千万万别下载错了 先确认 Chrome 浏览器版本 以 win64 版本为例 那我们下载这一个啊,不要下载错了 下载地址贴在这哈 https://storage.googleapis.com/chrome-for-testing-public/122.0.…...

【数据结构】双向链表及LRU缓存的实现
目录 前言 1. 在原有的自定义链表类 Linked 的基础上,添加新的 “节点添加”方法 addNode(Node node) 测试用例 测试结果 2. 在自定义链表类的基础上,使用双重循环“强力” 判断两个节点是否发生相交 测试用例 测试结果 3. 在自定义链表类的基础上…...
2、计划任务不显示UI的问题
计划任务不显示UI的问题 1、原因: 在windows7以上系统,使用system权限启动的进程默认是没有ui界面,这是windows系统出于安全考虑的限制。防止用户在高权限下误删重要的文件。 2、解决方案: 1、降权 解决的办法:降…...
学C还是学C++?
计算机专业学生,大一上学期学习了C语言,下学期学校要学C,请问我寒假继续深入学习C还是提前学C,大佬们有什么建议吗?(个人感觉C学的不是很明白,链表文件什么的还不是很懂…) 这个并没有一个统一的…...
Springboot参数分组校验
Springboot参数分组校验 文章目录 Springboot参数分组校验简介代码准备单个或多个参数的校验非 JSON 格式的对象参数校验JSON 格式的对象参数校验Service 层校验项目地址 简介 Java API规范(JSR303)定义了Bean校验的标准validation-api,但没有提供实现。hibernate …...

无缝集成 MongoDB Relational Migrator,Tapdata 提供关系型到 MongoDB 实时迁移优化方案
在去年的 MongoDB 用户大会纽约站上,MongoDB 正式宣布全面推出新工具 MongoDB Relational Migrator(MongoDB RM),用以简化应用程序迁移和转换——即从传统关系型数据模型到现代的文档数据模型,助力组织快速提升运营效率…...
【C++】每日一题 146 LRU缓存
请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 …...
CentOS搭建NAS服务器并使用
CentOS搭建NAS服务器并使用 文章目录 前言一、配置NAS服务器安装 NFS 服务:启动 NFS 服务:使 NFS 服务在系统启动时自动启动: 二、挂载服务器三、常见错误以及解决方案1、mount.nfs: No route to host2、mount.nfs: access denied by server …...

爬虫入门到精通_框架篇16(Scrapy框架基本使用)_名人名言的抓取
1 目标站点分析 抓取网站:http://quotes.toscrape.com/ 主要显示了一些名人名言,以及作者、标签等等信息: 点击next,page变为2: 2 流程框架 抓取第一页:请求第一页的URL并得到源代码,进行下…...
mac inter 芯片遇到程序无法打开(无法验证开发者)
mac inter 芯片遇到程序无法打开(无法验证开发者) 解决方案 终端运行命令: sudo xattr -r -d com.apple.quarantine 文件路径(直接把文件拖入到终端,可以自动找到文件路径)即可令其获得权限 补充知识: 通过gpt可以…...

科技成果鉴定测试如何进行?第三方检测机构进行鉴定测试的好处
科技成果鉴定测试,作为科技领域中一项重要的质量检验手段,具有广泛的应用范围。旨在为科技成果的研发者和使用者提供客观、科学、权威的鉴定结果,从而评估科技成果的技术水平和市场竞争力。 科技成果鉴定测试是对科技成果进行系统、全面的…...

八、词嵌入语言模型(Word Embedding)
词嵌入(Word Embedding, WE),任务是把不可计算、非结构化的词转换为可以计算、结构化的向量,从而便于进行数学处理。 一个更官方一点的定义是:词嵌入是是指把一个维数为所有词的数量的高维空间(one-hot形式…...
重学SpringBoot3-WebMvcConfigurer接口
摘要: 本文详细介绍了SpringBoot 3中的WebMvcConfigurer接口,旨在帮助读者深入理解其原理和实现,从而能够更好地使用SpringBoot进行Web开发。阅读本文需要大约30分钟。 关键词:SpringBoot, WebMvcConfigurer, SpringMVC, Web开发…...

《深入理解springCloud与微服务》笔记
第一章 微服务介绍 1.3 微服务的不足 1.3.2 分布式事务 CAP 理论,即同时满足“一致性”“可用性”和“分区容错”是 件不可能的事。 Consistency :指数据的强一致性。如果写入某个数据成功,之后读取,读到的都是新写入的数据&a…...
Vivado原语模板
1.原语的概念 原语是一种元件! FPGA原语是芯片制造商已经定义好的基本电路元件,是一系列组成逻辑电路的基本单元,FPGA开发者编写逻辑代码时可以调用原语进行底层构建。 2.原语的分类 原语可分为预定义原语和用户自定义原语。预定义原语为如and/or等门级原语不需要例化,可以…...

【linux本地安装tinycudann包教程】
【linux本地安装tinycudann包教程】 tiny-cuda-nn官网链接 如果你是windows 10系统的,想要安装tiny-cuda-nn可以参考我的文章——windows 10安装tiny-cuda-n包 根据官网要求:C++要求对应14,其实这样就已经告诉我们linux系统中的gcc版本不能高于9,同时下面又告诉我们gcc版…...

使用Nginx进行负载均衡
什么是负载均衡 Nginx是一个高性能的开源反向代理服务器,也可以用作负载均衡器。通过Nginx的负载均衡功能,可以将流量分发到多台后端服务器上,实现负载均衡,提高系统的性能、可用性和稳定性。 如下图所示: Nginx负…...

什么护眼台灯效果好?热门护眼台灯全方位测评推荐
台灯可以说是佳佳必备,尤其是家中有正在上学的孩子的更是需要一款好的台灯,不管是看书、写字都离不开台灯。不过很多家长在挑选台灯时往往仅关注到光线亮度是否充足,而忽略掉光线均匀度、舒适度等等方面的问题。所以选择一款优质的护眼台灯是…...

云上三问,迈向智能时代的关键
在今天的中国,第一热词是什么?面对这个问题,“新质生产力”当仁不让,而智能化技术毫无疑问是“新质生产力”最重要的来源之一。 在这样的大势下,大型政企是向新技术要“新质生产力”的时代先锋。云服务,则是…...

【网络安全】手机不幸被远程监控,该如何破解,如何预防?
手机如果不幸被远程监控了,用三招就可以轻松破解,再用三招可以防范于未然。 三招可破解可解除手机被远程监控 1、恢复出厂设置 这一招是手机解决软件故障和系统故障的终极大招。只要点了恢复出厂设置,你手机里后装的各种APP全部将灰飞烟灭…...
每日OJ题_哈希表④_力扣219. 存在重复元素 II
目录 力扣219. 存在重复元素 II 解析代码 力扣219. 存在重复元素 II 219. 存在重复元素 II 难度 简单 给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] nums[j] 且 abs(i - j) < k 。如果存在&am…...

42.坑王驾到第八期:uniCloud报错
uniCloud 报错 今天调用云函数来调试小程序的时候突然暴了一个奇葩错误,require(…).main is not a function。翻官方文档后发现,原来是这样:**如果你写的是云对象,入口文件应为 index.obj.js,如果你写的是云函数入口…...

Linux常用操作命令
Linux常用操作命令 1.文件管理catfile 2.文档编辑3.文件传输4.磁盘管理5.磁盘维护6.网络通讯7.系统管理8.系统设置9.备份压缩10.设备管理 Linux 英文解释为 Linux is not Unix。 Linux内核最初只是由芬兰人李纳斯托瓦兹(Linus Torvalds)在赫尔辛基大学上…...

OpenCV的常用数据类型
OpenCV涉及的常用数据类型除包含C的基本数据类型,如:char、uchar,int、unsigned int,short 、long、float、double等数据类型外, 还包含Vec,Point、Scalar、Size、Rect、RotatedRect、Mat等类。C中的基本数据类型不需再做说明下面重点介绍一下…...

STM32串口通信—串口的接收和发送详解
目录 前言: STM32串口通信基础知识: 1,STM32里的串口通信 2,串口的发送和接收 串口发送: 串口接收: 串口在STM32中的配置: 1. RCC开启USART、串口TX/RX所对应的GPIO口 2. 初始化GPIO口 …...

《汇编语言》第3版 (王爽) 第14章
第14章 端口 检测点14.1 (1).编程,读取CMOS RAM的2号单元的内容。 mov al,2 ;向al写入2 out 70,al ;将2送入端口70h in al,71 ;从端口71h读取2号单元的内容在CMOS RAM中用6个字节存放当前时间(以BCD码形式存放)&…...

Axure原型设计项目效果 全国职业院校技能大赛物联网应用开发赛项项目原型设计题目
目录 前言 一、2022年任务书3效果图 二、2022年任务书5效果图 三、2022年国赛正式赛卷 四、2023年国赛第一套样题 五、2023年国赛第二套样题 六、2023年国赛第三套样题 七、2023年国赛第四套样题 八、2023年国赛第七套样题 九、2023年国赛正式赛题(第八套…...