string类详解(上)

news2025/3/13 21:20:24

文章目录

  • 目录
    • 1. STL简介
      • 1.1 什么是STL
      • 1.2 STL的版本
      • 1.3 STL的六大组件
    • 2. 为什么学习string类
    • 3. 标准库中的string类
      • 3.1 string类
      • 3.2 string类的常用接口说明

目录

  • STL简介
  • 为什么学习string类
  • 标准库中的string类
  • string类的模拟实现
  • 现代版写法的String类
  • 写时拷贝

1. STL简介

1.1 什么是STL

STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架

1.2 STL的版本

  • 原始版本

Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。HP 版本–所有STL实现版本的始祖。

  • P. J. 版本

由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低,符号命名比较怪异。

  • RW版本

由Rouge Wage公司开发,继承自HP版本,被C+ + Builder 采用,不能公开或修改,可读性一般。

  • SGI版本

由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版本。被GCC(Linux)采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程风格上看,阅读性非常高。我们后面学习STL要阅读部分源代码,主要参考的就是这个版本

1.3 STL的六大组件

STL的六大组件

2. 为什么学习string类

C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。

3. 标准库中的string类

3.1 string类

string类的具体信息可以通过cplusplus网站进行查阅

在使用string类时,必须包含#include头文件以及using namespace std;

3.2 string类的常用接口说明

我们先来总的看一下string类的常用接口:

  1. string类对象的常见构造
    string类对象的常见构造
  2. string类对象的容量操作
    string类对象的容量操作
  3. string类对象的访问及遍历操作
    string类对象的访问及遍历操作
  4. string类对象的修改操作
    string类对象的修改操作
  5. string类非成员函数
    string类非成员函数

接下来,我们通过一些具体的场景来学习如何使用这些接口:

  • 如何构造一个string类对象
    string类对象的构造
#include <iostream>
#include <string>

using namespace std;

void test_string1()
{
	//常用
	string s1;
	string s2("hello world");
	string s3(s2);
	
	//不常用 了解
	string s4(s2, 3, 5);
	string s5(s2, 3);
	string s6(s2, 3, 30);
	string s7("hello world", 5);
	string s8(10, 'x');

	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	cout << s5 << endl;
	cout << s6 << endl;
	cout << s7 << endl;
	cout << s8 << endl;

	cin >> s1;
	cout << s1 << endl;
}

int main()
{
	test_string1();

	return 0;
}

补充:

void push_back(const string& s)
{

}

void test_string2()
{
	//构造
	string s1("hello world");

	//隐式类型转换
	string s2 = "hello world";
	
	const string& s3 = "hello world";
	
	push_back(s1);
	push_back("hello world");
}

int main()
{
	test_string2();

	return 0;
}

  • string的遍历

第一种方法:

//class string
//{
//public:
//	//引用返回
//	//1. 减少拷贝
//	//2. 修改返回对象
//	char& operator[](size_t i)
//	{
//		assert(i < _size);
//
//		return _str[i];
//	}
//private:
//	char* _str;
//	size_t _size;
//	size_t _capacity;
//};

void test_string3()
{
	string s1("hello world");
	cout << s1.size() << endl;//11
	//cout << s1.length() << endl;//11

	for (size_t i = 0; i < s1.size(); i++)
	{
		s1[i]++;
	}

	s1[0] = 'x';

	//越界检查
	//s1[20];

	for (size_t i = 0; i < s1.size(); i++)
	{
		//cout << s1.operator[](i) << " ";
		cout << s1[i] << " ";
	}

	cout << endl;

	const string s2("hello world");
	//不能修改
	//s2[0] = 'x';
}

int main()
{
	test_string3();

	return 0;
}

size和operator[]
注: size() 与 length() 方法底层实现原理完全相同,引入 size() 的原因是为了与其他容器的接口保持一致,一般情况下基本都是用 size()

第二种方法:
iterator

void test_string4()
{
	string s1("hello world");

	//遍历方式2:迭代器
	string::iterator it1 = s1.begin();

	while (it1 != s1.end())
	{
		*it1 += 3;

		cout << *it1 << " ";
		++it1;
	}

	cout << endl;

	//cout << typeid(it1).name() << endl;
}

int main()
{
	test_string4();

	return 0;
}

iterator的优势

void test_string4()
{
	list<int> lt1;
	lt1.push_back(1);
	lt1.push_back(2);
	lt1.push_back(3);

	list<int>::iterator it = lt1.begin();

	while (it != lt1.end())
	{
		cout << *it << " ";
		++it;
	}

	cout << endl;
}

