【C++笔记】string类使用详解
前言
各位读者朋友们大家好!上期我们讲完了C++的模板初阶,这一期我们开启STL的学习。STL是C++的数据结构和算法库,是我们学习C++的很重要的一部分内容,在以后的工作中也很重要。现在我们开始讲解。
目录
- 前言
- 一. 为什么学习string类
- 1. C语言中的字符串
- 二. 标准库中的string类
- 2.1 string类
- 2.2 auto和范围for
- 2.3 string类的常用接口说明
- 1. string类对象的常见构造
- 2. string类对象的容量操作
- 2.1 size和lenth
- 2.2 capacity
- 2.3 empty
- 2.4 clear
- 2.5 reserve
- 2.6 resize
- 3. string类的访问及遍历操作
- 1. 迭代器(iterator)
- 2.operator[]访问
- 3. [] + 下标遍历
- 4. begin + end遍历
- 5. rbegin + rend遍历
- 6. 范围for遍历
- 4. string类对象的修改操作
- 4.1 push back
- 4.2 append
- 4.3 operator+=
- 4.4 insert
- 4.5 erase
- 5. string类的其他相关操作
- 5.1 c_str
- 5.2 find + npos
- 5.3 substr
- 5.4 rfind
- 5.5 find_first_of 和 find_last_of
- 5.6 find_first_not_of 和 find_last_not_of
- 6.getline
- 结语
一. 为什么学习string类
1. C语言中的字符串
C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但这些库函数与字符串是分开的,不太符合OOP(面向对象编程,Object-Oriented Programming是一种广泛使用的编程范式,它基于“对象”的概念来设计和实现软件。)的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
二. 标准库中的string类
2.1 string类
string类的文档
在使用string类时,必须包含#include< string >头文件以及指明命名空间std;
2.2 auto和范围for
auto关键字
在这里补充两个C++11的语法,方便后续学习:
-
在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,后来这个不重要了。C++11中,标准委员会变废为宝赋予了auto新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推到而得。

-
用auto声明指针类型时,用auto和auto * 没有区别,但是auto声明引用类型的时候必须加&
-
当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

-
auto不能作为函数的参数,可以做返回值,但是建议谨慎使用

-
auto不能用来直接声明数组

范围for -
对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会犯错,因此C++11中引入了基于范围的for循环。for循环后的括号由冒号“:”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判结束。
-
范围for可以作用到数组和容器对象上进行遍历

-
范围for的底层很简单,容器遍历实际就是替换迭代器,这个在汇编层面可以看到
2.3 string类的常用接口说明
1. string类对象的常见构造

- 1.string()

这是string的无参构造,构造一个长度为0的空字符串。
int main()
{string s1;cout << s1;return 0;
}

- 2. string (const string& str);

这是string类的拷贝构造
int main()
{string s1;string s2(s1);cout << s2;return 0;
}

- 3. string (const string& str, size_t pos, size_t len = npos);

从字符串的指定位置(我们给的是下标)拷贝len个字符,如果字符串太短或着len是npos就拷贝到字符串结束。
int main()
{string s("hello world");string s1(s, 0, 5);string s2(s, 0, 15);string s3(s, 0);// 第三个参数使用缺省值nposcout << s1 << endl;cout << s2 << endl;cout << s3 << endl;return 0;
}

- 4.string (const char * s);

这是string类的带参构造
int main()
{string s("hello world");cout << s << endl;return 0;
}

- 5. string (const char * s, size_t n);

从s指向的字符数组中,复制前n个字符
int main()
{string s("hello world", 5);cout << s;return 0;
}

- 6. string (size_t n, char c);

用n个字符c来构造字符串
int main()
{string s(5, 'h');cout << s;return 0;
}

2. string类对象的容量操作
| 函数名称 | 功能说明 |
|---|---|
| size(重点) | 返回字符串的有效字符长度 |
| length | 返回字符串有效字符长度 |
| capacity | 返回空间总大小 |
| empty(重点) | 检测字符串是否为空串,是返回True,否则返回False |
| clear(重点) | 清空有效字符 |
| reserve(重点) | 为字符串预留空间 |
| resize(重点) | 将有效字符的个数改成n个,多出的空间用字符c填充 |
2.1 size和lenth
size和lenth都是用来求字符串长度的

2.2 capacity
capacity是返回字符串的容量的,跟顺序表中的capacity一样,但是string中的capacity不包含\0

在实现顺序表的时候,我们对顺序表的扩容是二倍扩容,在Vs环境中,编译器对string类的扩容是怎样扩的呢?我们通过下面的一段代码看一下:
void TestPushBack()
{string s;size_t sz = s.capacity();cout << "making s grow:\n";for (int i = 0; i < 100; ++i){s.push_back('c');if (sz != s.capacity()){sz = s.capacity();cout << "capacity changed: " << sz << '\n';}}
}

