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

秒懂C++之string类(下)

fe594ea5bf754ddbb223a54d8fb1e7bc.gif

目录

一.接口说明

1.1 erase

1.2 replace(最好别用)

1.3 find

1.4 substr

1.5 rfind

1.6 find_first_of

1.7 find_last_of

二.string类的模拟实现

2.1 构造

2.2 无参构造

2.3 析构

2.4.【】运算符

2.5 迭代器

2.6 打印

2.7 reserve扩容

2.8 push_back尾插

2.9 append追加

2.10 insert插入

2.11 erase删除

2.12 swap交换

2.13 find寻找

2.14 运算符+=

2.15 substr

2.16 流插入<<

2.17 流提取>>

三.现代写法

拷贝构造

赋值拷贝

四.小拓展

五.全部代码


一.接口说明

1.1 erase

#include <iostream>
#include <string>
using namespace std;int main()
{string s1("hello world");s1.erase(0, 4);cout << s1 << endl;//o world 从下标为0开始,删除4个字符s1.erase();cout << s1 << endl;//return 0;}

1.2 replace(最好别用)

int main()
{string s1("hello world");string s2;s1.replace(0, 1, "aaaa");cout << s1 << endl;//aaaaello worldreturn 0;
}

替换指定位置内容,并挪动后面数据。

1.3 find

int main()
{string s1("hello world a b");// 所有的空格替换为100%size_t pos = s1.find(' ', 0);//从下标为0位置开始找while (pos != string::npos){s1.replace(pos, 1, "100%");// 效率很低,能不用就不要用了pos = s1.find(' ', pos + 4);}cout << s1 << endl;//hello100%world100%a100%breturn 0;
}

作用就是从头开始找到该字符并返回其下标位置。

之所以不用replace是因为有更好的替代~ 


int main()
{string s1("hello world a b");string s2;for (auto ch : s1){if (ch == ' '){s2 += "100%";}else{s2 += ch;}}s1.swap(s2);cout << s1 << endl;//hello100%world100%a100%breturn 0;
}

注意:

swap(s1,s2)与s1.swap(s2)可不一样,前者是通过有个中间变量进行交换,而后者是让双方指针进行交换,后者更为高效~

1.4 substr

int main()
{string s1("hello");string s2;s2 = s1.substr(1, 2);cout << s2 << endl;//elcout << s1.substr(1) << endl;//elloreturn 0;
}
str 中从 pos 位置开始,截取 n 个字符,然后将其返回

1.5 rfind

从末尾开始找字符并返回下标

int main()
{//获取后缀名string s1("Test.cpp");string s2("Test.tar.zar");size_t pos1 = s1.find('.');size_t pos2 = s2.rfind('.');if(pos1 != string::npos){string s3 = s1.substr(pos1);cout << s3 << endl;//.cppstring s4 = s2.substr(pos2);cout << s4 << endl;//.zar}return 0;
}

1.6 find_first_of

int main()
{string s1("hello world");size_t pos1 = s1.find_first_of("abcde");cout << pos1 << endl;//1pos1 = s1.find_first_of("ow");cout << pos1 << endl;//4return 0;
}

返回在选定字符串中任意一个字符第一次出现的下标。(从头开始遍历)

1.7 find_last_of

int main()
{string s1("hello world");size_t pos1 = s1.find_last_of("abcde");cout << pos1 << endl;//10pos1 = s1.find_last_of("h");cout << pos1 << endl;//0return 0;
}

返回在选定字符串中任意一个字符第一次出现的下标。(从尾开始遍历)

注意:find_first_not_of与find_last_not_of,就是返回指选定字符串之外的字符下标

int main()
{string s1("hello world");size_t pos1 = s1.find_first_not_of("abcde");cout << pos1 << endl;//0pos1 = s1.find_last_not_of("h");cout << pos1 << endl;//10return 0;
}

二.string类的模拟实现

2.1 构造

首先实现构造函数的时候在初始化列表不能直接这么写,涉及到了权限放大~

也不能在私有成员那写:const char* _str,这样_str以后只能指向一处,无法修改指向,也意味着无法增删改。

namespace lj
{class string{public://构造string(const char* str){_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];//加1是因为在_capacity那被认为‘\0’是有效字符strcpy(_str, str);}private:size_t _size;size_t _capacity;char* _str;};void test_string1(){string s1("aabbcc");//构造成功}
}

建议直接放弃在列表初始化,还得考虑声明顺序啥的挺麻烦~

2.2 无参构造

//无参构造string(){_str = nullptr;_size = 0;_capacity = 0;}//返回c格式字符串const char* c_str(){return _str;}

可惜这种无参写法不行,因为c_str是以指针的形式返回的(字符串形式),而cout接触到指针会认为是要打印字符串,直接解引用指针,一个空指针被解引用是错误的。

开辟个1字节的空间,里面放个字符(但不是有效字符)

不过与其写无参不如直接写缺省参数

//为什么字符串就能匹配上啊?,因为这样指针就能指向它,本身是地址。

2.3 析构

~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}

2.4.【】运算符

		char& operator[](size_t pos){return _str[pos];}

//为什么里面还能有【】,因为这个是给内置类型使用的,自定义类型要自己自定义

2.5 迭代器

typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}