int main()
{
	test_string4();

	return 0;
}

第三种方法:

void test_string4()
{
	string s1("hello world");
	
	//遍历方式3:范围for(通用的)
	//底层角度,它就是迭代器
	for (auto& e : s1)
	{
		e++;//不会影响s1中的数据,它是一个赋值拷贝;要加上引用才会改变s1中的数据
		cout << e << " ";
	}

	cout << endl;
	cout << s1 << endl;


	list<int> lt1;
	lt1.push_back(1);
	lt1.push_back(2);
	lt1.push_back(3);

	for (auto& e : lt1)
	{
		cout << e << " ";
	}

	cout << endl;
}

int main()
{
	test_string4();

	return 0;
}

注: 除了普通迭代器之外,还有

  1. const迭代器
    const迭代器
void test_string5()
{
	const string s1("hello world");
	//string::const_iterator it1 = s1.begin();
	auto it1 = s1.begin();

	while (it1 != s1.end())
	{
		//不能修改
		//*it1 += 3;

		cout << *it1 << " ";
		++it1;
	}

	cout << endl;
}

int main()
{
	test_string5();

	return 0;
}
  1. 反向迭代器
    反向迭代器
void test_string5()
{
	string s2("hello world");
	string::reverse_iterator it2 = s2.rbegin();
	//auto it2 = s2.rbegin();

	while (it2 != s2.rend())
	{
		*it2 += 3;

		cout << *it2 << " ";
		++it2;
	}

	cout << endl;

	const string s3("hello world");
	string::const_reverse_iterator it3 = s3.rbegin();
	//auto it3 = s3.rbegin();

	while (it3 != s3.rend())
	{
		//不能修改
		//*it3 += 3;

		cout << *it3 << " ";
		++it3;
	}

	cout << endl;
}

int main()
{
	test_string5();

	return 0;
}

  • 按字典序排序
    排序
#include <algorithm>

void test_string6()
{
	string s1("hello world");
	cout << s1 << endl;

	//s1按字典序(ASCII码)排序
	//sort(s1.begin(), s1.end());
	
	//第一个和最后一个不参与排序
	//sort(++s1.begin(), --s1.end());
	
	//前5个排序
	sort(s1.begin(), s1.begin() + 5);
	
	cout << s1 << endl;
}

int main()
{
	test_string6();

	return 0;
}
  • 插入字符
    append
void test_string7()
{
	string s1("hello world");
	cout << s1 << endl;

	s1.push_back('x');
	cout << s1 << endl;

	s1.append(" yyyyyy!!");
	cout << s1 << endl;

	string s2("111111");

	s1 += 'y';
	s1 += "zzzzzzzz";
	s1 += s2;
	cout << s1 << endl;
}

int main()
{
	test_string7();

	return 0;
}

注: 在string尾部追加字符时,s.push_back(‘c’) / s.append(1, ‘c’) / s += ‘c’ 三种的实现方式差不多,一般情况下string类的 += 操作用的比较多,+= 操作不仅可以连接单个字符,还可以连接字符串

  • 关于修改的一些接口
    insert
void test_string8()
{
	string s1("hello world");
	cout << s1 << endl;

	s1.assign("111111");
	cout << s1 << endl;

	//慎用,因为效率不高 -> O(N)
	//实践中需求也不高
	string s2("hello world");
	s2.insert(0, "xxxx");
	cout << s2 << endl;

	s2.insert(0, 1, 'y');
	cout << s2 << endl;

	s2.insert(s2.begin(), 'y');
	cout << s2 << endl;

	s2.insert(s2.begin(), s1.begin(), s1.end());
	cout << s2 << endl;
}

int main()
{
	test_string8();

	return 0;
}
void test_string9()
{
	string s1("hello world");
	cout << s1 << endl;
	
	//erase效率不高,慎用,和insert类似,要挪动数据
	s1.erase(0, 1);
	cout << s1 << endl;

	//s1.erase(5);
	s1.erase(5, 100);
	cout << s1 << endl;

	//replace效率不高,慎用,和insert类似,要挪动数据
	string s2("hello world");
	s2.replace(5, 1, "%20");
	cout << s2 << endl;

	string s3("hello world hello bit");

	for (size_t i = 0; i < s3.size(); )
	{
		if (' ' == s3[i])
		{
			s3.replace(i, 1, "%20");
			i += 3;
		}
		else
		{
			i++;
		}
	}

	cout << s3 << endl;

	string s4("hello world hello bit");
	string s5;

	for (auto ch : s4)
	{
		if (ch != ' ')
		{
			s5 += ch;
		}
		else
		{
			s5 += "%20";
		}
	}

	cout << s5 << endl;
}