Vs中,string类的实现加了一个buff数组,当字符长度小于16时,就存在buff数组中,如果大于16就去堆上开空间,看一下string的大小:

在32位环境下,按照上面string类的底层内存对齐计算得string类的大小也是28字节,不管使用数组还是在堆上开空间。

在Linux环境中使用g++编译器,是完全的2倍扩容

2.3 empty
2.4 clear

将字符串清空,空间清不清空看编译器,Vs和g++都不清
int main()
{string s("hello world");cout << s << endl;cout << s.size() << endl;cout << s.capacity() << endl;s.clear();cout << s.size() << endl;cout << s.capacity() << endl;return 0;
}

2.5 reserve

reserve用来预留空间,预留的空间在Vs环境下会大于等于我们给定的空间,这与Vs的内存对齐有关,在g++环境下会严格等于要求的大小。

那如果预留的空间过大,编译器会不会缩容呢?

C++标准并没有强制要求缩容,看编译器,但是有一点是确定的:这个函数不会改变字符串的长度和内容。
int main()
{string s("********************");cout << s.size() << endl;cout << s.capacity() << endl << endl;s.reserve(15);cout << s.size() << endl;cout << s.capacity() << endl << endl;s.reserve(28);cout << s.size() << endl;cout << s.capacity() << endl << endl;s.reserve(48);cout << s.size() << endl;cout << s.capacity() << endl << endl;return 0;
}

上面可以看到,在Vs环境下,是不会缩的,但是在g++环境下编译器是会进行缩容的。
2.6 resize


int main()
{string s("************************");//24cout << s.size() << endl;cout << s.capacity() << endl;s.resize(18);cout << s.size() << endl;cout << s.capacity() << endl;s.resize(28, 'x');cout << s << endl;cout << s.size() << endl;cout << s.capacity() << endl;s.resize(36, '#');cout << s << endl;cout << s.size() << endl;cout << s.capacity() << endl;return 0;
}

3. string类的访问及遍历操作
| 函数名称 | 功能说明 |
|---|---|
| operator[](重点) | 返回pos位置的字符,const string类对象调用 |
| begin+end | begin获取开始位置字符的迭代器+end获取最后一个字符下一个位置的迭代器 |
| rbegin+rend | rbegin获取最后一个字符的迭代器+rend获取第一个字符前一个位置的迭代器 |
| 范围for | C++11支持更简洁的范围for的新遍历方式 |
1. 迭代器(iterator)
在C++中,迭代器(Iterator)是一种用于访问容器(如数组、向量、列表、集合等)中元素的对象。迭代器提供了一种统一的方式来遍历容器中的元素,以下是迭代器的主要作用:
| 1.遍历容器 |
|---|
| 2.访问元素 |
| 3. 范围操作 |
| 4. 支持泛型编程:迭代器使得算法和容器可以分离,从而实现高层次的抽象和泛型编程。通过定义迭代器类型,容器可以与各种算法无缝集成。 |
| 5. 插入和删除操作 |
| 6. 统一接口:迭代器提供了一个统一的接口来访问和操作容器中的元素,使得用户可以用相同的方式处理不同类型的容器。 |
迭代器共有四种:

2.operator[]访问
string类重载了[]这一操作符,返回的是字符串的任意位置的字符的引用,这样我们就可以修改字符串某一位置的值了,并且越界访问还会报错。
int main()
{string s("hello world");cout << s[4] << endl;//cout << s[20];s[4] = 'x';cout << s << endl;return 0;
}

我们可以认为string类是如下结构:
class string
{
public:char& operator[](size_t i){assert(i < _size);return _str[i];}
private:char* _str;size_t _size;size_t _capacity;
};
operator[]封装在类里面作为成员函数默认为内联,效率也会很高。
3. [] + 下标遍历
int main()
{string s("hello world");for (int i = 0; i < s.size(); ++i){cout << s[i] << " ";}return 0;
}

这种方式像数组访问一样
4. begin + end遍历
int main()
{string s("hello world");string::iterator it = s.begin();while (it != s.end()){cout << *it << " ";++it;}return 0;
}


这种遍历方式所有的容器都可以使用这种方式
当字符串被const修饰时,使用string::const_interator迭代器遍历:

