当前位置: 首页 > news >正文

【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+endbegin获取开始位置字符的迭代器+end获取最后一个字符下一个位置的迭代器
rbegin+rendrbegin获取最后一个字符的迭代器+rend获取第一个字符前一个位置的迭代器
范围forC++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类使用详解

前言 各位读者朋友们大家好&#xff01;上期我们讲完了C的模板初阶&#xff0c;这一期我们开启STL的学习。STL是C的数据结构和算法库&#xff0c;是我们学习C的很重要的一部分内容&#xff0c;在以后的工作中也很重要。现在我们开始讲解。 目录 前言一. 为什么学习string类1.…...

数字隔离器与光隔离器有何不同?---腾恩科技

在电子隔离中&#xff0c;两种常用的解决方案是数字隔离器和光学隔离器。两者都旨在电气隔离电路的各个部分&#xff0c;以保护敏感元件免受高压干扰&#xff0c;但它们通过不同的技术实现这一目标。本文探讨了这些隔离器之间的差异&#xff0c;重点介绍了它们的工作原理、优势…...

方差与协方差

方差是一种特殊的协方差。...

【含文档】基于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.功能 系统定…...

【股票市场情绪量化模型】

股票市场情绪量化模型&#xff1a;理论与实践 目录 什么是股票市场情绪情绪量化模型的基本概念情绪数据的来源与获取情绪量化模型的构建 4.1 情绪指标的选择4.2 模型设计与算法 情绪与市场表现的关系情绪量化模型的应用案例模型的局限性与挑战总结 1. 什么是股票市场情绪 股…...

Oracle视频基础1.3.8与1.4.1练习

1.3.8与1.4.1 -看数据文件的目录&#xff0c; dump 的目录&#xff0c;oracle的软件目录 -(secureCRT&#xff0c;telnet连接linux。)看当前用户&#xff0c;当前所属组&#xff0c;通过操作系统认证以sysdba登陆,启动数据库然后关闭 -看口令文件 看数据文件的目录&#xff0c…...

基于前馈神经网络模型和卷积神经网络的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.网工入门篇--------介绍下网络服务及应用

一、网络服务的概念 网络服务是指通过网络提供的软件功能或设施&#xff0c;它允许不同的设备和用户在网络环境中进行信息交换、资源共享和协作。这些服务基于各种网络协议&#xff0c;以实现高效、可靠的通信。 二、常见网络服务类型 &#xff08;一&#xff09;文件传输服务 …...

区分 electron 全屏和最大化

一. 全屏 在 Electron 中&#xff0c;当窗口处于全屏状态时&#xff0c;通常不能直接使用 JavaScript 来改变窗口大小。这是出于安全和用户体验的考虑&#xff0c;以防止意外的窗口大小变化影响全屏体验。 1. 退出全屏后再调整大小 检测全屏状态&#xff0c;退出全屏并调整大…...

封装一个请求的hook(react函数组件)

对于后台系统&#xff0c;上面筛选&#xff0c;下面表格分页的页面&#xff0c;这个hook非常实用 omitBy方法&#xff1a;过滤不为undefined的对象属性 export const omitBy <T extends IObject, K extends keyof T>(object:T, predicate:(value:T[K]) > boolean):I…...

c语言内存块讲解

文章目录 前言一、栈区1、栈区的特点&#xff1a;1.1 自动管理1.2 后进先出1.3 有限大小1.4 高速访问1.5 栈区存储方向 2、栈区使用注意事项 二、堆区1、堆区的定义2、堆区的特点3、堆区的内存分配与释放4、注意事项&#xff1a; 三、全局/静态存储区1、全局存储区1.1 全局变量…...

2024年10月23日Github流行趋势

项目名称&#xff1a;hiteshchoudhary / apihub 项目维护者&#xff1a;wajeshubham, atulbhatt-system32, jwala-anirudh, arnb-smnta, shrey-dadhaniya 项目介绍&#xff1a;您自己的API Hub&#xff0c;用于学习和掌握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 分糖果

题目描述 某个幼儿园里&#xff0c;有 55 位小朋友编号依次为 1,2,3,4,51,2,3,4,5 他们按照自己的编号顺序围坐在一张圆桌旁。他们身上有若干糖果&#xff0c;现在他们玩一个分糖果游戏。从 11 号小朋友开始&#xff0c;将自己的糖果均分成 33 份&#xff08;如果有多余的糖果…...

VBA字典与数组第二十讲:如何在代码运行时创建数组

《VBA数组与字典方案》教程&#xff08;10144533&#xff09;是我推出的第三套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;字典是VBA的精华&#xff0c;我要求学员必学。7.1.3.9教程和手册掌握后&#xff0c;可以解决大多数工作中遇到的实际问题。…...

字符串统计(Python)

接收键盘任意录入&#xff0c;分别统计大小写字母、数字及其它字符数量&#xff0c;打印输出。 (笔记模板由python脚本于2024年11月02日 08:23:31创建&#xff0c;本篇笔记适合熟悉python字符串并懂得基本编程技法的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xf…...

NVR小程序接入平台/设备EasyNVR多个NVR同时管理视频监控新选择

在数字化转型的浪潮中&#xff0c;视频监控作为安防领域的核心组成部分&#xff0c;正经历着前所未有的技术革新。随着技术的不断进步和应用场景的不断拓展&#xff0c;视频监控系统的兼容性、稳定性以及安全性成为了用户关注的焦点。NVR小程序接入平台/设备EasyNVR&#xff0c…...

怎样能把图片做压缩处理?学会4款在线工具高效压缩图片

随着现在图片质量不断的提高&#xff0c;导致图片的大小也越来越大&#xff0c;很多的网上平台只能上传比较小的图片&#xff0c;那么可以使用压缩图片或者图片改尺寸的方式来修改图片大小&#xff0c;那么图片压缩的操作技巧是什么样的呢&#xff1f;本文将带大家了解4个操作简…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案

引言 在分布式系统的事务处理中&#xff0c;如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议&#xff08;2PC&#xff09;通过准备阶段与提交阶段的协调机制&#xff0c;以同步决策模式确保事务原子性。其改进版本三阶段提交协议&#xff08;3PC&#xf…...

C# winform教程(二)----checkbox

一、作用 提供一个用户选择或者不选的状态&#xff0c;这是一个可以多选的控件。 二、属性 其实功能大差不差&#xff0c;除了特殊的几个外&#xff0c;与button基本相同&#xff0c;所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...