其实迭代器实现也挺简单的~

for+auto的遍历底层逻辑其实还是迭代器。

2.6 打印

首先调用size()函数的时候出现了权限放大的问题,调用运算符【】也是如此所以在这里我们就要引入const成员函数进行修改~对需要改变自身的额外再写一个针对const权限函数,对不需要改变自身的加入const。

void print_str(const string& s){for (size_t i = 0; i < s.size(); i++){//s[i]++;cout << s[i] << endl;}string::const_iterator it = s.begin();while (it != s.end()){// *it = 'x';cout << *it << " ";++it;}cout << endl;}

2.7 reserve扩容

		void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];//还有一个开给\0strcpy(tmp, _str);//拷贝所指向的内容delete[] _str;//销毁旧空间_str = tmp;//指向新空间_capacity = n;}}

2.8 push_back尾插

void push_back(char ch){if (_size == _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;_size++;_str[_size] = '\0';}

由于\0不算有效字符,所以最后计算完后_size都会与其下标相等,而这时候可以刚好插入字符。最后需要注意人工补上\0。

2.9 append追加

		void append(const char* str){size_t len = strlen(str);//计算所追加的长度if (_size + len > _capacity){reserve(_size + len);}strcpy(_str+_size, str);_size += len;}

//strcpy(_str+_size, str);为什么不是_size就行了呢?因为_size是一个数据不是一个指针,而_str是指针+数可以达到偏移的效果

2.10 insert插入

		void insert(size_t pos, char ch){assert(pos <=_size);if (_size == _capacity){size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newCapacity);}size_t end = _size;while (pos < end){_str[end] = _str[end - 1];end--;}_str[pos] = ch;_size++;_str[_size] = '\0';}

需要注意的细节有点多:如果是这种写法

while (end >= (int)pos){_str[end + 1] = _str[end];--end;}

最后end会减为负数,而其类型又是无符号整型,会一直陷入死循环。就算把end改为整型,在循环条件里又会和pos触发类型提升(小的向大的转,有符号向无符号转),最后还得强制转化pos类型才可以解决问题。所以直接换个写法一劳永逸~

		void insert(size_t pos, const char* str){assert(pos <= _size);size_t len = strlen(str);if (_size+len > _capacity){reserve(_size+len);}size_t end = _size;while (pos < end){_str[end+len-1] = _str[end - 1];end--;}strncpy(_str + pos, str,len);_size+=len;_str[_size] = '\0';}

 

2.11 erase删除

void erase(size_t pos, size_t len = npos){assert(pos <= _size);if (len == npos || pos + len > _size){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);//很精妙_size -= len;}}

2.12 swap交换

void swap(string& s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}

如果没有中间的swap(string),那么swap(s1,s2)就会走与swap(a,b)一样的结果,产生中间变量。如果有中间的swap(string),那当我们swap(s1,s2)时进入其中就会让我们去调用string类里面的swap,只需要交换指针即可,不产生中间变量。

2.13 find寻找

size_t find(char ch, size_t pos = 0){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 char* ptr = strstr(_str + pos, str);if (ptr == nullptr){return npos;}else{return ptr - _str;//利用指针-指针}}

2.14 运算符+=

        string& operator+=(char ch){push_back(ch);return *this;}string& operator+=(const char* str){append(str);return *this;}

简单复用即可

2.15 substr
 

		string substr(size_t pos = 0, size_t len = npos){assert(pos < _size);size_t end = pos+len;if (len == npos || pos + len >= _size){end = _size;}string sub1;sub1.reserve(end - pos);//重新创个空间for (size_t i = pos; i < end; i++)//拷贝内容{sub1 += _str[i];}return sub1;}

最终会报错~

问题一:因为是临时对象,这意味着出作用会就会调用析构函数(清理资源),而临时对象又指向临时资源,被清理后那就变成野指针了。

解决方法:写出拷贝构造(深拷贝)

string(const string& s){//深拷贝_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;}

问题二:在赋值拷贝中(s2=s1)会出现以下情况,要么s2的空间过大,与s1大小差距过大造成资源浪费。要么s2的空间太小,不足够容纳s1,只有二者刚刚好才合适。

// s2 = s1
string& operator=(const string& s){if (this != &s)//不自己调用自己{char* tmp = new char[s._capacity + 1];strcpy(tmp, s._str);delete[] _str;_str = tmp;_size = s._size;_capacity = s._capacity;}return *this;}

既然这样就重新构造一个与s1相仿的空间,再拷贝原内容进去,删掉s2所指的原来空间,令s2指向新空间,再浅拷贝,使得赋值拷贝合理化。

成功实现效果~ 

2.16 流插入<<

	ostream& operator<<(ostream& out, const string& s){for (auto ch : s){out << ch;}return out;}

2.17 流提取>>

	void clear(){_size = 0;_str[0] = '\0';}istream& operator>>(istream& in,  string& s){s.clear();char ch = in.get();while (ch != ' ' && ch != '\n'){s += ch;ch = in.get();}return in;}

细节一:clear函数

如果没有_str[0] = '\0';由于cout<<s1是以_size为准的,在遍历的时候就停止流插入了。而cout<<s1.c_str()中由于其返回的是整段的字符串不看_size,是直接解引用的。那么在没有'\0'的情况下还是会输出,没有达成清理的效果。

另外如果没有clear函数清理原内容,那么cin最后做到的只是拼接。

细节二.get函数

如果ch以这样的方式提取那么最终会无法识别到‘ ’与‘\n’而死循环。因为in拿不到‘ ’与‘\n’,他们通常是作为分割符合使用的,所以会无视。只有get函数才能够识别并提取它们。

三.现代写法

备注:功能和传统写法一组,只是让代码行数更少

拷贝构造

		//传统写法			string s2(s1) string(const string& s){//深拷贝_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;}//现代写法			string s2(s1) string(const string& s){string tmp(s._str);//调用构造,构造出与s1一样的空间与内容swap(tmp);//s2与tmp交换指针}

细节:s2必须得指向空(全缺省),如果指向其他地方那么tmp可能会出现随机值,报错。

赋值拷贝

        //传统写法  s1 = s3string& operator=(const string& s){if (this != &s)//不自己调用自己{char* tmp = new char[s._capacity + 1];strcpy(tmp, s._str);delete[] _str;_str = tmp;_size = s._size;_capacity = s._capacity;}return *this;}//现代写法  s1 = s3string& operator=(string s){swap(s);return *this;}

四.小拓展

to_string可以识别各种类型然后转化为string。

stoi可以识别string类型然后转化为需要的类型。

五.全部代码

//string.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include "string.h"namespace lj
{//构造string::string(const char* str)//不能给'\0'类型不匹配,而字符串会默认带\0{_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];//加1是因为在_capacity那被认为‘\0’是有效字符strcpy(_str, str);}//现代写法			string s2(s1) string::string(const string& s){string tmp(s._str);//调用构造swap(tmp);}//现代写法  s1 = s3string& string::operator=(string s){swap(s);return *this;}string::~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}char& string::operator[](size_t pos){return _str[pos];}const char& string:: operator[](size_t pos)const{return _str[pos];}void string::reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];//还有一个开给\0strcpy(tmp, _str);//拷贝所指向的内容delete[] _str;//销毁旧空间_str = tmp;//指向新空间_capacity = n;}}void string::push_back(char ch){if (_size == _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;_size++;_str[_size] = '\0';}void string::append(const char* str){size_t len = strlen(str);//计算所追加的长度if (_size + len > _capacity){reserve(_size + len);}strcpy(_str + _size, str);_size += len;}void string::insert(size_t pos, char ch){assert(pos <= _size);if (_size == _capacity){size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newCapacity);}size_t end = _size;while (pos < end){_str[end] = _str[end - 1];end--;}_str[pos] = ch;_size++;_str[_size] = '\0';}void string::insert(size_t pos, const char* str){assert(pos <= _size);size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}size_t end = _size;while (pos < end){_str[end + len - 1] = _str[end - 1];end--;}strncpy(_str + pos, str, len);_size += len;_str[_size] = '\0';}void string::erase(size_t pos, size_t len){assert(pos <= _size);if (len == npos || pos + len > _size){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);//很精妙_size -= len;}}void string::swap(string& s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}size_t string::find(char ch, size_t pos){for (size_t i = pos; i <= _size; i++){if (_str[i] == ch){return i;}}return npos;}size_t string::find(const char* str, size_t pos){const char* ptr = strstr(_str + pos, str);if (ptr == nullptr){return npos;}else{return ptr - _str;//利用指针-指针}}string& string::operator+=(char ch){push_back(ch);return *this;}string& string::operator+=(const char* str){append(str);return *this;}string string::substr(size_t pos, size_t len){assert(pos < _size);size_t end = pos + len;if (len == npos || pos + len >= _size){end = _size;}string sub1;sub1.reserve(end - pos);//重新创个空间for (size_t i = pos; i < end; i++)//拷贝内容{sub1 += _str[i];}return sub1;}void string::clear(){_size = 0;_str[0] = '\0';}ostream& operator<<(ostream& out, const string& s){for (auto ch : s){out << ch;}return out;}istream& operator>>(istream& in, string& s){s.clear();char ch = in.get();while (ch != ' ' && ch != '\n'){s += ch;ch = in.get();}return in;}};

//string.h
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
namespace lj
{class string{public://无参构造/*	string():_str(new char[1]){_str[0] = '\0';_size = 0;_capacity = 0;}*///返回c格式字符串const char* c_str()const{return _str;}//构造string(const char* str = "");//不能给'\0'类型不匹配,而字符串会默认带\0//现代写法			string s2(s1) string(const string& s);//现代写法  s1 = s3string& operator=(string s);~string();size_t size()const{return _size;}typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}const_iterator begin()const{return _str;}iterator end(){return _str + _size;}const_iterator end()const{return _str + _size;}char& operator[](size_t pos);const char& operator[](size_t pos)const;void reserve(size_t n);void push_back(char ch);void append(const char* str);void insert(size_t pos, char ch);void insert(size_t pos, const char* str);void erase(size_t pos, size_t len = npos);void swap(string& s);size_t find(char ch, size_t pos = 0);size_t find(const char* str, size_t pos = 0);string& operator+=(char ch);string& operator+=(const char* str);string substr(size_t pos = 0, size_t len = npos);void clear();private:size_t _size = 0;size_t _capacity = 0;char* _str = nullptr;const static size_t npos = -1;};ostream& operator<<(ostream& out, const string& s);istream& operator>>(istream& in, string& s);}

//test.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <string>
using namespace std;//int main()
//{
//	//string s1("hello world");
//	//s1.erase(0, 4);
//	//cout << s1 << endl;//o world 从下标为0开始,删除4个字符
//	//s1.erase();
//	//cout << s1 << endl;//
//
//	//string s1("hello world");
//	//string s2;
//	//s1.replace(0, 1, "aaaa");
//	//cout << s1 << endl;//aaaaello world
//	string s1("hello world a b");
//	// 所有的空格替换为100%
//	size_t pos = s1.find(' ', 0);
//	while (pos != string::npos)
//	{
//		s1.replace(pos, 1, "100%");
//		// 效率很低,能不用就不要用了
//
//		pos = s1.find(' ', pos + 4);
//	}
//	cout << s1 << endl;//hello100%world100%a100%b
//
//	return 0;
//}//int main()
//{
//	string s1("hello world a b");
//	string s2;
//	for (auto ch : s1)
//	{
//		if (ch == ' ')
//		{
//			s2 += "100%";
//		}
//		else
//		{
//			s2 += ch;
//		}
//	}
//	s1.swap(s2);
//	cout << s1 << endl;//hello100%world100%a100%b
//
//	return 0;
//}//int main()
//{
//	string s1("hello");
//	string s2;
//	s2 = s1.substr(1, 2);
//	cout << s2 << endl;//el
//	cout << s1.substr(1) << endl;//ello
//
//	return 0;
//}//int main()
//{
//	//获取后缀名
//	string s1("Test.cpp");
//	string s2("Test.tar.zar");
//
//	size_t pos1 = s1.find('.');
//	size_t pos2 = s2.rfind('.');
//
//	if(pos1 != string::npos)
//	{
//		string s3 = s1.substr(pos1);
//		cout << s3 << endl;//.cpp
//
//		string s4 = s2.substr(pos2);
//		cout << s4 << endl;//.zar
//
//	}
//
//	return 0;
//}//int main()
//{
//	string s1("hello world");
//
//	size_t pos1 = s1.find_first_not_of("abcde");
//	cout << pos1 << endl;//0
//
//	pos1 = s1.find_last_not_of("h");
//	cout << pos1 << endl;//10
//
//
//	return 0;
//}#include"string.h"void print_str(const string& s)
{for (size_t i = 0; i < s.size(); i++){//s[i]++;cout << s[i] << endl;}string::const_iterator it = s.begin();while (it != s.end()){// *it = 'x';cout << *it << " ";++it;}cout << endl;}
void test_string1()
{//string s1("aabbcc");//构造成功//cout << s1.c_str() << endl;//for (size_t i = 0; i < s1.size(); i++)//{//	s1[i]++;//}//cout << s1.c_str() << endl;//string s2;cout << s2.c_str << endl;//string s1("aabbcc");//string::iterator it = s1.begin();//while (it != s1.end())//{//	cout << *it << " ";//	++it;//}//cout << endl;//a a b b c c//string s1("aabbcc");//for (auto ch : s1)//{//	cout << ch << " ";//}//cout << endl;//a a b b c c//string s3("hello");//print_str(s3);//bb cc dd//string s1("aabbcc ddeeff");//s1.push_back('a');//cout << s1.c_str() << endl;//string s2;//s2.push_back('a');//cout << s2.c_str() << endl;/*string s1("aabbcc ddeeff");s1.append("aaa");cout << s1.c_str() << endl;*///string s1("aabbcc ddeeff");//s1.insert(0, 'w');//cout << s1.c_str() << endl;//string s1("aabbcc ddeeff");//s1.insert(0, "ddd");//cout << s1.c_str() << endl;//string s2("aabbcc ddeeff");//s2.insert(12, "ddd");//cout << s2.c_str() << endl;//string s1("aabbcc ddeeff");//s1.erase(1, 2);//cout << s1.c_str() << endl;//string s1("aabbcc ddeeff");//string s2("abc");//s2.swap(s1);//cout << s1.c_str() << endl;//cout << s2.c_str() << endl;/*string s1("aabbcc ddeeff");cout << s1.find('\0') << endl;cout << s1.find('a',1) << endl;*///string s1("aabbcc ddeeff");//cout << s1.find("cc",0) << endl;//cout << s1.find('a', 1) << endl;//string s1("aabbcc ddeeff");//s1 += 'a';//cout << s1.c_str() << endl;//string s2("aabbcc ddeeff");//s2 += "bbb";//cout << s2.c_str() << endl;//string s1("aabbcc ddeeff");//string s2;//s2 = s1.substr(3, 4);//cout << s2.c_str() << endl;//string str;//string& s = str;//string s1("abcd");cout << s1 << endl;//string s2("acacac");//cout << s2 << endl;//string s1("abcabc");//cin >> s1;//cout << s1 << endl;/*string s1("hello world");cout << s1.c_str() << endl;cout << s1 << endl;s1.clear();cout << s1.c_str() << endl;cout << s1 << endl;*///string s1("abc");//cout << s1 << endl;//string s2(s1);//cout << s2 << endl;//string s1("aaaaaa");//string s3("xxxxxx");//s1 = s3;//cout << s1 << endl;//cout << s3 << endl;std::string str = std::to_string(123);cout << str << endl;std::string str1 = std::to_string(123.222);cout << str1 << endl;std::string str2 = std::to_string(123);int i = stoi(str2);cout << i << endl;}
int main()
{test_string1();return 0;
}

相关文章:

秒懂C++之string类(下)

目录 一.接口说明 1.1 erase 1.2 replace&#xff08;最好别用&#xff09; 1.3 find 1.4 substr 1.5 rfind 1.6 find_first_of 1.7 find_last_of 二.string类的模拟实现 2.1 构造 2.2 无参构造 2.3 析构 2.4.【】运算符 2.5 迭代器 2.6 打印 2.7 reserve扩容 …...

github简单地操作

1.调节字体大小 选择options 选择text 选择select 选择你需要的参数就可以了。 2.配置用户名和邮箱 桌面右键&#xff0c;选择git Bash Here git config --global user.name 用户名 git config --global user.email 邮箱名 3.用git实现代码管理的过程 下载别人的项目 git …...

模型改进-损失函数合集

模版 第一步在哪些地方做出修改&#xff1a; 228行 self.use_wiseiouTrue 230行 self.wiou_loss WiseIouLoss(ltypeMPDIoU, monotonousFalse, inner_iouTrue, focaler_iouFalse) 238行 wiou self.wiou_loss(pred_bboxes[fg_mask], target_bboxes[fg_mask], ret_iouFalse…...

C++模板(初阶)

1.引入 在之前的笔记中有提到&#xff1a;函数重载&#xff08;特别是交换函数&#xff08;Swap&#xff09;的实现&#xff09; void Swap(int& left, int& right) {int temp left;left right;right temp; } void Swap(double& left, double& right) {do…...

下面关于Date类的描述错误的一项是?

下面关于Date类的描述错误的一项是&#xff1f; A. java.util.Date类下有三个子类&#xff1a;java.sql.Date、java.sql.Timestamp、java.sql.Time&#xff1b; B. 利用SimpleDateFormat类可以对java.util.Date类进行格式化显示&#xff1b; C. 直接输出Date类对象就可以取得日…...

【Python面试题收录】Python编程基础练习题①(数据类型+函数+文件操作)

本文所有代码打包在Gitee仓库中https://gitee.com/wx114/Python-Interview-Questions 一、数据类型 第一题&#xff08;str&#xff09; 请编写一个Python程序&#xff0c;完成以下任务&#xff1a; 去除字符串开头和结尾的空格。使用逗号&#xff08;","&#…...

C# Nmodbus,EasyModbusTCP读写操作

Nmodbus读写 两个Button控件分别为 读取和写入 分别使用控件的点击方法 ①引用第三方《NModbus4》2.1.0版本 全局 public SerialPort port new SerialPort("COM2", 9600, Parity.None, 8, (StopBits)1); ModbusSerialMaster master; public Form1() port.Open();…...

spark常用参数调优

目录 1.set spark.grouping.sets.reference.hivetrue;2.set spark.locality.wait.rack0s3.set spark.locality.wait0s;4.set spark.executor.memoryOverhead 2G;5.set spark.sql.shuffle.partitions 1000;6.set spark.shuffle.file.buffer 256k7. set spark.reducer.maxSizeInF…...

C#/WinFrom TCP通信+ 网线插拔检测+客服端异常掉线检测

Winfor Tcp通信(服务端) 今天给大家讲一下C# 关于Tcp 通信部分&#xff0c;这一块的教程网上一大堆&#xff0c;不过关于掉网&#xff0c;异常断开连接的这部分到是到是没有多少说明&#xff0c;有方法 不过基本上最多的两种方式&#xff08;1.设置一个超时时间&#xff0c;2.…...

一篇文章掌握Python爬虫的80%

转载&#xff1a;一篇文章掌握Python爬虫的80% Python爬虫 Python 爬虫技术在数据采集和信息获取中有着广泛的应用。本文将带你掌握Python爬虫的核心知识&#xff0c;帮助你迅速成为一名爬虫高手。以下内容将涵盖爬虫的基本概念、常用库、核心技术和实战案例。 一、Python 爬虫…...

【用户会话信息在异步事件/线程池的传递】

用户会话信息在异步事件/线程池的传递 author:shengfq date:2024-07-29 version:1.0 背景: 同事写的一个代码功能,是在一个主线程中通过如下代码进行异步任务的执行,结果遇到了问题. 1.ThreadPool.execute(Runnable)启动一个子线程执行异步任务 2.applicationContext.publis…...

Java8: BigDecimal

Java8:BigDecimal 转两位小数的百分数-CSDN博客 BigDecimal 先做除法 然后取绝对值 在Java 8中&#xff0c;如果你想要对一个BigDecimal值进行除法操作&#xff0c;并随后取其绝对值&#xff0c;你可以通过组合divide方法和abs方法来实现这一目的。不过&#xff0c;需要注意的…...

苹果推送iOS 18.1带来Apple Intelligence预览

&#x1f989; AI新闻 &#x1f680; 苹果推送iOS 18.1带来Apple Intelligence预览 摘要&#xff1a;苹果向iPhone和iPad用户推送iOS 18.1和iPadOS 18.1开发者预览版Beta更新&#xff0c;带来“Apple Intelligence”预览。目前仅支持M1芯片或更高版本的设备。Apple Intellige…...

testRigor-基于人工智能驱动的无代码自动化测试平台

1、testRigor介绍 简单来说&#xff0c;testRigor是一款基于人工智能驱动的无代码自动化测试平台&#xff0c;它能够通过分析应用的行为模式&#xff0c;智能地生成测试用例&#xff0c;并自动执行这些测试&#xff0c;无需人工编写测试脚本。可以用于Web、移动、API和本机桌面…...

hadoop学习(一)

一.hadoop概述 1.1hadoop优势 1&#xff09;高可靠性&#xff1a;Hadoop底层维护多个数据副本&#xff0c;即使Hadoop某个计算元素或存储出现故障&#xff0c;也不会导致数据的丢失。 2&#xff09;高扩展性&#xff1a;在集群间分配任务数据&#xff0c;可方便扩展数以千计…...

Linux性能监控:sar的可视化方案

在当今的IT环境中&#xff0c;系统性能监控是确保应用程序稳定运行和快速响应问题的关键。Linux作为一种广泛使用的操作系统&#xff0c;拥有多种性能监控工具&#xff0c;其中sar&#xff08;System Activity Reporter&#xff09;因其全面性和灵活性被广泛采用。然而&#xf…...

如何录制电脑屏幕视频,5招让您成为电脑录制高手

在今天&#xff0c;屏幕录制成为每个电脑使用者都应掌握的基础技能。不论是教学分享、会议记录还是游戏直播&#xff0c;屏幕录制都能帮你捕捉那些重要的瞬间&#xff0c;将无形的信息转化为有形的视频。那么&#xff0c;如何录制电脑屏幕视频呢&#xff1f;今天&#xff0c;我…...

AI届的新宠:小语言模型(SLM)?

大语言模型&#xff08;LLM&#xff09;在过去几年产生了巨大影响&#xff0c;特别是随着OpenAI的ChatGPT的出现&#xff0c;各种大语言模型如雨后春笋般出现&#xff0c;国内如KimiChat、通义千问、文心一言和智谱清言等。 然而&#xff0c;大语言模型通常拥有庞大的参数&…...

PMP模拟题错题本

模拟题A 错题整理 项目经理为一个具有按时完成盈利项目历史记录的组织工作。然而&#xff0c;由于缺乏相关方的支持以及他们未能提供信息&#xff0c;这些项目都经历过问题。若要避免这些问题&#xff0c;项目经理在新项目开始时应该做什么&#xff1f; A. 在启动阶段识别关键…...

Laravel Dusk:点亮自动化测试的明灯

Laravel Dusk&#xff1a;点亮自动化测试的明灯 在Web开发中&#xff0c;确保应用程序的用户体验和功能正确性至关重要。Laravel Dusk是一个强大的浏览器自动化测试工具&#xff0c;它允许开发者模拟用户与应用程序的交互&#xff0c;从而进行端到端的测试。本文将深入探讨Lar…...

Git、Gitlab以及分支管理

分布式版本控制系统 一、Git概述 Git是一种分布式版本控制系统&#xff0c;用于跟踪和管理代码的变更。它由Linus torvalds创建的&#xff0c;最初被设计用于Linux内核的开发。Git 允许开发人员跟踪和管理代码的版本&#xff0c;并且可以在不同的开发人员之间进行协作。 Githu…...

TCP/IP 协议栈介绍

TCP/IP 协议栈介绍 1. 引言 TCP/IP&#xff08;传输控制协议/互联网协议&#xff09;是一组用于数据网络中通信的协议集合&#xff0c;它是互联网的基础。本文将详细介绍TCP/IP协议栈的各个层次、工作原理以及其在网络通信中的作用。 2. TCP/IP 协议栈的层次结构 TCP/IP协议…...

香橙派orangepi系统没有apt,也没有apt-get,也没有yum命令,找不到apt、apt-get、yum的Linux系统

以下是一个关于如何在 Orange Pi 上的 Arch Linux 系统中发现缺失包管理器的问题并解决的详细教程。 发现问题 确认系统类型&#xff1a; 使用以下命令检查当前的 Linux 发行版&#xff1a; uname -a cat /etc/os-release如果你看到类似于 “Arch Linux” 的信息&#xff0c;说…...

在invidia jetpack4.5.1上运行c++版yolov8(tensorRT)

心路历程&#xff08;可略过&#xff09; 为了能在arm64上跑通yolov8&#xff0c;我试过很多很多代码&#xff0c;太多对库版本的要求太高了&#xff1b; 比如说有一个是需要依赖onnx库的&#xff0c;&#xff08;https://github.com/UNeedCryDear/yolov8-opencv-onnxruntime-…...

Vue3 接入 i18n 实现国际化多语言

在 Vue.js 3 中实现网页的国际化多语言&#xff0c;最常用的包是 vue-i18n。 第一步&#xff0c;安装一个 Vite 下使用 <i18n> 标签的插件&#xff1a;unplugin-vue-i18n npm install unplugin-vue-i18n # 或 yarn add unplugin-vue-i18n 安装完成后&#xff0c;调整 v…...

深度学习环境坑。

前面装好了之后装pytorch之后老显示gpufalse。 https://www.jb51.net/article/247762.htm 原因就是清华源的坑。 安装的时候不要用conda&#xff0c; 用pip命令 我cuda12.6&#xff0c;4070s cudnn-windows-x86_64-8.9.7.29_cuda12-archive.zip cuda_12.5.1_555.85_windows.…...

LLM——10个大型语言模型(LLM)常见面试题以及答案解析

今天我们来总结以下大型语言模型面试中常问的问题 1、哪种技术有助于减轻基于提示的学习中的偏见? A.微调 Fine-tuning B.数据增强 Data augmentation C.提示校准 Prompt calibration D.梯度裁剪 Gradient clipping 答案:C 提示校准包括调整提示&#xff0c;尽量减少产生…...

MongoDB - 聚合阶段 $count、$skip、$project

文章目录 1. $count 聚合阶段2. $skip 聚合阶段3. $project 聚合阶段1. 包含指定字段2. 排除_id字段3. 排除指定字段4. 不能同时指定包含字段和排除字段5. 排除嵌入式文档中的指定字段6. 包含嵌入式文档中的指定字段7. 添加新字段8. 重命名字段 1. $count 聚合阶段 计算匹配到…...

如何获取文件缩略图(C#和C++实现)

在C中&#xff0c;可以有以下两种办法 使用COM接口IThumbnailCache 文档链接&#xff1a;IThumbnailCache (thumbcache.h) - Win32 apps | Microsoft Learn 示例代码如下&#xff1a; VOID GetFileThumbnail(PCWSTR path) {HRESULT hr CoInitialize(nullptr);IShellItem* i…...

create-vue项目的README中文版

使用方法 要使用 create-vue 创建一个新的 Vue 项目&#xff0c;只需在终端中运行以下命令&#xff1a; npm create vuelatest[!注意] (latest 或 legacy) 不能省略&#xff0c;否则 npm 可能会解析到缓存中过时版本的包。 或者&#xff0c;如果你需要支持 IE11&#xff0c;你…...

Centos 7系统(最小化安装)安装Git 、git-man帮助、补全git命令-详细文章

安装之前由于是最小化安装centos7安装一些开发环境和工具包 文章使用国内阿里源 cd /etc/yum.repos.d/ && mkdir myrepo && mv * myrepo&&lscurl -O https://mirrors.aliyun.com/repo/epel-7.repo;curl -O https://mirrors.aliyun.com/repo/Centos-7…...

Golang零基础入门课_20240726 课程笔记

视频课程 最近发现越来越多的公司在用Golang了&#xff0c;所以精心整理了一套视频教程给大家&#xff0c;这个只是其中的第一部&#xff0c;后续还会有很多。 视频已经录制完成&#xff0c;完整目录截图如下&#xff1a; 课程目录 01 第一个Go程序.mp402 定义变量.mp403 …...

杂记-镜像

-i https://pypi.tuna.tsinghua.edu.cn/simple 清华 pip intall 出现 error: subprocess-exited-with-error 错误的解决办法———————————pip install --upgrade pip setuptools57.5.0 ————————————————————————————————————…...

如何将WordPress文章中的外链图片批量导入到本地

在使用采集软件进行内容创作时&#xff0c;很多文章中的图片都是远程链接&#xff0c;这不仅会导致前端加载速度慢&#xff0c;还会在微信小程序和抖音小程序中添加各种域名&#xff0c;造成管理上的麻烦。特别是遇到没有备案的外链&#xff0c;更是让人头疼。因此&#xff0c;…...

primetime如何合并不同modes的libs到一个lib文件

首先&#xff0c;用primetime 抽 timing model 的指令如下。 代码如下&#xff08;示例&#xff09;&#xff1a; #抽lib时留一些margin, setup -max/hold -min set_extract_model_margin -port [get_ports -filter "!defined(clocks)"] -max 0.1 #抽lib extract_mod…...

【运维笔记】数据库无法启动,数据库炸后备份恢复数据

事情起因 在做docker作业的时候&#xff0c;把卷映射到了宿主机原来的mysql数据库目录上&#xff0c;宿主机原来的mysql版本为8.0&#xff0c;docker容器版本为5.6&#xff0c;导致翻车。 具体操作 备份目录 将/var/lib/mysql备份到~/mysql_backup&#xff1a;cp /var/lib/…...

成功解决:java.security.InvalidKeyException: Illegal key size

在集成微信支付到Spring Boot项目时&#xff0c;可能会遇到启动报错 java.security.InvalidKeyException: Illegal key size 的问题。这是由于Java加密扩展&#xff08;JCE&#xff09;限制了密钥的长度。幸运的是&#xff0c;我们可以通过简单的替换文件来解决这个问题。 解决…...

微服务事务管理(分布式事务问题 理论基础 初识Seata XA模式 AT模式 )

目录 一、分布式事务问题 1. 本地事务 2. 分布式事务 3. 演示分布式事务问题 二、理论基础 1. CAP定理 1.1 ⼀致性 1.2 可⽤性 1.3 分区容错 1.4 ⽭盾 2. BASE理论 3. 解决分布式事务的思路 三、初识Seata 1. Seata的架构 2. 部署TC服务 3. 微服务集成Se…...

测试面试宝典(三十五)—— fiddler的工作原理

Fiddler 是一款强大的 Web 调试工具&#xff0c;其工作原理主要基于代理服务器的机制。 首先&#xff0c;当您在计算机上配置 Fiddler 为系统代理时&#xff0c;客户端&#xff08;如浏览器&#xff09;发出的所有 HTTP 和 HTTPS 请求都会被导向 Fiddler。 Fiddler 接收到这些…...

旷野之间32 - OpenAI 拉开了人工智能竞赛的序幕,而Meta 将会赢得胜利

他们通过故事做到了这一点&#xff08;Snapchat 是第一个&#xff09;他们用 Reels 实现了这个功能&#xff08;TikTok 是第一个实现这个功能的&#xff09;他们正在利用人工智能来实现这一点。 在人工智能竞赛开始时&#xff0c;Meta 的人工智能平台的表现并没有什么特别值得…...

机械学习—零基础学习日志(高数15——函数极限性质)

零基础为了学人工智能&#xff0c;真的开始复习高数 这里我们将会学习函数极限的性质。 唯一性 来一个练习题&#xff1a; 再来一个练习&#xff1a; 这里我问了一下ChatGPT&#xff0c;如果一个值两侧分别趋近于正无穷&#xff0c;以及负无穷。理论上这个极限值应该说是不存…...

树 形 DP (dnf序)

二叉搜索子树的最大键值 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(null…...

React的生命周期?

React的生命周期分为三个主要阶段&#xff1a;挂载&#xff08;Mounting&#xff09;、更新&#xff08;Updating&#xff09;和卸载&#xff08;Unmounting&#xff09;。 1、挂载&#xff08;Mounting&#xff09; 当组件实例被创建并插入 DOM 时调用的生命周期方法&#x…...

c# - - - ASP.NET Core 网页样式丢失,样式不对

c# - - - ASP.NET Core 网页样式丢失&#xff0c;样式不对 问题 正常样式是这样的。 修改项目名后&#xff0c;样式就变成这样了。底部的内容跑到中间了。 解决 重新生成解决方案&#xff0c;然后发布网站。 原因&#xff1a; 修改项目名之前的 div 上有个这个自定义属…...

Cannot find module ‘html-webpack-plugin

当你在使用Webpack构建项目时遇到Cannot find module html-webpack-plugin这样的错误&#xff0c;这意味着Webpack在构建过程中找不到html-webpack-plugin模块。要解决这个问题&#xff0c;你需要确保已经正确安装了html-webpack-plugin模块&#xff0c;并且在Webpack配置文件中…...

vue、react部署项目的 hashRouter 和 historyRouter模式

Vue 项目 使用 hashRouter 如果你使用的是 hashRouter&#xff0c;通常不需要修改 base&#xff0c;因为 hashRouter 使用 URL 的哈希部分来管理路由&#xff0c;这部分不会被服务器处理。你只需要确保 publicPath 设置正确即可。 使用 historyRouter 如果你使用的是 histo…...

Qt 实现抽屉效果

1、实现效果和UI设计界面 2、工程目录 3、mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QToolButton> #include <QPushButton> #include <vector> using namespace std;QT_BEGIN_NAMESPACE namespace…...

windows上启动Kafka

官网下载 如&#xff1a;kafka_2.13-2.4.0.tgz 新版集成了Zookeeper ,无需另行下载 解压 至D:\Kafka\kafka_2.13-2.4.0 下 配置Kafka&#xff08;可跳过&#xff09; Zookeeper配置 kafka\config\zookeeper.properties下修改dataDir路径(Zookeeper数据目录)dataDirD:\\Program…...

贪心系列专题篇三

目录 单调递增的数字 坏了的计算器 合并区间 无重叠区间 用最少数量的箭 声明&#xff1a;接下来主要使用贪心法来解决问题&#xff01;&#xff01;&#xff01; 单调递增的数字 题目 思路 如果我们遍历整个数组&#xff0c;然后对每个数k从[k,0]依次遍历寻找“单调递…...

Java中两个集合取差集

Java中两个集合取差集 说明: 集合A ListA: search archive relation test 集合B ListB: search search-gejunhao archive-gejunhao archive system 需求: 现在要取存在于A但是不存在B中的元素 test 该如何实现 思路: 在Java中&#xff0c;如果你想要从一个集合&#xff…...