【C++】string类(上):string类的常用接口介绍
文章目录
- 前言
- 一、C++中设计string类的意义
- 二、string类的常用接口说明
- 1. string类对象的常见构造
- 2. string类对象的容量操作
- 2.1 size、capacity 和 empty的使用
- 2.2 clear的使用
- 2.3 reserve的使用
- 2.4 resize的使用
- 3. string类对象的访问及遍历操作
- 3.1 下标[ ] 和 at
- 3.2 迭代器iterator
- 3.3 范围for
- 4. string类对象的修改操作
- 4.1 push_back、append 和 operator+=(在字符串后追加字符)
- 4.2 insert(在字符串任意位置追加字符)
- 4.3 erase(删除指定范围的字符)
- 4.3 replace(替换字符串中指定范围的字符)
- 5. string类对象的字符串操作
- 5.1 c_str的使用
- 5.2 find的使用
- 5.3 rfind的使用
- 5.4 substr(从字符串中提取一个子字符串)
- 6. string类非成员函数
- 6.1 operator+
- 6.2 relational operators系列函数
- 6.3 >>运算符重载 和 getline函数的区别
前言
一、C++中设计string类的意义
二、string类的常用接口说明(string类对象的常见构造、容量操作、遍历操作、修改操作和查找操作等接口,以及一些string类非成员函数的接口)
一、C++中设计string类的意义
C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中还提供了一些字符串操作库函数,但是这些库函数与字符串是分离开的,而且底层空间需要用户自己管理,操作繁琐且容易出错(如内存越界、忘记释放内存等)。
C++的string类封装了字符串的存储和操作,提供了更安全、便捷的接口。string类自动管理字符串的内存分配和释放,避免了手动管理内存的复杂性,减少了内存泄漏和悬空指针的风险;string类还提供了丰富的成员函数,如拼接、查找、替换、比较等,简化了字符串的常见操作;而且string类是类型安全的,避免了C语言中字符数组和指针的潜在问题,如类型不匹配或越界访问。
二、string类的常用接口说明
(string类的所有接口说明详见链接: link)
1. string类对象的常见构造
C++11中,std::string类的构造函数的所有重载类型如下:
std::string类对象的常见构造介绍:
(constructor)函数名称 | 功能说明 |
---|---|
string() | 构造空的std::string类对象,即空字符串 |
string(const char* s) | 用C-string来构造std::string类对象 |
string(size_t n, char c) | 用n个c字符构造std::string类对象 |
string(const string& str) | 拷贝构造函数 |
string (const string& str, size_t pos, size_t len = npos); | 用str中字符串的pos位置往后的len个字符来构造初始化std::string类对象,如果len大于字符串pos位置往后的字符串长度,取到末尾也会停止 |
补充:npos是std::string类中的定义的public静态成员常量,它的数据类型是size_t
size_t 是一种无符号整数类型,当你将 -1 赋值给一个 size_t 类型的变量/常量时,会发生类型转换。由于 -1 是一个负数,而 size_t 是无符号类型(只能表示正数),因此 -1 会被转换为 size_t 类型的最大值。
#include <string>
using namespace std;int main()
{string s1; // 构造空的string类对象s1string s2("hello world"); // 用C格式字符串构造string类对象s2string s3(6, 'x'); // 用6个'x'字符构造string类对象s3string s4(s2); // 用对象s2拷贝构造s4string s5(s2, 5, 10); // 用s2中字符串pos位置往后的10个字符构造s5,// s2中字符串pos位置往后不够10个字符,取到其末尾停止return 0;
}
2. string类对象的容量操作
2.1 size、capacity 和 empty的使用
函数名称 | 功能说明 |
---|---|
size(通用) | 返回字符串有效字符长度(不包括’\0’) |
length(用法同size) | 返回字符串有效字符长度 |
capacity | 返回空间(容量)总大小(不包括’\0’) |
empty | 检测字符串是否为空串,是返回true,否则返回false |
补充:size()与length()方法底层实现原理完全相同,size()是后来添加的,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。
(1) size和capacity的使用
#include <string>
#include <iostream>
using namespace std;
int main()
{string s1("wukong");cout << "s1的有效字符长度:" << s1.size() << endl;cout << "s1的容量:" << s1.capacity() << endl;string s2("I love Minecraft");cout << "s2的有效字符长度:" << s2.size() << endl;cout << "s2的容量:" << s2.capacity() << endl;return 0;
}
(2)empty的使用
#include <string>
#include <iostream>
using namespace std;
int main()
{string s1;cout << s1.empty() << endl;string s2("I love Minecraft");cout << s2.empty() << endl;return 0;
}
2.2 clear的使用
std::string 类提供的 clear() 成员函数,用于清除字符串中的所有字符,使字符串变为空字符串。这个方法不会改变字符串的容量,只是将字符串的长度设置为0。
#include <string>
#include <iostream>
using namespace std;
int main()
{string s1("I love Minecraft");cout << "s1是否为空串:" << s1.empty() << endl;cout << "s1的有效字符长度:" << s1.size() << endl;cout << "s1的容量:" << s1.capacity() << endl;s1.clear();cout << "s1是否为空串:" << s1.empty() << endl;cout << "s1的有效字符长度:" << s1.size() << endl;cout << "s1的容量:" << s1.capacity() << endl;return 0;
}
2.3 reserve的使用
std::string 类提供的 reserve() 成员函数,用于请求字符串对象的容量调整。
注:这个函数不会改变字符串的有效字符长度,也不会修改字符串有效字符中的内容。
(1)使用 reserve() 扩容(vs2022运行结果):
#include <string>
#include <iostream>
using namespace std;
int main()
{string s1("wukong");cout << "s1的有效字符长度:" << s1.size() << endl;cout << "s1的容量:" << s1.capacity() << endl;s1.reserve(50); // 将容量扩到50字节,但实际扩到了63字节,// 这是由于内存对齐的一些规则导致的,但只会多扩,不会少扩 cout << "s1的有效字符长度:" << s1.size() << endl;cout << "s1的容量:" << s1.capacity() << endl;return 0;
}
(2)使用 reserve() 缩容(vs2022不执行reserve函数的缩容命令):
#include <string>
#include <iostream>
using namespace std;
int main()
{string s1("wukong");cout << "s1的有效字符长度:" << s1.size() << endl;cout << "s1的容量:" << s1.capacity() << endl;s1.reserve(10); cout << "s1的有效字符长度:" << s1.size() << endl;cout << "s1的容量:" << s1.capacity() << endl;s1.reserve(5);cout << "s1的有效字符长度:" << s1.size() << endl;cout << "s1的容量:" << s1.capacity() << endl;return 0;
}
总结:
(1)扩容:如果请求的新容量大于当前容量,字符串会分配新的存储空间,使容量至少等于请求的新容量。
(2)缩容:如果请求的新容量小于当前容量,字符串的容量可能不会改变(因编译器而异)。
因为reserve函数的缩容机制因编译器而异,所以我们一般不会使用这个函数缩容。我们一般只用reserve函数进行扩容,使用场景如下:在你预先知道字符串将增长到某个大小时,可以使用reserve函数提前分配足够的空间,避免频繁扩容。
2.4 resize的使用
std::string 类提供的 resize() 成员函数,用于改变字符串的大小。
如果新的大小大于当前大小,字符串会用指定的字符填充(如果未指定填充字符,默认使用’\0’填充);如果新的大小小于当前大小,字符串会被截断。
(1)使用resize函数增加字符串大小:
int main()
{string s1("wukong");cout << s1 << endl;cout << "s1的有效字符长度:" << s1.size() << endl;cout << "s1的容量:" << s1.capacity() << endl;s1.resize(10,'x');cout << s1 << endl;cout << "s1的有效字符长度:" << s1.size() << endl;cout << "s1的容量:" << s1.capacity() << endl;s1.resize(20,'x');cout << s1 << endl;cout << "s1的有效字符长度:" << s1.size() << endl;cout << "s1的容量:" << s1.capacity() << endl;return 0;
}
(2)使用resize函数缩小字符串大小:
int main()
{string s1("wukong");cout << s1 << endl;cout << "s1的有效字符长度:" << s1.size() << endl;cout << "s1的容量:" << s1.capacity() << endl;s1.resize(4);cout << s1 << endl;cout << "s1的有效字符长度:" << s1.size() << endl;cout << "s1的容量:" << s1.capacity() << endl;return 0;
}
总结:
(1)增加大小:如果新的大小大于当前大小,字符串会用指定的字符填充。如果未指定填充字符,默认使用空字符(‘\0’)填充。
(2)减少大小:如果新的大小小于当前大小,字符串会被截断,超出部分的字符会被丢弃。
(3)容量调整:resize 方法可能会改变字符串的容量。如果新的大小大于字符串的当前容量,就会扩容。
3. string类对象的访问及遍历操作
3.1 下标[ ] 和 at
函数名称 | 功能说明 |
---|---|
operator[ ] | 返回pos位置的字符(越界访问的情况是不确定的) |
at | 返回pos位置的字符(越界访问会抛异常) |
(1) 使用下标[ ]访问及遍历std::string类对象中内容(调用operator[ ]函数,注意它两个版本的区别):
#include <string>
#include <iostream>
using namespace std;
int main()
{string s1("abcdef");for (size_t i = 0; i < s1.size(); ++i){s1[i] += 1;cout << s1[i];// 普通对象调用 char& operator[](size_t pos); // 返回字符串中指定位置字符的引用(char&),// 这意味着你可以通过返回的引用修改字符串中的字符。}cout << endl;const string s2("abcdef");for (size_t i = 0; i < s1.size(); ++i){cout << s2[i];// const对象调用 const char& operator[](size_t pos) const; // 返回字符串中指定位置字符的常引用(const char&),// 这意味着你只能读取字符串中的字符,而无法进行修改。}cout << endl;return 0;
}
(2)使用at访问及遍历std::string类对象中内容(调用at函数,它的使用跟operator[ ]函数类似):
#include <string>
#include <iostream>
using namespace std;
int main()
{string s1("abcdef");for (size_t i = 0; i < s1.size(); ++i){s1[i] += 1;cout << s1.at(i);}cout << endl;const string s2("abcdef");for (size_t i = 0; i < s1.size(); ++i){cout << s2.at(i);}cout << endl;return 0;
}
3.2 迭代器iterator
函数名称 | 功能说明 |
---|---|
begin | 获取字符串第一个字符的迭代器 |
end | 获取字符串(不包括’\0’)最后一个字符下一个位置的迭代器 |
int main()
{string s1("abcdefgh");string::iterator it1 = s1.begin();// 普通对象调用 iterator begin();// 返回指向字符串第一个字符的普通迭代器,允许修改字符串中的字符。while (it1 != s1.end()){(*it1)++;cout << *it1;++it1;}cout << endl;const string s2("abcdefgh");string::const_iterator it2 = s2.begin();// const对象调用 const_iterator begin() const;// 返回指向字符串第一个字符的const迭代器,只允许读取字符串中的字符,不能修改。while (it2 != s2.end()){cout << *it2;++it2;}cout << endl;return 0;
}
为什么用 iterator(迭代器) 定义变量/对象时要指定类域?
要知晓原因需研究一下 iterator 的底层实现。
iterator 在底层的实现方式一般有以下两种:
(1)内部类实现: iterator(正向迭代器)是定义在string类中的内部类,内部类可以访问外部类的私有成员,从而实现高效的迭代器操作。定义内部类的对象时需要指定外部类类域。
(2)指针实现: 在一些简单的容器(如array,vector,string等)中,iterator可以直接通过指针实现。比如,在string类中,将 char* 类型重命名为 iterator,代码如下:typedef char* iterator。因为是在string类中将 char* 重命名为 iterator,所以在类外要使用string类中的 iterator类型定义变量时需要指定类域。
所以无论 iterator 在底层的实现方式是以上的哪一种,在使用 iterator(迭代器) 定义变量/对象时都需要指定类域。
3.3 范围for
对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此
C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。
范围for的应用:
(1)范围for可以作用到数组和容器对象上进行遍历
(2)范围for的底层很简单,数组遍历实际就是使用指针(编译器会将范围for循环转换为基于指针的循环,使用数组的首地址和末地址来遍历数组中的元素);容器遍历实际就是替换为迭代器(范围for循环在容器中的底层实现是通过调用容器的begin()和end()方法来获取迭代器,并使用这些迭代器来遍历容器中的元素)
#include <string>
#include <iostream>
using namespace std;
int main()
{char array[] = "wukong";for (char e : array){cout << e;}cout << endl;string str("one piece");for (char ch : str){cout << ch;} cout << endl;return 0;
}
4. string类对象的修改操作
4.1 push_back、append 和 operator+=(在字符串后追加字符)
函数名称 | 功能说明 |
---|---|
push_back | 在字符串后尾插字符 |
append | 在字符串后追加一个字符串或字符序列 |
operator+= | 在字符串后追加一个字符串或字符 |
(1)std::string类提供的push_back成员函数,用于将一个字符追加到字符串的末尾。
#include <string>
#include <iostream>
using namespace std;
int main()
{string s1("wukong");cout << s1 << endl;s1.push_back('o');cout << s1 << endl;s1.push_back('n');cout << s1 << endl;s1.push_back('e');cout << s1 << endl;return 0;
}
(2)std::string类提供的append成员函数(运算符重载),用于将一个字符串或字符序列追加到当前字符串的末尾。
示例一(追加另一个字符串的一部分到当前字符串的末尾):
#include <string>
#include <iostream>
using namespace std;
int main()
{string s1("zhangsan");cout << s1 << endl;string s2("i love you");s1.append(s2, 1, 5);// 调用 string& append(const string& str, size_t subpos, size_t sublen);// 用于将另一个字符串的一部分(从subpos位置往后sublen个字符)追加到当前字符串的末尾。// subpos位置往后的字符个数不够sublen,到末尾也会停止,不会额外追加。cout << s1 << endl;string s3("i like apple");s1.append(s3, 6, 20);cout << s1 << endl;return 0;
}
示例二(追加字符数组的前n个字符到当前字符串的末尾):
#include <string>
#include <iostream>
using namespace std;
int main()
{string s1("one piece ");cout << s1 << endl;char a1[] = "is still enough";s1.append(a1, 9);// 调用 string& append(const char* s, size_t n);// 用于将字符数组的前n个字符追加到当前字符串的末尾。cout << s1 << endl;char a2[] = "missing is silent";s1.append(a2, 7);cout << s1 << endl;return 0;
}
(3)std::string类提供的operator+=成员函数,用于将一个字符串、字符数组或单个字符追加到当前字符串的末尾。
#include <string>
#include <iostream>
using namespace std;
int main()
{string s1("One Piece ");cout << s1 << endl;string s2("is a ");s1 += s2;cout << s1 << endl;char a1[] = "Miracle";s1 += a1;cout << s1 << endl;s1 += '!';cout << s1 << endl;return 0;
}
4.2 insert(在字符串任意位置追加字符)
std::string类提供的insert成员函数,用于在字符串的指定位置插入新的字符或子串。
示例一(在指定位置插入另一个字符串的子串):
#include <string>
#include <iostream>
using namespace std;
int main()
{string str1 = "i one piece!";string str2 = "peace and love";str1.insert(1, str2, 9, 20);// 调用string& insert(size_t pos, const string& str, size_t subpos, size_t sublen);// 参数:// pos:插入的位置。// str:要插入的std::string对象。// subpos:从str中开始插入的位置。// sublen:要插入的字符数。cout << str1 << endl;return 0;
}
示例二(在指定位置插入C风格字符串的前n个字符):
#include <string>
#include <iostream>
using namespace std;
int main()
{string str1 = "war and !";char ch[] = "peace and love";str1.insert(8, ch, 5);// 调用string& insert (size_t pos, const char* s, size_t n);// 在指定位置插入C风格字符串的前n个字符。cout << str1 << endl;return 0;
}
示例三(在指定位置插入n个字符):
#include <string>
#include <iostream>
using namespace std;
int main()
{string str1 = "hello";str1.insert(2, 5, 'x');// 调用string& insert (size_t pos, size_t n, char c);// 在指定位置插入n个c字符。cout << str1 << endl;return 0;
}
4.3 erase(删除指定范围的字符)
std::string类提供的erase成员函数,用于从字符串中删除指定范围的字符。
#include <string>
#include <iostream>
using namespace std;
int main()
{string str1 = "hello world!";str1.erase(6, 5);// 调用string& erase (size_t pos = 0, size_t len = npos);// 参数:// pos:开始删除的位置。// n:要删除的字符数。cout << str1 << endl;return 0;
}
4.3 replace(替换字符串中指定范围的字符)
std::string类提供的replace成员函数,用于替换字符串中指定范围的字符。
示例一(将字符串中指定范围的字符替换成另一个字符串的子串):
#include <string>
#include <iostream>
using namespace std;
int main()
{string str1 = "xxx xxxxxxxxxx xxx";string str2 = "one two three";str1.replace(4, 10, str2, 8, 10);// 调用string& replace (size_t pos, size_t len, const string& str,// size_t subpos, size_t sublen);// 参数:// pos:开始替换的位置。// n:要替换的字符数。// str:用于替换的std::string对象。// subpos:在str中用于替换的起始位置。// sublen:用于替换的字符长度cout << str1 << endl;return 0;
}
示例二(将字符串中指定范围的字符替换成C风格字符串的前n个字符):
#include <string>
#include <iostream>
using namespace std;
int main()
{string str1 = "xxx xxxxxxxxxx xxx";char ch[] = "one two three";str1.replace(4, 10, ch, 3);// 调用string& replace (size_t pos, size_t len, const char* s, size_t n);// 将字符串中指定范围的字符替换成C风格字符串的前n个字符cout << str1 << endl;return 0;
}
示例三(将字符串中指定范围的字符替换成n个c字符):
int main()
{string str1 = "xxx xxxxxxxxxx xxx";str1.replace(4, 10, 5, 'o');// 调用 string& replace (size_t pos, size_t len, size_t n, char c);// 将字符串中指定范围的字符替换成n个c字符cout << str1 << endl;return 0;
}
5. string类对象的字符串操作
5.1 c_str的使用
std::string类提供的 c_str 成员函数,返回 C 格式字符串。
这个函数在需要将 std::string 对象传递给需要 C 格式字符串的函数时非常有用。
#include <string>
#include <iostream>
using namespace std;
int main()
{string str("Please split this sentence into tokens");char* cstr = new char[str.size() + 1];strcpy(cstr, str.c_str());// char* strcpy(char* destination, const char* source );cout << cstr << endl;delete[] cstr;return 0;
}
5.2 find的使用
std::string类提供的 find 成员函数,从字符串pos位置开始往后找指定的字符或子串,找到了返回字符或子串首次出现的位置。如果未找到字符或子串,则返回一个特殊的常量 std::string::npos,表示“未找到”。
示例一(从字符串pos位置开始往后找指定的字符串):
int main()
{string s1 = "Hello World!";string s2 = "World";size_t pos = s1.find(s2);// pos不指定默认为0cout << pos << endl;return 0;
}
示例二(从字符串pos位置开始往后找指定的C风格字符串):
int main()
{string s1 = "Hello World!";size_t pos = s1.find("llo");cout << pos << endl;return 0;
}
示例三(从字符串pos位置开始往后找指定的字符):
int main()
{string s1 = "war and peace";size_t pos = s1.find(' ');while (pos != string::npos){s1[pos] = 'X';pos = s1.find(' ', pos + 1);}cout << s1 << endl;return 0;
}
5.3 rfind的使用
std::string 类中的 rfind 成员函数,用于在字符串中从后向前查找指定的字符或子串,找到了返回字符或子串最后一次出现的位置。如果未找到字符或子串,则返回一个特殊的常量 std::string::npos,表示“未找到”。
int main()
{string s1 = "war war war war";size_t pos = s1.rfind("war");cout << pos << endl;return 0;
}
5.4 substr(从字符串中提取一个子字符串)
std::string 类中的 substr 成员函数,用于从字符串中提取一个子字符串,通过指定起始位置和长度来获取子字符串。
#include <string>
#include <iostream>
using namespace std;
int main()
{string s1 = "Hello World!";string s2 = s1.substr(6, 5);cout << s2 << endl;return 0;
}
6. string类非成员函数
函数名称 | 功能说明 |
---|---|
operator+ | 尽量少用,因为传值返回,导致深拷贝效率低 |
operator>> | 输入运算符重载 |
operator<< | 输出运算符重载 |
getline | 获取一行字符串 |
relational operators | 大小比较 |
6.1 operator+
std::string 类提供了多种方式来连接字符串,其中 operator+ 是一个常用的非成员函数,operator+ 的非成员函数形式允许你将两个字符串连接起来,或者将字符串与其他类型的对象(如C风格字符串、字符等)连接起来。
示例中依次调用以上operator+ 非成员函数的5种重载形式:
#include <iostream>
#include <string>
using namespace std;
int main() {std::string str1 = "Hello, ";std::string str2 = "world!";const char* cstr = "C-style string";char ch = '!';// 连接两个 string类对象string result1 = str1 + str2;// 连接 string类对象 和 C风格字符串string result2 = str1 + cstr;// 连接 C风格字符串 和 string类对象string result3 = cstr + str1;// 连接 string对象 和 字符string result4 = str1 + ch;// 连接 字符 和 string对象string result5 = ch + str1;cout << result1 << endl;cout << result2 << endl;cout << result3 << endl;cout << result4 << endl;cout << result5 << endl;return 0;
}
6.2 relational operators系列函数
std::string 类提供了一系列非成员函数形式的关系运算符的重载(Relational Operators),用于比较两个字符串 或 字符串与C风格字符串。
这些运算符包括:==(等于)、!=(不等于)、<(小于)、<=(小于等于)、>(大于)和 >=(大于等于)。
int main() {std::string str1 = "apple";std::string str2 = "banana";const char* cstr = "apple";// 比较两个 std::string 对象cout << "str1 == str2: " << (str1 == str2) << endl; cout << "str1 != str2: " << (str1 != str2) << endl; cout << "str1 < str2: " << (str1 < str2) << endl; // 比较 std::string 和 C风格字符串cout << "str1 == cstr: " << (str1 == cstr) << endl; cout << "str1 != cstr: " << (str1 != cstr) << endl; cout << "str1 < cstr: " << (str1 < cstr) << endl;// 比较 C风格字符串 和 std::stringcout << "cstr == str2: " << (cstr == str2) << endl; cout << "cstr != str2: " << (cstr != str2) << endl;cout << "cstr < str2: " << (cstr < str2) << endl; return 0;
}
6.3 >>运算符重载 和 getline函数的区别
(1) >>运算符重载
>>是流提取运算符,通常用于从输入流(如 std::cin)中读取数据。
行为:
读取数据时,会跳过前导空白字符(如空格、制表符、换行符等)。
读取到第一个空白字符时停止,空白字符不会被包含在结果中。
适用于读取单个单词或简单数据类型(如 int、double、std::string 等)。
示例:
int main()
{string word;cin >> word;// 输入" hello world"// >>运算符重载读取数据时,会跳过前导空白字符;// 开始读取有效字符时,读取到第一个空白字符时停止,空白字符不会被包含在结果中。// 所以 word 的值为"hello"cout << "输出:" << word << endl;return 0;
}
(2) getline 函数
getline 是专门用于从输入流中读取一行数据的函数。
行为:
读取整行内容,直到遇到指定的分隔符(默认为换行符 \n)。
不会跳过前导空白字符,会读取包括空格在内的所有字符。
读取的内容包含分隔符之前的所有字符,但不包括分隔符本身。
示例一(分隔符默认为换行符 \n):
int main()
{string word;getline(cin, word);// 输入 " hello world"// getline函数读取数据时,不会跳过前导空白字符,// 一直读取内容直到遇到指定的分隔符(默认为换行符 \n),// 所以 word 的值为 " hello world"cout << "输出:" << word << endl;return 0;
}
示例二(自己指定的分隔符):
int main()
{string word;getline(cin, word, '+');// 输入 " hello world/ncrazy 6+1"// getline函数读取数据时,会一直读取到到指定的分隔符'+'才停止// 所以 word 的值为 " hello world/ncrazy 6"cout << "输出:" << word << endl;return 0;
}
相关文章:
【C++】string类(上):string类的常用接口介绍
文章目录 前言一、C中设计string类的意义二、string类的常用接口说明1. string类对象的常见构造2. string类对象的容量操作2.1 size、capacity 和 empty的使用2.2 clear的使用2.3 reserve的使用2.4 resize的使用 3. string类对象的访问及遍历操作3.1 下标[ ] 和 at3.2 迭代器it…...
[SAP ABAP] ABAP SQL跟踪工具
事务码ST05 操作步骤 步骤1:使用事务码ST05之前,将要检测的程序生成的页面先呈现出来,这里我们想看下面程序的取数操作,所以停留在选择界面 步骤2: 新建一个GUI窗口,输入事务码ST05,点击 Acti…...
OpenGL学习笔记(六):Transformations 变换(变换矩阵、坐标系统、GLM库应用)
文章目录 向量变换使用GLM变换(缩放、旋转、位移)将变换矩阵传递给着色器坐标系统与MVP矩阵三维变换绘制3D立方体 & 深度测试(Z-buffer)练习1——更多立方体 现在我们已经知道了如何创建一个物体、着色、加入纹理。但它们都还…...
PHP 常用函数2025.02
PHP implode() 函数 语法 implode(separator,array) 参数描述separator可选。规定数组元素之间放置的内容。默认是 ""(空字符串)。array必需。要组合为字符串的数组。 技术细节 返回值:返回一个由数组元素组合成的字符串。PHP 版…...
17.3.4 颜色矩阵
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 17.3.4.1 矩阵基本概念 矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合,类似于数组。 由…...
1. 【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--前言
在我们的专栏《单体开发》中,我们实现了一个简单的记账软件的服务端,并且成功上线。随着用户数量的不断增长,问题逐渐开始显现。访问量逐渐增加,服务端的压力也随之加大。随着访问量的攀升,服务端的响应时间变得越来越…...
02.04 数据类型
请写出以下几个数据的类型: 整数 a ----->int a的地址 ----->int* 存放a的数组b ----->int[] 存放a的地址的数组c ----->int*[] b的地址 ----->int* c的地址 ----->int** 指向printf函数的指针d ----->int (*)(const char*, ...) …...
WPS动画:使图形平移、围绕某个顶点旋转一定角度
1、平移 案例三角形如下图,需求:该三角形的A点平移至原点 (1)在预想动画结束的位置绘制出图形 (2)点击选中原始图像,插入/动画/绘制自定义路径/直线 (3)十字星绘制的直线…...
想表示消息返回值为Customer集合
道奈特(240***10) 14:34:55 EA中序列图。我想表示消息返回值为 Customer 集合。目前只有一个Customer实体类,我需要另外新建一个CustomerList 类吗? 潘加宇(35***47) 17:01:26 不需要。如果是分析,在类的操作中,定义一个参数&…...
93,【1】buuctf web [网鼎杯 2020 朱雀组]phpweb
进入靶场 页面一直在刷新 在 PHP 中,date() 函数是一个非常常用的处理日期和时间的函数,所以应该用到了 再看看警告的那句话 Warning: date(): It is not safe to rely on the systems timezone settings. You are *required* to use the date.timez…...
五、定时器实现呼吸灯
5.1 定时器与计数器简介 定时器是一种通过对内部时钟脉冲计数来测量时间间隔的模块。它的核心是一个递增或递减的寄存器(计数器值)。如果系统时钟为 1 MHz,定时器每 1 μs 计数一次。 计数器是一种对外部事件(如脉冲信号ÿ…...
顺序打印数字的进一步理解
之前博客写了篇博文,面试时要求使用多线程顺序打印ABC循环20次,这是我当时使用join函数实现代码: public class TestABCJoin {public static void main(String[] args) {// 创建任务Runnable taskA () -> {for (int i 0; i < 5; i) …...
使用React和Material-UI构建TODO应用的前端UI
使用React和Material-UI构建TODO应用的前端UI 引言环境准备代码解析1. 导入必要的模块2. 创建React组件3. 定义函数3.1 获取TODO列表3.2 创建TODO项3.3 更新TODO项3.4 删除TODO项3.5 处理编辑点击事件3.6 关闭编辑对话框3.7 保存编辑内容 4. 使用Effect钩子5. 渲染组件 功能实现…...
开屏广告-跳过神器
给大家介绍一款超实用的软件——SKIP,它堪称李跳跳的最佳平替!这款软件已经在Github开源免费,完全无需担心内置源问题,也无需导入任何规则。安装完成后,即可直接使用,非常便捷! 首次打开软件时…...
bat脚本实现自动化漏洞挖掘
bat脚本 BAT脚本是一种批处理文件,可以在Windows操作系统中自动执行一系列命令。它们可以简化许多日常任务,如文件操作、系统配置等。 bat脚本执行命令 echo off#下面写要执行的命令 httpx 自动存活探测 echo off httpx.exe -l url.txt -o 0.txt nuc…...
如何运行Composer安装PHP包 安装JWT库
1. 使用Composer Composer是PHP的依赖管理工具,它允许你轻松地安装和管理PHP包。对于JWT,你可以使用firebase/php-jwt这个库,这是由Firebase提供的官方库。 安装Composer(如果你还没有安装的话): 访问Co…...
(回溯递归dfs 电话号码的字母组合 remake)leetcode 17
只找边界条件和非边界条件,剩下的交给数学归纳法就行,考虑子问题的重复性 [class Solution {vector<string>str { "","","abc","def","ghi","jkl","mno","pqrs"…...
it基础使用--5---git远程仓库
文章目录 it基础使用--5---git远程仓库1. 按顺序看2. 什么是远程仓库3. Gitee操作3.1 新建远程仓库3.2 远程操作基础命令3.3 查看当前所有远程地址别名 git remote -v3.4 创建远程仓库别名 git remote add 别名 远程地址3.4 推送本地分支到远程仓库 git push 别名 分支3.5 拉取…...
Git 的起源与发展
序章:版本控制的前世今生 在软件开发的漫长旅程中,版本控制犹如一位忠诚的伙伴,始终陪伴着开发者们。它的存在,解决了软件开发过程中代码管理的诸多难题,让团队协作更加高效,代码的演进更加有序。 简单来…...
c++提取矩形区域图像的梯度并拟合直线
c提取旋转矩形区域的边缘最强梯度点,并拟合直线 #include <opencv2/opencv.hpp> #include <iostream> #include <vector>using namespace cv; using namespace std;int main() {// 加载图像Mat img imread("image.jpg", IMREAD_GRAYS…...
【PyQt】超级超级笨的pyqt计算器案例
计算器 1.QT Designer设计外观 1.pushButton2.textEdit3.groupBox4.布局设计 2.加载ui文件 导入模块: sys:用于处理命令行参数。 QApplication:PyQt5 应用程序类。 QWidget:窗口基类。 uic:用于加载 .ui 文件。…...
每日一题——小根堆实现堆排序算法
小根堆实现堆排序算法 堆排序的基本思想堆排序的步骤 实现步骤1. 构建小根堆2. 删除最小元素并调整堆 C语言实现输出示例代码解释1. percolateDown 函数2. buildMinHeap 函数3. heapSort 函数4. printArray函数 排序过程详解步骤1:构建小根堆步骤2:删除堆…...
k8s集群
文章目录 项目描述项目环境系统与软件版本概览项目步骤 环境准备IP地址规划关闭selinux和firewall配置静态ip地址修改主机名添加hosts解析 项目步骤一、使用kubeadm安装k8s单master的集群环境(1个master2个node节点)1、互相之间建立免密通道2.关闭交换分…...
数据分析系列--[11] RapidMiner,K-Means聚类分析(含数据集)
一、数据集 二、导入数据 三、K-Means聚类 数据说明:提供一组数据,含体重、胆固醇、性别。 分析目标:找到这组数据中需要治疗的群体供后续使用。 一、数据集 点击下载数据集 二、导入数据 三、K-Means聚类 Ending, congratulations, youre done....
技术架构师成长路线(2025版)
目录 通用知识 计算机原理(1 - 2 个月) 数据结构(2 - 3 个月) 网络编程(1 - 2 个月) 软件工程(1 个月) 基础知识 Java 编程语言基础(2 - 3 个月) JVM&…...
NetLify账号无法登录解决办法
本文收录在【建站】专栏内,专栏目录:【建站】专栏目录 用github账号登录时,说校验失败 Authentication Error Authenticating failed due to the following error: Your account requires additional verification. Please check your email…...
linux本地部署deepseek-R1模型
国产开源大模型追平甚至超越了CloseAI的o1模型,大国崛起时刻!!! DeepSeek R1 本地部署指南 在人工智能技术飞速发展的今天,本地部署AI模型成为越来越多开发者和企业关注的焦点。本文将详细介绍如何在本地部署DeepS…...
集合通讯概览
集合通信概览 (1)通信的算法 是根据通讯的链路组成的 (2)因为通信链路 跟硬件强相关,所以每个CCL的库都不一样 芯片与芯片、不同U之间是怎么通信的 多卡训练:多维并行(xxx并行在上一期已经讲述…...
如何解决云台重力补偿?
如何解决云台重力补偿? 最近在调试步兵云台的时候,由于枪管、图传、摄像头等重力的原因,pitch轴的参数尤其难以调整,又不想抬升和降低使用两套不同的参数,所以使用了重力补偿,效果也是比较理想的,于是整理为一篇文章记录一下 一、问题根源:枪管重力在“搞事情” 想象…...
【LeetCode 刷题】回溯算法(4)-排列问题
此博客为《代码随想录》二叉树章节的学习笔记,主要内容为回溯算法排列问题相关的题目解析。 文章目录 46.全排列47.全排列 II 46.全排列 题目链接 class Solution:def permute(self, nums: List[int]) -> List[List[int]]:res, path [], []used [0] * len(n…...
FPGA|IP核PLL调用测试:建立工程
闲来无事,测试下FPGA的IP核调用 一、生成工程 1、打开软件新建工程 2、命名为PLL_test 3、选择芯片型号 4、生成工程如图...
数据的表示和运算
一-定点数的表示 1-定点数和浮点数 定点数:小数点的位置固定(常规计数) 浮点数:小数点的位置不固定(科学计数法) 2-定点数的表示 ①无符号数 整个机器字长的全部二进制位均为数值位,没有符号…...
文字显示省略号
多行文本溢出显示省略号...
22.Word:小张-经费联审核结算单❗【16】
目录 NO1.2 NO3.4 NO5.6.7 NO8邮件合并 MS搜狗输入法 NO1.2 用ms打开文件,而不是wps❗不然后面都没分布局→页面设置→页面大小→页面方向→上下左右:页边距→页码范围:多页:拼页光标处于→布局→分隔符:分节符…...
鲸鱼算法 matlab pso
算法原理 鲸鱼优化算法的核心思想是通过模拟座头鲸的捕食过程来进行搜索和优化。座头鲸在捕猎时会围绕猎物游动并产生气泡网,迫使猎物聚集。这一行为被用来设计搜索策略,使算法能够有效地找到全局最优解。 算法步骤 初始化:随机生成一…...
c++之模板进阶
在前面的文章中,我们已经简单的了解了模板的使用,在这篇文章中,我们将继续深入探讨模板 1.模板的特化 1.1 概念 通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果&a…...
C语言中的信号量
信号是操作系统中用来传递特定消息的机制。操作系统可以使用这种方式将程序运行过程中发生的各类特殊情况发送给程序,并按照其指定的逻辑进行处理。信号名称都以 “SIG” 作为前缀,如程序访问非法内存时,会产生名为 SIGSEGV 的信号。 程序需…...
AI主流大模型介绍和API价格比较
主流的大模型系列 ###1. OpenAI: GPT-4,GPT-4 Turbo, GPT-4o OpenAI 的介绍: 全称:Open Artificial Intelligence,简称OpenAI。性质:起初为非营利性组织,后转变为由营利性公司OpenAI LP及非营…...
自主Shell命令行解释器
什么是命令行 我们一直使用的"ls","cd","pwd","mkdir"等命令,都是在命令行上输入的,我们之前对于命令行的理解: 命令行是干啥的?是为我们做命令行解释的。 命令行这个东西实际上是我们…...
git笔记-简单入门
git笔记 git是一个分布式版本控制系统,它的优点有哪些呢?分为以下几个部分 与集中式的版本控制系统比起来,不用担心单点故障问题,只需要互相同步一下进度即可。支持离线编辑,每一个人都有一个完整的版本库。跨平台支持…...
重新刷题求职2-DAY1
DAY1 1.704. 二分查找 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 最普通的二分查找,查用的习惯左闭右…...
浅析DDOS攻击及防御策略
DDoS(分布式拒绝服务)攻击是一种通过大量计算机或网络僵尸主机对目标服务器发起大量无效或高流量请求,耗尽其资源,从而导致服务中断的网络攻击方式。这种攻击方式利用了分布式系统的特性,使攻击规模更大、影响范围更广…...
路径规划之启发式算法之二十九:鸽群算法(Pigeon-inspired Optimization, PIO)
鸽群算法(Pigeon-inspired Optimization, PIO)是一种基于自然界中鸽子群体行为的智能优化算法,由Duan等人于2014年提出。该算法模拟了鸽子在飞行过程中利用地标、太阳和磁场等导航机制的行为,具有简单、高效和易于实现的特点,适用于解决连续优化问题。 更多的仿生群体算法…...
SwiftUI 在 Xcode 预览修改视图 FetchedResults 对象的属性时为什么会崩溃?
概览 从 SwiftUI 诞生那天起,让秃头码农们又爱又恨的 Xcode 预览就在界面调试中扮演了及其重要的角色。不过,就是这位撸码中的绝对主角却尝尝在关键时刻“掉链子”。 比如当修改 SwiftUI 视图中 FetchedResults 对象的属性时,Xcode 预览可能…...
pytorch实现基于Word2Vec的词嵌入
PyTorch 实现 Word2Vec(Skip-gram 模型) 的完整代码,使用 中文语料 进行训练,包括数据预处理、模型定义、训练和测试。 1. 主要特点 支持中文数据,基于 jieba 进行分词 使用 Skip-gram 进行训练,适用于小数…...
MVC 文件夹:架构之美与实际应用
MVC 文件夹:架构之美与实际应用 引言 MVC(Model-View-Controller)是一种设计模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种架构模式不仅提高了代码的可维护性和可扩展性,而且使得开发流程更加清晰。本文将深入探讨MVC文…...
Python在线编辑器
from flask import Flask, render_template, request, jsonify import sys from io import StringIO import contextlib import subprocess import importlib import threading import time import ast import reapp Flask(__name__)RESTRICTED_PACKAGES {tkinter: 抱歉&…...
The Simulation技术浅析(四):随机数生成
随机数生成技术 是 The Simulation 中的核心组成部分,广泛应用于蒙特卡洛模拟、密码学、统计建模等领域。随机数生成技术主要分为 伪随机数生成器(PRNG,Pseudo-Random Number Generator) 和 真随机数生成器(TRNG,True Random Number Generator)。 1. 伪随机数生成器(PR…...
centos stream 9 安装 libstdc++-static静态库
yum仓库中相应的镜像源没有打开,libstdc-static在CRB这个仓库下,但是查看/etc/yum.repos.d/centos.repo,发现CRB镜像没有开启。 解决办法 如下图开启CRB镜像, 然后执行 yum makecache yum install glibc-static libstdc-static…...
Java自定义IO密集型和CPU密集型线程池
文章目录 前言线程池各类场景描述常见场景案例设计思路公共类自定义工厂类-MyThreadFactory自定义拒绝策略-RejectedExecutionHandlerFactory自定义阻塞队列-TaskQueue(实现 核心线程->最大线程数->队列) 场景1:CPU密集型场景思路&…...