int main()
{
	test_string9();

	return 0;
}

我们来做几个题目:

  • 仅仅反转字母
    仅仅反转字母
class Solution
{
public:
    bool isLetter(char ch)
    {
        if (ch >= 'a' && ch <= 'z')
        {
            return true;
        }

        if (ch >= 'A' && ch <= 'Z')
        {
            return true;
        }

        return false;
    }

    string reverseOnlyLetters(string s)
    {
        if (s.empty())
        {
            return s;
        }

        size_t begin = 0, end = s.size() - 1;

        while (begin < end)
        {
            while (begin < end && !isLetter(s[begin]))
            {
                ++begin;
            }

            while (begin < end && !isLetter(s[end]))
            {
                --end;
            }

            swap(s[begin], s[end]);
            ++begin;
            --end;
        }

        return s;
    }
};
  • 字符串中的第一个唯一字符
    字符串中的第一个唯一字符
 class Solution
{
public:
    int firstUniqChar(string s)
    {
        int count[26] = { 0 };

        //统计次数
        for (auto ch : s)
        {
            count[ch - 'a']++;
        }

        for (size_t i = 0; i < s.size(); ++i)
        {
            if (1 == count[s[i] - 'a'])
            {
                return i;
            }
        }

        return -1;
    }
};
  • 验证回文串
    验证回文串
class Solution
{
public:
    bool isLetterOrNumber(char ch)
    {
        return (ch >= '0' && ch <= '9')
        || (ch >= 'a' && ch <= 'z');
    }

    bool isPalindrome(string s)
    {
        for (auto& ch : s)
        {
            if (ch >= 'A' && ch <= 'Z')
            {
                ch += 32;
            }
        }

        int begin = 0, end = s.size() - 1;

        while (begin < end)
        {
            while (begin < end && !isLetterOrNumber(s[begin]))
            {
                ++begin;
            }

            while (begin < end && !isLetterOrNumber(s[end]))
            {
                --end;
            }

            if (s[begin] != s[end])
            {
                return false;
            }
            else
            {
                ++begin;
                --end;
            }
        }

        return true;
    }
};
  • 字符串相加
    字符串相加

法一:

//时间复杂度:O(N^2) 因为头插的效率太低
class Solution
{
public:
    string addStrings(string num1, string num2)
    {
        int end1 = num1.size() - 1;
        int end2 = num2.size() - 1;

        string str;
        int next = 0;//进位

        while (end1 >= 0 || end2 >= 0)
        {
            int x1 = end1 >= 0 ? num1[end1--] - '0': 0;
            int x2 = end2 >= 0 ? num2[end2--] - '0': 0;
            int x = x1 + x2 + next;
            
            //处理进位
            next = x / 10;
            x = x % 10;

            //头插
            //str.insert(0, 1, '0' + x);
            str.insert(str.begin(), '0' + x);
        }

        if (1 == next)
        {
            str.insert(str.begin(), '1');
        }

        return str;
    }
};

法二:

//时间复杂度:O(N)
class Solution
{
public:
    string addStrings(string num1, string num2)
    {
        int end1 = num1.size() - 1;
        int end2 = num2.size() - 1;

        string str;
        int next = 0;//进位

        while (end1 >= 0 || end2 >= 0)
        {
            int x1 = end1 >= 0 ? num1[end1--] - '0': 0;
            int x2 = end2 >= 0 ? num2[end2--] - '0': 0;
            int x = x1 + x2 + next;
            
            //处理进位
            next = x / 10;
            x = x % 10;

            //尾插
            str += ('0' + x);
        }

        if (1 == next)
        {
            str += '1';
        }

        reverse(str.begin(), str.end());

        return str;
    }
};

  • string类对象的容量操作