5. rbegin + rend遍历
rebegin和rend是反向迭代器(string::reverse_iterator)的函数,rbegin获取最后一个字符的迭代器+rend获取第一个字符前一个位置的迭代器。这样方式的遍历是反向遍历
int main()
{string s("hello world");string::reverse_iterator rit = s.rbegin();while (rit != s.rend()){cout << *rit << " ";++rit;}return 0;
}

6. 范围for遍历
int main()
{string s("hello world");for (auto ch : s){cout << ch << " ";}return 0;
}

范围for是自动推导出类型,自动遍历的,也就是说编译器推导出s的类型,然后将其拷贝赋值给ch。

在汇编层面看,范围for的底层就是迭代器。

我们发现,对ch进行修改并没有影响s,这是因为ch是字符串的拷贝,而对迭代器进行操作就会影响到s,我们可以将迭代器理解为指针,对指针解引用修改,想要通过范围for修改s的内容,可以给auto后面加引用,这样ch就是s里面每个变量的别名。

4. string类对象的修改操作
| 函数名称 | 功能说明 |
|---|---|
| push back | 在字符串后尾插字符c |
| append | 在字符串后追加一个字符串 |
| operator+=(重点) | 在字符串后面追加字符串 |
| insert | 在pos位置插入字符 |
| erase | 在pos位置删除len长度的字符 |
4.1 push back

在字符串的后面尾插一个字符
int main()
{string s("hello wodld");s.push_back('x');cout << s << endl;return 0;
}

4.2 append
在字符串的末尾追加一个新的字符串
int main()
{string s("hello world");s.append(" hello Yuey");cout << s << endl;return 0;
}

4.3 operator+=

重载了+=操作符,可以在字符串的末尾追加string类、字符串以及字符
int main()
{string s1("hello world");string s2("hello world");string s3("hello world");// 追加string类string s4(" hello Yuey");s1 += s4;cout << s1 << endl;// 追加字符串s2 += " hello Yuey";cout << s2 << endl;// 追加字符s3 += "*";cout << s3 << endl;
}

这个+=在实践中使用最多
4.4 insert
在pos位置插入字符或字符串,也可以使用迭代器

int main()
{string s("hello world");string s1(" hello Yuey");//s.insert(5, "#");// 插入一个字符s.insert(5,1,'#');s.insert(12, s1);cout << s << endl;// 迭代器s.insert(s.begin(), '*');cout << s << endl;return 0;
}

4.5 erase

erase支持在指定位置删除len长度的字符,如果len不传的话默认删除npos也就是删除pos位置及以后的所有字符,erase也支持迭代器删除,但是用的最多的还是第一种
int main()
{string s1("hello world");// 头删s1.erase(0, 1);cout << s1 << endl;s1.erase(s1.begin());cout << s1 << endl;// 尾删s1.erase(--s1.end());cout << s1 << endl;s1.erase(s1.size() - 1, 1);cout << s1 << endl;// 指定位置删除string s2("hello Yuey");s2.erase(6, 4);cout << s2 << endl;// 指定位置不传长度s2.erase(1);cout << s2 << endl;return 0;
}

5. string类的其他相关操作
| 函数名 | 功能说明 |
|---|---|
| c_str(重点) | 返回c格式字符 |
| find + npos(重点) | 从字符串pos位置开始往后找到字符c,返回该字符在字符串中的位置 |
| rfind | 从字符串的pos位置开始往前找字符c,返回该字符在字符串中的位置 |
| substr | 从str中从pos位置开始,截取n个字符,然后将其返回 |
5.1 c_str

这个函数的目的主要是兼容C语言,返回的是指向数组的指针,主要在文件读取时使用
5.2 find + npos

find支持在pos位置开始正向查找string类、字符串以及字符,返回值是第一次找到的指定字符的下标,没找到返回npos,如果pos不传,默认从第一个字符开始
将字符串中的空格替换为%:
int main()
{string s("hello world hello Yuey");cout << s << endl;size_t pos = s.find(' ', 0);while (pos != string::npos){s.replace(pos, 1, "%");pos = s.find(' ', pos + 1);}cout << s << endl;return 0;
}

这里用到了replace函数:

replace函数就是将pos及以后位置的len长度的字符替换为给定的字符
int main()
{string s1("hello world");s1.replace(0, 2, "***");cout << s1 << endl;string s2("hello Yuey");s2.replace(5, 3, "***");cout << s2;return 0;
}

但是上面的代码在空格极多的时候效率极低,我们可以用空间换时间的方法:
int main()
{string s("hello world hello Yuey");cout << s << endl;string tmp;for (auto ch : s){if (ch == ' '){tmp += "%";}else{tmp += ch;}}s = tmp;cout << s << endl;return 0;
}
5.3 substr

