string使用及模拟

前言

        相信看过我博客的小伙伴都已经C++的接触已经很久了,也没那么多废话。stl库直接走起,最开始、最简单的就是string。string就相当于是把C语言中的字符串“char[]”给升了级,像是顺序表一样多了记录长度和容量的大小,还加了很多的函数去控制这个对象。

        本篇博客将会介绍标准库中的string,string中各种函数的作用和用法,最后会穿插自己写的string模拟。最后扩展一下string的标准。

一、string介绍

        string是用来存储字符串的容器,能够储存字符。有能够扩宽容量改变长度的函数,包括构造函数等函数在内一共有45个函数。这里不会将所有函数都模拟,但是使用方法会大致讲到。

        string出现在C++早期,当时由于没有写标准库容器先例,所以先人也就是摸着石头过河,有很多函数出现了重复功能。部分函数可以说没有存在的必要,因此string在界内讨论许多,之后标准库容器吸收了教训就会好很多。

        使用string需要包含标准库<string>。

二、string中函数介绍

        这里我会挑选出比较常用的函数进行说明,构造和拷贝构造等函数会放到之后介绍。和模拟实现放在一起会好解释更多。

        但是基础还是需要介绍的,作为一个容器。string拥有一个指针指向存储char类型的空间,一个容量、一个记录长度的变量。不同的编译器有不同的版本,优化之后有可能会多一个变量,记录浅拷贝构造次数。但是在VS下,容器中的内容基本上都是深拷贝,会拷贝指针指向的内容。

    class string{private:char* _str; // 指向存储内容的指针size_t _capacity; // 容量size_t _size; // 长度};

1、构造、拷贝构造和赋值重载

        这些函数的使用方法都是相似的,能够放在一起讲,就直接说了。

        构造函数有以上7种构造,比较常用的是第一种、第二种、第四种构造。支持默认构造拷贝构造和“char*”构造。当然也支持控制构造的长度以及迭代器构造,只是这些不常用。

        赋值重载就少一些,有3种:

        分别是用string、char*和字符char,进行赋值,其实前两种有一个就行了。char*能够构造string,所以第二个能包含在第一个里面。因为参数string&前面有const修饰,构成了隐示构造。

        当然,string因为只有字符,所以支持流插入流提取,用法如下:

void test_string1()
{// 构造string str1("nice");// 拷贝构造string str2(str1);// 默认构造string str3;// 赋值重载str3 = str2;cout << str2 << endl;cout << str3 << endl;cin >> str1;cout << str1 << endl;
}

2、析构函数

        析构函数释放申请的空间,自动调用,不做演示。

3、有关iterator的函数

        这个类的函数比较多,但是都可以顾名思义。作为string的迭代器,它的iterator就能直接是“char*”这里分为两块讲就行了。

3.1、begin()和end()

        这两个函数,一个返回初始位置,一个返回末尾位置。在这里空间是左闭右开的,所以begin()返回的是头,但是end()返回的是最后的字符后面一位的位置。

        对于string的iterator来说是支持“++”、“--”,“+n”、“-n”的,同时支持解引用。所以如果想访问string中的元素能够通过iterator来访问。当然也就支持迭代器和范围for。

void test_string2()
{string str1("happe ending");string::iterator cur = str1.begin();while(cur != str1.end()){cout << *cur << " ";++cur;}for(auto ch : str1){cout << ch ;}cout << endl;
}

3.2、rbegin()和rend()

        string支持反向迭代器,所以有rbegin()和rend(),分别返回反向的iterator。使用起来还是比较怪异的,可以顾名思义的理解,就是转了顺序读字符串。于是能够倒着打印字符串。

void test_string3()
{string str1("happe ending");string::reverse_iterator cur = str1.rbegin();while(cur != str1.rend()){cout << *cur << " ";++cur;}cout << endl;
}

3.3、其他

        这里还有其他的四个函数就不做讲解了,有兴趣的小伙伴可以去官网查。效果和前面4种一样,不如说就是改了个名。

4、有关容量的函数

        这一类的函数比较多,需要将的也比较多。有的函数在不同编译器下效果还会不同,这里都会提到。

4.1、size()、length()和capacity()

         前两种的用法是相同的,都会返回string中元素的个数,而“capacity()”会返回当前string的容量。“size()”和“length()”的用法其实重复了所以之后的容器只剩下第一种用法。

void test_string4()
{string str1("happe ending");cout << str1.size() << endl;cout << str1.length() << endl;cout << str1.capacity() << endl;
}

4.2、resize()和reserve()

        resize()这个函数能够控制string中剩下的元素个数,少了就补充,多了就删除。

        使用的时候多了会默认补充“ ”,也可以自己添加补充的元素。不过这里只用第二种重载就行,给他一个默认参数就好。

        reserve()的说法就比较多了,不同编译器下的操作不同。它是控制string容量的函数,能够增加容量、部分平台下能够减少容量。因为无论是增加或者说减少都会开新的空间,所以部分编译器不支持缩减。

       resize()对字符串长度没有影响,也不能更改其内容。

void test_string5()
{string str1;cout << str1.size() << endl;str1.resize(20);cout << str1.size() << endl;str1.resize(10);cout << str1.size() << endl;cout << str1.capacity() << endl;str1.reserve(100);cout << str1.capacity() << endl;str1.reserve(50);cout << str1.capacity() << endl;str1.reserve(10);cout << str1.capacity() << endl;
}

        不同编译器下结果不同,望周知。

4.3、clear()和empty()

        “clear()“用来清理string中的数据,不改变容量。

        “empty()”用来查看string中有没有数据,如果有会返回false,未有数据会返回true。


void test_string6()
{string str1("happe ending");cout << str1 << endl;cout << str1.empty() << endl << endl;str1.clear();cout << str1 << endl;cout << str1.empty() << endl << endl;
}

4.4、其他

        另外两个函数用处较少所以不做讲解。

5、元素访问

        元素访问最简单的就是“[]”访问了,就和C语言中的字符串一样使用就行。

void test_string7()
{string str1("happe ending");size_t size1 = str1.size();for(size_t i = 0; i < size1; ++i){cout << str1[i];} 
}

        也能够通过一下函数访问:

        但是剩下的访问没这个方便,所以就只讲这一个常用的就足够了。

6、字符串操作

        这个就相当于是给了一个适应C语言的接口:

        函数很多,但是用处多的不多。

6.1、c_str()

        比较重要的是c_str()这个是为了访问文件方便,所以弄出来的。能够返回容器中指向资源的“char*”作用和“data()”相同。

void test_string8()
{string file("test.txt");// 这里需要用到char*所以需要取出来指针FILE* fin = fopen(file.c_str(), "w");string str1("over again");for(auto ch : str1){fprintf(fin, "%c", ch);}fclose(fin);
}

6.2、copy()

        copy()用来将string中的内容复制到字符数组中。

void test_string9()
{string str1("hello world");char arr[20];str1.copy(arr, 12);cout << arr << endl;
}

6.3、find()和find_first_of()

        find()用于从头开始找字符,直到第一次找到返回该字符在字符串中的位置,否则返回npos。

void test_string10()
{std::string str ("There are two needles in this haystack with needles.");std::string str2 ("needle");// different member versions of find in the same order as above:std::size_t found = str.find(str2);if (found!=std::string::npos)std::cout << "first 'needle' found at: " << found << '\n';found=str.find("needles are small",found+1,6);if (found!=std::string::npos)std::cout << "second 'needle' found at: " << found << '\n';found=str.find("haystack");if (found!=std::string::npos)std::cout << "'haystack' also found at: " << found << '\n';found=str.find('.');if (found!=std::string::npos)std::cout << "Period found at: " << found << '\n';// let's replace the first needle:str.replace(str.find(str2),str2.length(),"preposition");std::cout << str << '\n';}

        和find()函数不同find_first_of()用来查找一串字符串中出现的字符。只要字符串中出现过搜索字符串中的任何一个字符就返回当前位置,find()函数如果输入的是字符串的话就需要按照顺序全部一致。

void test_string11()
{std::string str ("Please, replace the vowels in this sentence by asterisks.");std::size_t found = str.find_first_of("aeiou");while (found!=std::string::npos){str[found]='*';found=str.find_first_of("aeiou",found+1);}std::cout << str << '\n';
}

6.4、find_last_of()、find_firsr_not_of()和find_last_not_of()

        这三个放在一起讲,和find_first_of()有相同之处,find_last_of()表示重字符串最后开始搜索相同字符,另外两个分别是从前开始向后、和从后开始向前找不同的字符位置。可以直接把find_first_of()的例子直接改成find_last_of()、find_firsr_not_of()和find_last_not_of(),最后打印出来查看效果,这里不做演示,详情查看上方代码。

6.5、substr()

        别被函数名称骗了,这不是从这个函数里增加字符串,而是从原来字符串的某个位置开始提取相对长度得到字符串,最后返回一个临时变量。

void test_string12()
{std::string str="We think in generalities, but we live in details.";// (quoting Alfred N. Whitehead)std::string str2 = str.substr (3,5);     // "think"std::size_t pos = str.find("live");      // position of "live" in strstd::string str3 = str.substr (pos);     // get from "live" to the endstd::cout << str2 << ' ' << str3 << '\n';}

6.5、compare()

        compare()函数和C语言中strcmp()函数是一样类型的函数,用来比较字符串是否相等,不过compare()的重载函数很多,功能不完全一样。能够直接比较全部,也能够单独分出来一块部分比较。

void test_string13()
{std::string str1 ("green apple");std::string str2 ("red apple");if (str1.compare(str2) != 0)std::cout << str1 << " is not " << str2 << '\n';if (str1.compare(6,5,"apple") == 0)std::cout << "still, " << str1 << " is an apple\n";if (str2.compare(str2.size()-5,5,"apple") == 0)std::cout << "and " << str2 << " is also an apple\n";if (str1.compare(6,5,str2,4,5) == 0)std::cout << "therefore, both are apples\n";
}

7、npos

        npos是在string中定义的固定值,类型是size_t,实际值为-1.

8、其他的重载函数

        在重载函数中除了支持流插入流提取到string中以外,还能比较。例如“!=”"=="之类的都有重载,效果和compare()是相同的,只是由于重载的是符号所以使用起来更加方便。

void test_string14()
{std::string foo = "alpha";std::string bar = "beta";if (foo==bar) std::cout << "foo and bar are equal\n";if (foo!=bar) std::cout << "foo and bar are not equal\n";if (foo< bar) std::cout << "foo is less than bar\n";if (foo> bar) std::cout << "foo is greater than bar\n";if (foo<=bar) std::cout << "foo is less than or equal to bar\n";if (foo>=bar) std::cout << "foo is greater than or equal to bar\n";}

        比较重要的函数swap(),能够让两个string交换容器内的内容。在重载的赋值模拟中用处更大。

void test_string15()
{std::string buyer ("money");std::string seller ("goods");std::cout << "Before the swap, buyer has " << buyer;std::cout << " and seller has " << seller << '\n';swap (buyer,seller);std::cout << " After the swap, buyer has " << buyer;std::cout << " and seller has " << seller << '\n';
}

        和流提取不同getline()函数能够提取到“ ”和“\n”,这个时候需要自己限制结束条件,总之,用这个能够提取“ ”。

void test_string16()
{std::string name;std::cout << "Please, enter your full name: ";std::getline (std::cin,name);std::cout << "Hello, " << name << "!\n";
}

三、string模拟实现

        string的模拟实现,我会挑选比较实用的函数进行实现,包括构造函数、析构函数、函数重载、输入输出等等。

        那么接下来给出代码,并且参考前一大节string中的函数介绍内容,实现函数的功能,所有拷贝都是深拷贝,函数的写法思路,可以参考上一次写的“Date”。

1、模拟

#include <iostream>
#include <string.h>
#include <assert.h>
using namespace std;namespace lcs
{class string{friend ostream& operator<<(ostream& _cout, const lcs::string& s);friend istream& operator>>(istream& _cin, lcs::string& s);public:typedef char* iterator;public:string(const char* str = ""){_size = strlen(str);_capacity = _size + 1;_str = new char[_capacity];strcpy(_str, str);}string(const string& s){_size = s._size;_capacity = s._capacity;_str = new char[_capacity];strcpy(_str, s._str);}string& operator=(const string &s){string tmp(s);swap(tmp);return *this;}~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}//// iteratoriterator begin(){assert(_str);return _str;}iterator end(){assert(_str);return _str + _size;}/// modifyvoid push_back(char c){assert(_str);if(_size + 1 == _capacity) // 满了扩容{_capacity = _capacity > 3 ? _capacity * 2 : 4;char* tmp = new char[_capacity];strcpy(tmp, _str);delete[] _str;_str = tmp;}_str[_size++] = c;}string& operator+=(char c){assert(_str);push_back(c);return *this;}void append(const char* str){assert(_str);int len = strlen(str);for(int i = 0; i < len; ++i){push_back(str[i]);}}string& operator+=(const char* str){append(str);return *this;}void clear(){_size = 0;_str[_size] = '\0';}void swap(string& s){std::swap(_size, s._size);std::swap(_capacity, s._capacity);std::swap(_str, s._str);}const char* c_str()const{assert(_str);return _str;}/// capacitysize_t size()const{return _size;}size_t capacity()const{return _capacity;}bool empty()const{return _size == 0;}void resize(size_t n, char c = '\0'){assert(_str);if(n < _size){_size = n;_str[_size] = '\0';}else{for(int i = _size; i < n; ++i){push_back(c);}}}void reserve(size_t n){assert(_str);if(_capacity <= n){_capacity = n > 2 * _capacity ? n : 2 * _capacity;char* tmp = new char[_capacity];strcpy(tmp, _str);delete[] _str;_str = tmp;}}/// accesschar& operator[](size_t index){assert(index < _size);return _str[index];}const char& operator[](size_t index)const{assert(index < _size);return _str[index];}///relational operatorsbool operator<(const string& s){return strcmp(_str, s._str) < 0;}bool operator<=(const string& s){return *this < s || *this == s;}bool operator>(const string& s){return !(*this <= s);}bool operator>=(const string& s){return !(*this < s);}bool operator==(const string& s){return strcmp(_str, s._str) == 0;}bool operator!=(const string& s){return !(*this == s);}// 返回c在string中第一次出现的位置size_t find (char c, size_t pos = 0) const{for(int i = pos; i < _size; ++i){if(c == _str[i]){return i;}}return -1;}// 返回子串s在string中第一次出现的位置size_t find (const char* s, size_t pos = 0) const{char* tmp = strstr(_str + pos, s);if(tmp == nullptr){return -1;}return tmp - _str;}// 在pos位置上插入字符c/字符串str,并返回该字符的位置string& insert(size_t pos, char c){assert(pos <= _size);if(_size + 1 == _capacity){reserve(_size + 2);}for(size_t i = _size; i > pos; --i){_str[i] = _str[i - 1];}_str[pos] = c;_size++;return *this;}string& insert(size_t pos, const char* str){assert(pos <= _size);int len = strlen(str);if(len == 0){return *this;}if(_size + len >= _capacity){reserve(_size + len + 1);}for(size_t i = _size + len - 1; i > pos + len - 1; --i){_str[i] = _str[i - len];}for(size_t i = 0; i < len; ++i){_str[i + pos] = str[i];}_size += len;return *this;}// 删除pos位置上的元素,并返回该元素的下一个位置string& erase(size_t pos = 0, size_t len = -1){if(pos >= _size){return *this;}if(pos + len >= _size){_str[pos] = '\0';_size = pos;}else{int n = _size - pos - len;for(size_t i = 0; i < n; ++i){_str[pos + i] = _str[pos + i + len];}_str[pos + n] = '\0';_size = pos + n;}return *this;}private:char* _str;size_t _capacity;size_t _size;};ostream& operator<<(ostream& _cout, const lcs::string& s){size_t size = s.size();for(size_t i = 0; i < size; ++i){_cout << s[i];}return _cout;}istream& operator>>(istream& _cin, lcs::string& s){s.clear();char ch = _cin.get();while(ch != ' ' && ch != '\n'){s += ch;ch = _cin.get();}return _cin;}
}

2、测试

        测试之中所写的,代码分为5个模块测试。如代码注释:

#include "string.hpp"// 测试赋值、构造、流插入流输出
void test_string1()
{lcs::string str1("hello world hahah");lcs::string str2(str1);cout << str1 << " " << str2 << endl;lcs::string str3("ku");str3 = str1;cout << str3 << endl;cin >> str3;cout << str3 << endl;
}// 测试迭代器,+=重载
void test_string2()
{lcs::string str1("hello world");for(auto ch : str1){cout << ch << " ";}cout << endl;str1 += "overcome your self";cout << str1 << endl;
}// 测试和容量相关的函数size()/capacity(),resize()/reserve()
void test_string3()
{lcs::string str1;cout << str1.capacity() << endl;str1.reserve(81);cout << str1.capacity() << endl;str1.reserve(66);cout << str1.capacity() << endl << endl;cout << str1.size() << endl;str1.resize(20);cout << str1.size() << endl;str1.resize(10);cout << str1.size() << endl;
}// 测试比较函数的重载
void test_string4()
{lcs::string str1("call");lcs::string str2("call");lcs::string str3("cell");cout << (str1 == str2) << endl;cout << (str1 < str2) << endl;cout << (str1 > str2) << endl;cout << (str1 != str2) << endl;cout << (str1 >= str2) << endl;cout << (str1 <= str2) << endl;cout << (str1 == str3) << endl;cout << (str1 == "call") << endl;
}// 测试不规则插入、输出函数
void test_string5()
{lcs::string str1("hallo");str1.insert(5, " ###");str1.insert(0, "$$$ ");cout << str1 << endl;str1.erase(8, 1);cout << str1 << endl;str1.erase(8, 10);cout << str1 << endl;
}int main()
{test_string1();test_string2();test_string3();test_string4();test_string5();return 0;
}

结语

        本来模拟打算多讲一点的,但是感觉有点废话就省掉了,主要是实现出来的内容其实和之前介绍的讲的差不多,有一些函数没有模拟出来,其实是因为不是很常用。

        下一篇就是将vector了,vector和string模拟其实挺像的,但是为了和stl库中实现的大致相同,那么就会出现迭代器失效等等问题。提一嘴,之后遇到了细讲。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

大模型面试:LLM+向量库的文档对话系统

面试题 1.1 为什么大模型需要外挂(向量)知识库&#xff1f;如何将外部知识注入大模型&#xff0c;最直接的方法&#xff1a;利用外部知识对大模型进行微调 回答 大模型需要外挂(向量)知识库的原因&#xff1a; 知识更新频率&#xff1a;大模型在训练时使用的知识是静态的&am…

免杀笔记 -->API的整理Shellcode加密(过DeFender)

最近更新频率明显下降我懒&#xff0c;那么今天就来记录一下我们的一些常用的API的整理以及ShellCode的加密。 1.WinAPI整理 问我为什么要整理&#xff1f; 就是用起来的时候要左翻右翻 &#xff1a;&#xff1a; 烦死了 1.VirtualAlloc VirtualAlloc(NULL,sizeof(buf),MEM_…

人工智能和计算机视觉领域国际学术会议submission

文章目录 1. AAAI 20252. CVPR 20253. ICCV 20254. IJCAI 20255. ICRA 20256. NeurIPS 20257. ACL 20258. ICLR 2025 1. AAAI 2025 人工智能促进协会&#xff08;AAAI&#xff09;是一个成立于1979年的非营利性科学组织&#xff0c;专注于深化对智能行为和思维机制的科学理解&…

通过 WSL 2 在Windows 上挂载 Linux 磁盘

原文查看 曾为了传输或者共享不同系统的文件频繁地在 Windows 和 Linux 系统之间切换&#xff0c;效率过低&#xff0c;所以尝试通过 WSL 2 在Windows 上挂载 Linux 磁盘。 先决条件 需要在Windows 10 2004 及更高版本&#xff08;Build 19041 及更高版本&#xff09;或 Win…

排查一次线程泄漏

背景&#xff1a;最近经常发生K8S健康检查到应用的心跳接口超时不通&#xff0c;然后发生了重启&#xff0c;第一时间进入pod内部使用任何jvm命令都会导致java进程重启&#xff08;也包括arthas工具使用不了&#xff09;&#xff0c;dump不下来&#xff0c;事故现场没法保留&am…

SpringBoot集成Sharding-JDBC实现分库分表

本文已收录于专栏 《中间件合集》 目录 版本介绍背景介绍拆分方式集成并测试1.引入依赖2.创建库和表3.pom文件配置3.编写测试类Entity层Mapper接口MapperXML文件测试类 4.运行结果 自定义分片规则定义分片类编写pom文件 总结提升 版本介绍 SpringBoot的版本是&#xff1a; 2.3.…

电子期刊制作攻略:从零开始,轻松入门

​随着互联网的快速发展&#xff0c;电子期刊已经逐渐成为人们获取信息和娱乐的重要途径。越来越多的人开始关注并投身于电子期刊的制作行业。那么&#xff0c;如何从零开始&#xff0c;轻松入门电子期刊制作呢&#xff1f; 1.首先点击FLBOOK在线制作制作电子杂志平台 2.点击开…

【odoo17】后端py方法触发右上角提示组件

概要 在前面文章中&#xff0c;有介绍过前端触发的通知服务。 【odoo】右上角的提示&#xff08;通知服务&#xff09; 此文章则介绍后端触发方法。 内容 直接上代码&#xff1a;但是前提一定是按钮触发&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; def bu…

无法解析插件 org.apache.maven.plugins:maven-war-plugin:3.2.3(已解决)

文章目录 1、问题出现的背景2、解决方法 1、问题出现的背景 最开始我想把springboot项目转为javaweb项目&#xff0c;然后我点击下面这个插件 就转为javaweb项目了&#xff0c;但是我后悔了&#xff0c;想要还原成springboot项目&#xff0c;点开项目结构关于web的都移除了&am…

HarmonyOS Next 省市区级联(三级联动)筛选框

效果图 完整代码 实例对象 export class ProvinceBean {id?: stringpid?: stringisSelect?: booleandeep?: objectextName?: stringchildren?: ProvinceBean[] }级联代码 import { MMKV } from tencent/mmkv/src/main/ets/utils/MMKV import { ProvinceBean } from ..…

【Git】merge合并分支

两个分支未修改同一个文件的同一处位置: Git自动合并 两个分支修改了同一个文件的同一处位置:产生冲突 例&#xff1a; 在master分支修改了main同时&#xff0c;feat分支也修改了相同的文件 合并的时候就会产生冲突 解决方法: Step1- 手工修改冲突文件&#xff0c;合并冲突内容…

【数据结构】单链表的增删改查

介绍 链表是有序的列表&#xff0c;但是它在内存中是如下存储的&#xff1a; ①链表以节点的方式进行存储&#xff0c;是链式存储的 ②每个节点包含 data 域、next 域&#xff1a;指向下一节点 ③链表的各个节点不一定是连续存放的 ④链表分为有头节点的链表和没有头节点的链表…

比肩 GPT-4o 的 Llama 3.1 本地部署快速体验的方法

比肩 GPT-4o 的 Llama 3.1 本地部署快速体验的方法 flyfish Llama 3.1模型简介 Llama 3.1是一系列大型语言模型&#xff0c;包含以下几种规模&#xff1a; 8B 参数&#xff1a;模型中有80亿个参数 70B 参数&#xff1a;模型中有700亿个参数 405B 参数&#xff1a;模型中有4…

深入理解MySQL锁机制与性能优化:详解记录锁、间隙锁、临键锁及慢SQL查询分析

1. 事务隔离和锁机制详解 记录锁 第一种情况,当我们对于唯一性的索引(包括唯一索引和主键索引)使用等值查询,精准匹配到一条记录的时候,这个时候使用的就是记录锁。 比如 where id = 1 4 7 10。 间隙锁 第二种情况,当我们查询的记录不存在,无论是用等值查询还是范围…

【vue教程】四. Vue 计算属性和侦听器

目录 本章涵盖知识点回顾计算属性&#xff08;Computed&#xff09;创建计算属性计算属性的多样性计算属性的数组过滤计算属性的复杂表达式 计算属性 vs 方法计算属性的实例演示 侦听器&#xff08;Watchers&#xff09;创建侦听器侦听器的高级用法侦听器的深度观察侦听器的立即…

无线遥控控制直流电机和无刷电机开关

一 目的 此文章记录了arduino与陶晶驰串口屏实现联动&#xff0c;点击屏幕双态开关远程控制arduino2560板载的直流电机和无刷电机开关。为手搓乒乓球发球机做准备。 二 接线 2.1串口屏接线 串口屏与Arduino UNO接线如下&#xff1a; ———————————————— RX …

pdf2image:将PDF文档转化为图像的Python魔法

标题&#xff1a;探索pdf2image&#xff1a;将PDF文档转化为图 像的Python魔法 背景 在数字时代&#xff0c;我们经常需要处理各种格式的文档&#xff0c;尤其是PDF文件。PDF以其跨平台的可读性和稳定性而广受欢迎。然而&#xff0c;有时我们需要将PDF文件转换成图像格式&am…

C++ - char*、const char*、char[]、string

const char* const char* 用来定义字符串常量。 char[ ] char型的字符数组是一种定长的数组&#xff0c;存储指定长度的字符序列&#xff0c;数组中的每个元素都是一个char类型的变量&#xff0c;如&#xff1a; char arr[] {h, a, l, l, o, \0}; char c arr[0]; // 访问…

CentOS怎么关闭自动锁屏?

禁止自动锁屏 有时候几分钟不用Centos&#xff0c;系统就自动锁屏了&#xff0c;这是一种安全措施&#xff0c;防止别人趁你不在时使用你的系统。但对于大部分人而言&#xff0c;这是没有必要的&#xff0c;尤其是Centos虚拟机&#xff0c;里面没啥重要的东西&#xff0c;每次…

光伏发电管理软件:光伏企业的核心驱动力

光伏产业面对日益增长的装机容量、复杂多变的运维需求以及激烈的市场竞争&#xff0c;光伏企业如何高效管理、优化运营、提升效益&#xff0c;成为了行业关注的焦点。在此背景下&#xff0c;鹧鸪云光伏发电管理软件应运而生&#xff0c;并逐渐成为光伏企业的核心驱动力。 一、提…