void TestPushBack()
{
	string s;
	size_t sz = s.capacity();
	cout << "capacity changed: " << sz << '\n';
	
	cout << "making s grow:\n";
	for (int i = 0; i < 200; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

void test_string10()
{
	string s1("hello world hello bit");
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
	cout << s1.max_size() << endl;
	
	TestPushBack();

	string s1("111111111");
	string s2("11111111111111111111111111111111111111111111111111");
}

int main()
{
	test_string10();

	return 0;
}

string类在不同环境下的对比

void TestPushBack()
{
	string s;
	//知道需要多少空间,提前开好
	s.reserve(200);
	size_t sz = s.capacity();
	cout << "capacity changed: " << sz << '\n';
	
	cout << "making s grow:\n";
	for (int i = 0; i < 200; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

void test_string10()
{	
	TestPushBack();

	string s1("111111111");
	string s2("11111111111111111111111111111111111111111111111111");

	cout << s1.capacity() << endl;
	
	s1.reserve(100);
	cout << s1.capacity() << endl;
	
	s1.reserve(20);
	cout << s1.capacity() << endl;
}

int main()
{
	test_string10();

	return 0;
}

reserve

void test_string11()
{
	string s1;
	//s1.resize(5, '0');
	s1.resize(5);
	s1[4] = '3';
	s1[3] = '4';
	s1[2] = '5';
	s1[1] = '6';
	s1[0] = '7';
	//76543

	//插入(空间不够会扩容)
	string s2("hello world");
	s2.resize(20, 'x');

	//删除
	s2.resize(5);
	
	//s2[10];

	try
	{
		s2.at(10);
	}
	catch (const exception& e)
	{
		cout << e.what() << endl;
	}
}

int main()
{
	test_string11();

	return 0;
}

注:

  1. clear()只是将string中有效字符清空,不改变底层空间大小。(代码中没有演示)
  2. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变
  3. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小
  4. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。

  • string类的一些其他操作
#define _CRT_SECURE_NO_WARNINGS 1

void test_string12()
{
	string file("test.cpp");
	FILE* fout = fopen(file.c_str(), "r");
	char ch = fgetc(fout);

	while (ch != EOF)
	{
		cout << ch;
		ch = fgetc(fout);
	}
}

int main()
{
	test_string12();

	return 0;
}
void test_string12()
{
	string file("string.cpp.zip");
	size_t pos = file.rfind('.');
	//string suffix = file.substr(pos, file.size() - pos);
	string suffix = file.substr(pos);
	cout << suffix << endl;
}

int main()
{
	test_string12();

	return 0;
}
void test_string12()
{
	string url("https://gitee.com/ailiangshilove/cpp-class/blob/master/%E8%AF%BE%E4%BB%B6%E4%BB%A3%E7%A0%81/C++%E8%AF%BE%E4%BB%B6V6/string%E7%9A%84%E6%8E%A5%E5%8F%A3%E6%B5%8B%E8%AF%95%E5%8F%8A%E4%BD%BF%E7%94%A8/TestString.cpp");
	size_t pos1 = url.find(':');
	string url1 = url.substr(0, pos1 - 0);
	cout << url1 << endl;

	size_t pos2 = url.find('/', pos1 + 3);
	string url2 = url.substr(pos1 + 3, pos2 - (pos1 + 3));
	cout << url2 << endl;

	string url3 = url.substr(pos2 + 1);
	cout << url3 << endl;
}

int main()
{
	test_string12();

	return 0;
}
void test_string13()
{
	string str("Please, replace the vowels in this sentence by asterisks.");
	size_t found = str.find_first_of("aeiou");
	
	while (found != string::npos)
	{
		str[found] = '*';
		found = str.find_first_of("aeiou", found + 1);
	}

	cout << str << '\n';
}

int main()
{
	test_string13();

	return 0;
}
void SplitFilename(const string& str)
{
	cout << "Splitting: " << str << '\n';
	size_t found = str.find_last_of("/\\");
	cout << " path: " << str.substr(0, found) << '\n';
	cout << " file: " << str.substr(found + 1) << '\n';
}

int main()
{
	string str1("/usr/bin/man");
	string str2("c:\\windows\\winhelp.exe");

	SplitFilename(str1);
	SplitFilename(str2);

	return 0;
}
void test_string14()
{
	string s1 = "hello";
	string s2 = "world";

	string ret1 = s1 + s2;
	cout << ret1 << endl;
	
	string ret2 = s1 + "xxxxx";
	cout << ret2 << endl;

	string ret3 = "xxxxx" + s1;
	cout << ret3 << endl;

	//字典序比较
	cout << (s1 < s2) << endl;
}

int main()
{
	test_string14();

	return 0;
}

一个题目:

  • 字符串最后一个单词的长度

字符串最后一个单词的长度

#include <iostream>
using namespace std;

int main()
{
    string str;
    //默认规定空格或者换行是多个值之间分割
    //cin >> str;

    //获取一行中包含空格,不能用>>
    getline(cin, str);

    size_t pos = str.rfind(' ');
    cout << str.size() - (pos + 1) << endl;

    return 0;
}

  • 输入多行字符依次打印:
int main()
{
	//默认规定空格或者换行是多个值之间分割
	string str;
	
	//ctrl + z 就可以结束
	while (cin >> str)
	{
		cout << str << endl;
	}

	return 0;
}
  • 字符串转整形,整形转字符串
int main()
{
	//atoi itoa

	//to_string
	int x = 0, y = 0;
	cin >> x >> y;
	string str = to_string(x + y);
	cout << str << endl;

	int z = stoi(str);

	return 0;
}

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

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

相关文章

【Go并发编程】Goroutine 调度器揭秘:从 GMP 模型到 Work Stealing 算法

每天一篇Go语言干货&#xff0c;从核心到百万并发实战&#xff0c;快来关注魔法小匠&#xff0c;一起探索Go语言的无限可能&#xff01; 在 Go 语言中&#xff0c;Goroutine 是一种轻量级的并发执行单元&#xff0c;它使得并发编程变得简单高效。而 Goroutine 的高效调度机制是…

【前端】Vue组件库之Element: 一个现代化的 UI 组件库

文章目录 前言一、官网1、官网主页2、设计原则3、导航4、组件 二、核心功能&#xff1a;开箱即用的组件生态1、丰富的组件体系2、特色功能亮点 三、快速上手&#xff1a;三步开启组件化开发1、安装&#xff08;使用Vue 3&#xff09;2、全局引入3、按需导入&#xff08;推荐&am…

坐井说天阔---DeepSeek-R1

前言 DeepSeek-R1这么火&#xff0c;虽然网上很多介绍和解读&#xff0c;但听人家的总不如自己去看看原论文。于是花了大概一周的时间&#xff0c;下班后有进入了研究生的状态---读论文。 DeepSeek这次的目标是探索在没有任何监督数据的情况下训练具有推理能力的大模型&#…

UART(一)——UART基础

一、定义 UART(Universal Asynchronous Receiver/Transmitter)是一种广泛使用的串行通信协议,用于在设备间通过异步方式传输数据。它无需共享时钟信号,而是依赖双方预先约定的参数(如波特率)完成通信。 功能和特点 基本的 UART 系统只需三个信号即可提供稳健的中速全双工…

DeepSeek 的创新融合:多行业应用实践探索

引言 在数字化转型的浪潮中&#xff0c;技术的融合与创新成为推动各行业发展的关键力量。蓝耘平台作为行业内备受瞩目的创新平台&#xff0c;以其强大的资源整合能力和灵活的架构&#xff0c;为企业提供了高效的服务支持。而 DeepSeek 凭借先进的人工智能技术&#xff0c;在自然…

CentOS 7超详细安装教程(含镜像)

1. 安装前准备 1.1 CentOS简介 CentOS&#xff08;Community Enterprise Operating System&#xff0c;中文意思是&#xff1a;社区企业操作系统&#xff09;是一种基于 Red Hat Enterprise Linux&#xff08;RHEL&#xff09;源代码构建的免费开源操作系统。它在稳定性、安全…

Qt中基于开源库QRencode生成二维码(附工程源码链接)

目录 1.QRencode简介 2.编译qrencode 3.在Qt中直接使用QRencode源码 3.1.添加源码 3.2.用字符串生成二维码 3.3.用二进制数据生成二维码 3.4.界面设计 3.5.效果展示 4.注意事项 5.源码下载 1.QRencode简介 QRencode是一个开源的库&#xff0c;专门用于生成二维码&…

SpringBoot教程(三十二) SpringBoot集成Skywalking链路跟踪

SpringBoot教程&#xff08;三十二&#xff09; | SpringBoot集成Skywalking链路跟踪 一、Skywalking是什么&#xff1f;二、Skywalking与JDK版本的对应关系三、Skywalking下载四、Skywalking 数据存储五、Skywalking 的启动六、部署探针 前提&#xff1a; Agents 8.9.0 放入 …

IntelliJ IDEA 接入 AI 编程助手(Copilot、DeepSeek、GPT-4o Mini)

IntelliJ IDEA 接入 AI 编程助手&#xff08;Copilot、DeepSeek、GPT-4o Mini&#xff09; &#x1f4ca; 引言 近年来&#xff0c;AI 编程助手已成为开发者的高效工具&#xff0c;它们可以加速代码编写、优化代码结构&#xff0c;并提供智能提示。本文介绍如何在 IntelliJ I…

【机器学习】深入浅出KNN算法:原理解析与实践案例分享

在机器学习中&#xff0c;K-最近邻算法&#xff08;K-Nearest Neighbors, KNN&#xff09;是一种既直观又实用的算法。它既可以用于分类&#xff0c;也可以用于回归任务。本文将简单介绍KNN算法的基本原理、优缺点以及常见应用场景&#xff0c;并通过一个简单案例帮助大家快速入…

vscode的一些实用操作

1. 焦点切换(比如主要用到使用快捷键在编辑区和终端区进行切换操作) 2. 跳转行号 使用ctrl g,然后输入指定的文件内容&#xff0c;即可跳转到相应位置。 使用ctrl p,然后输入指定的行号&#xff0c;回车即可跳转到相应行号位置。

JavaEE基础 Tomcat与Http (下)

目录 1.HTTP 协议 1.1 HTTP 协议概念 1.2. 无状态协议 1.3. HTTP1.0 和 HTTP1.1 1.4 请求协议和响应协议 ​编辑 1.5 请求协议 1.5.1 常见的请求协议 1.5.2 GET 请求 1.5.3 POST请求 1.5.4 响应协议 1.HTTP 协议 Http浏览器访问东西都是遵循的Http协议。 1.1 HTTP 协议…

【Linux】【进程】epoll内核实现总结+ET和LT模式内核实现方式

【Linux】【网络】epoll内核实现总结ET和LT模式内核实现方式 1.epoll的工作原理 eventpoll结构 当某一进程调用epoll_create方法时&#xff0c;Linux内核会创建一个eventpoll结构体&#xff0c;这个结构体中有两个成员与epoll的使用方式密切相关. struct eventpoll{..../*红…

英码科技基于昇腾算力实现DeepSeek离线部署

DeepSeek-R1 模型以其创新架构和高效能技术迅速成为行业焦点。如果能够在边缘进行离线部署&#xff0c;不仅能发挥DeepSeek大模型的效果&#xff0c;还能确保数据处理的安全性和可控性。 英码科技作为AI算力产品和AI应用解决方案服务商&#xff0c;积极响应市场需求&#xff0…

【SQL】SQL约束

&#x1f384;约束 &#x1f4e2;作用:是用于限制存储再表中的数据。可以再创建表/修改表时添加约束。 &#x1f4e2;目的:保证数据库中数据的正确、有效性和完整性。 &#x1f4e2;对于一个字段可以同时添加多个约束。 &#x1f384;常用约束: 约束分类 约束 描述关键字非…

解决 `pip is configured with locations that require TLS/SSL` 错误

问题描述 在使用 pip 安装 Python 包时&#xff0c;可能会遇到以下错误&#xff1a; WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.这意味着 Python 的 ssl 模块未正确安装或配置&#xff0c;导致 p…

Python 面向对象的三大特征

前言&#xff1a;本篇讲解面向对象的三大特征&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;&#xff0c;还有比较细致的&#xff08;类属性类方法&#xff0c;静态方法&#xff09;&#xff0c;分步骤讲解&#xff0c;比较适合理清楚三大特征的思路 面向对象的…

机器学习_18 K均值聚类知识点总结

K均值聚类&#xff08;K-means Clustering&#xff09;是一种经典的无监督学习算法&#xff0c;广泛应用于数据分组、模式识别和降维等领域。它通过将数据划分为K个簇&#xff0c;使得簇内相似度高而簇间相似度低。今天&#xff0c;我们就来深入探讨K均值聚类的原理、实现和应用…

从低清到4K的魔法:FlashVideo突破高分辨率视频生成计算瓶颈(港大港中文字节)

论文链接&#xff1a;https://arxiv.org/pdf/2502.05179 项目链接&#xff1a;https://github.com/FoundationVision/FlashVideo 亮点直击 提出了 FlashVideo&#xff0c;一种将视频生成解耦为两个目标的方法&#xff1a;提示匹配度和视觉质量。通过在两个阶段分别调整模型规模…

Nuclei 使用手册

Nuclei 是一个开源的快速、高效的漏洞扫描工具&#xff0c;主要用于网络安全领域的漏洞检测。它由 go 语言开发&#xff0c;设计目的是为了高效地扫描 Web 应用程序、网络服务等目标&#xff0c;帮助安全研究人员、渗透测试人员以及红队成员发现潜在的漏洞。 下载链接&#xf…