substr是返回从pos位置开始的后面len长度的子字符串,如果没传len函数使用缺省值npos,返回pos位置及以后的所有字符。
int main()
{string s("hello world");string S1;S1 = s.substr(5);cout << S1;return 0;
}

5.4 rfind

rfind是在pos位置反向查找string类、字符串以及字符,并返回第一次出现该字符的下标,没找到返回npos
int main()
{string s("Test.cpp.zip");// 看文件类型size_t pos = s.rfind('.');string s1 = s.substr(pos);cout << s1;return 0;
}
5.5 find_first_of 和 find_last_of
find_first_of:

这个函数是在字符串中找给定的字符或字符串中的所有字符,并返回第一次找到的地址
int main()
{string s("abcdefggfedcba");size_t pos = s.find_first_of("abc");while (pos != string::npos){s[pos] = '*';pos = s.find_first_of("abc", pos + 1);}cout << s;return 0;
}

find_last_of:

这个可以理解为反向找
void SplitFilename(const std::string& str)
{std::cout << "Splitting: " << str << '\n';std::size_t found = str.find_last_of("/\\");std::cout << " path: " << str.substr(0, found) << '\n';std::cout << " file: " << str.substr(found + 1) << '\n';
}int main()
{std::string str1("/usr/bin/man");std::string str2("c:\\windows\\winhelp.exe");SplitFilename(str1);SplitFilename(str2);return 0;
}
这样就能实现文件的路径和文件名分离
5.6 find_first_not_of 和 find_last_not_of
这两个函数是从字符串中找除了给定字符串里的的字符,并返回第一次找到的下标
int main()
{string s("abcdefggfedcba");size_t pos = s.find_first_not_of("abc");while (pos != string::npos){s[pos] = '*';pos = s.find_first_not_of("abc", pos + 1);}cout << s;return 0;
}

6.getline
在讲getline之前我们先看一道题目: 字符串最后一个单词的长度

这种情况下就需要借助getline函数了:getline

getline默认读取到换行的时候读取结束,读取结束的条件也可以自己设定

自定义结束条件
结语
以上就讲完了string类的基本用法,对于string类的模拟实现我们下期再讲,感谢大家的阅读,欢迎大家批评指正!
相关文章:
【C++笔记】string类使用详解
前言 各位读者朋友们大家好!上期我们讲完了C的模板初阶,这一期我们开启STL的学习。STL是C的数据结构和算法库,是我们学习C的很重要的一部分内容,在以后的工作中也很重要。现在我们开始讲解。 目录 前言一. 为什么学习string类1.…...
数字隔离器与光隔离器有何不同?---腾恩科技
在电子隔离中,两种常用的解决方案是数字隔离器和光学隔离器。两者都旨在电气隔离电路的各个部分,以保护敏感元件免受高压干扰,但它们通过不同的技术实现这一目标。本文探讨了这些隔离器之间的差异,重点介绍了它们的工作原理、优势…...
方差与协方差
方差是一种特殊的协方差。...
【含文档】基于Springboot+Vue的工商局商家管理系统 (含源码数据库+LW)
1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…...
【股票市场情绪量化模型】
股票市场情绪量化模型:理论与实践 目录 什么是股票市场情绪情绪量化模型的基本概念情绪数据的来源与获取情绪量化模型的构建 4.1 情绪指标的选择4.2 模型设计与算法 情绪与市场表现的关系情绪量化模型的应用案例模型的局限性与挑战总结 1. 什么是股票市场情绪 股…...
Oracle视频基础1.3.8与1.4.1练习
1.3.8与1.4.1 -看数据文件的目录, dump 的目录,oracle的软件目录 -(secureCRT,telnet连接linux。)看当前用户,当前所属组,通过操作系统认证以sysdba登陆,启动数据库然后关闭 -看口令文件 看数据文件的目录,…...
基于前馈神经网络模型和卷积神经网络的MINIST数据集训练
目录 前馈神经网络FNN模型 卷积神经网络CNN模型 前馈神经网络FNN模型 author: lxy function: model--mnist date : 2024/10/25 email : 13102790991163.com # 导入必要的库 import torch import torch.nn as nn import torchvision.datasets as dsets import torchvision.t…...
Vue3中Element Plus==el-eialog弹框中的input无法获取表单焦点
有弹框情况下 <template> <input ref"input" /> </template> <script setup> import { ref, onMounted } from vue // 声明一个 ref 来存放该元素的引用 // 必须和模板里的 ref 同名 const input ref(null) onMounted(() > { ne…...
16.网工入门篇--------介绍下网络服务及应用
一、网络服务的概念 网络服务是指通过网络提供的软件功能或设施,它允许不同的设备和用户在网络环境中进行信息交换、资源共享和协作。这些服务基于各种网络协议,以实现高效、可靠的通信。 二、常见网络服务类型 (一)文件传输服务 …...
区分 electron 全屏和最大化
一. 全屏 在 Electron 中,当窗口处于全屏状态时,通常不能直接使用 JavaScript 来改变窗口大小。这是出于安全和用户体验的考虑,以防止意外的窗口大小变化影响全屏体验。 1. 退出全屏后再调整大小 检测全屏状态,退出全屏并调整大…...
封装一个请求的hook(react函数组件)
对于后台系统,上面筛选,下面表格分页的页面,这个hook非常实用 omitBy方法:过滤不为undefined的对象属性 export const omitBy <T extends IObject, K extends keyof T>(object:T, predicate:(value:T[K]) > boolean):I…...
c语言内存块讲解
文章目录 前言一、栈区1、栈区的特点:1.1 自动管理1.2 后进先出1.3 有限大小1.4 高速访问1.5 栈区存储方向 2、栈区使用注意事项 二、堆区1、堆区的定义2、堆区的特点3、堆区的内存分配与释放4、注意事项: 三、全局/静态存储区1、全局存储区1.1 全局变量…...
2024年10月23日Github流行趋势
项目名称:hiteshchoudhary / apihub 项目维护者:wajeshubham, atulbhatt-system32, jwala-anirudh, arnb-smnta, shrey-dadhaniya 项目介绍:您自己的API Hub,用于学习和掌握API交互。非常适合前端、移动开发人员和后端开发人员。 …...
YOLOv6-4.0部分代码阅读笔记-dbb_transforms.py
dbb_transforms.py yolov6\layers\dbb_transforms.py 目录 dbb_transforms.py 1.所需的库和模块 2.def transI_fusebn(kernel, bn): 3.def transII_addbranch(kernels, biases): 4.def transIII_1x1_kxk(k1, b1, k2, b2, groups): 5.def transIV_depthconcat(kernel…...
C++ 基础语法 一
C 基础语法 一 文章目录 C 基础语法 一const 限定符常量指针类型别名autodecltypeQStringvector迭代器指针和数组显示转换static_castconst_cast 函数尽量使用常量引用数组形参不要返回局部对象的引用和指针返回数组指针 C四种转换内联函数constexpr函数函数指针 const 限定符 …...
B2020 分糖果
题目描述 某个幼儿园里,有 55 位小朋友编号依次为 1,2,3,4,51,2,3,4,5 他们按照自己的编号顺序围坐在一张圆桌旁。他们身上有若干糖果,现在他们玩一个分糖果游戏。从 11 号小朋友开始,将自己的糖果均分成 33 份(如果有多余的糖果…...
VBA字典与数组第二十讲:如何在代码运行时创建数组
《VBA数组与字典方案》教程(10144533)是我推出的第三套教程,目前已经是第二版修订了。这套教程定位于中级,字典是VBA的精华,我要求学员必学。7.1.3.9教程和手册掌握后,可以解决大多数工作中遇到的实际问题。…...
字符串统计(Python)
接收键盘任意录入,分别统计大小写字母、数字及其它字符数量,打印输出。 (笔记模板由python脚本于2024年11月02日 08:23:31创建,本篇笔记适合熟悉python字符串并懂得基本编程技法的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网…...
NVR小程序接入平台/设备EasyNVR多个NVR同时管理视频监控新选择
在数字化转型的浪潮中,视频监控作为安防领域的核心组成部分,正经历着前所未有的技术革新。随着技术的不断进步和应用场景的不断拓展,视频监控系统的兼容性、稳定性以及安全性成为了用户关注的焦点。NVR小程序接入平台/设备EasyNVR,…...
怎样能把图片做压缩处理?学会4款在线工具高效压缩图片
随着现在图片质量不断的提高,导致图片的大小也越来越大,很多的网上平台只能上传比较小的图片,那么可以使用压缩图片或者图片改尺寸的方式来修改图片大小,那么图片压缩的操作技巧是什么样的呢?本文将带大家了解4个操作简…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
高防服务器价格高原因分析
高防服务器的价格较高,主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因: 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器,因此…...
在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7
在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤: 第一步: 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为: // 改为 v…...
数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)
名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 原创笔记:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:《数据结构第4章 数组和广义表》…...
向量几何的二元性:叉乘模长与内积投影的深层联系
在数学与物理的空间世界中,向量运算构成了理解几何结构的基石。叉乘(外积)与点积(内积)作为向量代数的两大支柱,表面上呈现出截然不同的几何意义与代数形式,却在深层次上揭示了向量间相互作用的…...
