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

string(三)--实现

大家看了这么久的string了,可能对string的简单实现有兴趣,所以我实现了一个string类的常用接口,大家可以自行查看:

我是分多文件写的:

string.h:

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
#include <string.h>
#include <assert.h>namespace cx
{class string{public://构造函数:string(const char* str = "");//默认值声明时写--string()string(const string& s);	string(size_t n, char c);string(const char* s, size_t n);string(const string& str, size_t pos, size_t len = npos);//运算符重载构造string& operator= (const char* s);	string& operator= (char c);	//string& operator=(const string& s);string& operator=(const string s);//析构函数~string();//迭代器部分: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;}iterator rbegin(){return end();}const_iterator rbegin() const{return end();}iterator rend(){return begin();}const_iterator rend() const{return begin();}//capacity:inline size_t size()const{return _size;}inline size_t length()const{return _size;}inline size_t capacity()const{return _capacity;}inline bool empty()const{return _size == 0;}void reserve(size_t n = 0);inline size_t max_size() const{return -1;}void clear();		//modify:string& operator+= (const string& str);string & operator+= (const char* s);string& operator+= (char c);void push_back(char c);string& append(const string& str);string& append(const string& str, size_t subpos, size_t sublen);string & append(const char* s);string& append(const char* s, size_t n);string& append(size_t n, char c);string& erase(size_t pos = 0, size_t len = npos);void swap(string& str);void pop_back();string& replace(size_t pos, size_t len, const string& str);string& replace(size_t pos, size_t len, const char* s);//      const char* c_str()const;//access:char& operator[] (size_t pos);const char& operator[] (size_t pos) const;char& at(size_t pos);const char& at(size_t pos) const;//String operations :size_t find(const string& str, size_t pos = 0) const;size_t find(const char* s, size_t pos = 0) const;size_t find(const char* s, size_t pos, size_t n) const;size_t find(char c, size_t pos = 0) const;string substr(size_t pos = 0, size_t len = npos) const;//Non - member function overloads:bool operator<(const string& s);bool operator<=(const string& s);bool operator>(const string& s);bool operator>=(const string& s);bool operator==(const string& s);bool operator!=(const string& s);//友元部分:friend ostream& operator<<(ostream& _cout, const cx::string& s);	friend istream& operator>>(istream& _cin, cx::string& s);private:const static size_t npos=-1;//特殊用法//static size_t npos;char* _str=nullptr;//缺省值size_t _size=0;//缺省值size_t _capacity=0;//缺省值};
};
//static正常用法
//size_t npos = -1;

string.cpp:

#include "string.h"
//构造函数:
cx::string::string(const char* str)//默认值处理空串
{//不适合列表初始化,原因在于strlen时间复杂度O(N)_size = strlen(str);_capacity = _size;char* tmp = new char[_size + 1];//new不用检查strcpy(tmp, str);tmp[_size] = '\0';delete[] _str;_str = tmp;
}
//传统写法:
//cx::string::string(const string& s)
//{
//	char* tmp = new char[s.size() + 1];
//	strcpy(tmp, s._str);
//	tmp[s.size()] = '\0';
//	delete[] _str;
//	_str = tmp;
//	_capacity = s._capacity;
//	_size = s._size;
//}
//现代写法;
cx::string::string(const string& s)
{cx::string tmp(s._str);//拷贝一份临时变量swap(tmp);//将*this和tmp交换//注意点,this初始化情况,我们在private处给缺省值
}
cx::string::string(size_t n, char c)
{char* tmp = new char[n + 1];//strcpy(_str, 0);_size = n;_capacity = n;for (int i = 0; i < n; i++){tmp[i] = c;}tmp[_size] = '\0';delete[] _str;_str = tmp;
}
cx::string::string(const char* s, size_t n)
{char* tmp = new char[n + 1];strncpy(tmp, s, n);tmp[n] = '\0';delete[] _str;_str = tmp;_size = _capacity = n;
}
cx::string::string(const string& str, size_t pos, size_t len)
{if (len == npos || pos + len > str._size){char* tmp = new char[str.size() - pos + 1];_capacity = str.size() - pos;strncpy(tmp, str._str + pos, len);delete[] _str;_str = tmp;}else{char* tmp = new char[len + 1];_capacity = len;strncpy(tmp, str._str + pos, len);delete[] _str;_str = tmp;}_size = len;_str[_size] = '\0';
}
//运算符重载构造
cx::string& cx::string::operator= (const char* s)
{_capacity = _size = strlen(s);char* tmp = new char[_size + 1];strcpy(tmp, s);tmp[_size] = '\0';delete[] _str;_str = tmp;return *this;
}
cx::string& cx::string::operator= (char c)
{char* tmp = new char[2];tmp[0] = c;_size = _capacity = 1;tmp[_size] = '\0';delete[] _str;_str = tmp;return *this;
}
//传统写法:
//cx::string& cx::string::operator=(const string& s)
//{
//	if (this != &s)
//	{
//		char* tmp = new char[s._capacity + 1];
//		strcpy(tmp, s._str);
//		tmp[s._capacity] = '\0';
//		delete[] _str;
//		_str = tmp;
//		_size = s._size;
//		_capacity = s._capacity;
//	}
//	return *this;
//}
//现代写法:
cx::string& cx::string::operator=(string s)
{swap(s);//将this和s交换return *this;
}
//析构函数
cx::string::~string()
{delete[] _str;_str = nullptr;_size = _capacity = 0;
}//capacity:
void cx::string::reserve(size_t n)
{if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);		delete[] _str;_str = tmp;_capacity = n;}
}
void cx::string::clear()
{erase();
}
void cx::string::swap(string& str)
{std::swap(_str, str._str);std::swap(_size,str._size);std::swap(_capacity , str._capacity);
}
void cx::string::pop_back()
{erase(_size - 1, 1);
}
cx::string& cx::string::replace(size_t pos, size_t len, const string& str)
{//检查if (pos + len > _size){reserve(pos + len);strncpy(_str + pos, str._str, len);_size = pos + len;_str[_size] = '\0';}else{strncpy(_str + pos, str._str, len);_size = pos + len;}return *this;
}
cx::string& cx::string::replace(size_t pos, size_t len, const char* s)
{//检查if (pos + len > _size){reserve(pos + len);strncpy(_str + pos, s, len);_size = pos + len;_str[_size] = '\0';}else{strncpy(_str + pos, s, len);_size = pos + len;}return *this;
}//modify:
cx::string& cx::string::operator+= (const cx::string& str)
{append(str);return *this;
}
cx::string& cx::string::operator+= (const char* s)
{append(s);return *this;
}
cx::string& cx::string::operator+= (char c)
{push_back(c);return *this;
}
void cx::string::push_back(char c)
{if (_capacity == _size){size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;reserve(newcapacity);}_str[_size++] = c;_str[_size] = '\0';
}
cx::string& cx::string::append(const string& str)
{if (str._size + _size > _capacity){reserve(str._size + _size);}strcpy(_str + _size, str._str);_size += str._size;_str[_size] = '\0';return *this;
}
cx::string& cx::string::append(const char* s)
{size_t len = strlen(s);if (len + _size > _capacity){reserve(_size + len);}strcpy(_str + _size, s);_size += len;_str[_size] = '\0';return *this;
}
cx::string& cx::string::append(size_t n, char c)
{//检查if (n + _size > _capacity){reserve(n + _size);}for (size_t i = _size; i < _size + n; i++){_str[i] = c;}_size += n;_str[_size] = '\0';return *this;
}
cx::string& cx::string::append(const char* s, size_t n)
{//检查if (n + _size > _capacity){reserve(n + _size);}strncpy(_str+_size, s, n);_size += n;_str[_size] = '\0';return *this;
}
cx::string& cx::string::append(const string& str, size_t subpos, size_t sublen)
{//检查if (sublen + _size > _capacity){reserve(sublen + _size);}strncpy(_str+_size, str._str+subpos, sublen);_size += sublen;_str[_size] = '\0';return *this;
}
cx::string& cx::string::erase(size_t pos, size_t len)
{	assert(pos <= _size);if (len == npos || len + pos > _size){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;_str[_size] = '\0';}return *this;
}//access:
char& cx::string::operator[] (size_t pos)
{assert(pos <= _size);return *(_str + pos);//等价于_str[pos]
}
const char& cx::string::operator[] (size_t pos) const
{assert(pos <= _size);return *(_str + pos);//等价于_str[pos]
}
char& cx::string::at(size_t pos)
{assert(pos < _size);return _str[pos];
}
const char& cx::string::at(size_t pos) const
{assert(pos < _size);return _str[pos];
}//String operations :
size_t cx::string::find(const string& str, size_t pos ) const
{char* tmp = new char[str._size + 1];strcpy(tmp, str._str);tmp[str._size ] = '\0';const char* ptr = strstr(_str + pos, tmp);if (ptr == nullptr){delete[] tmp;tmp = nullptr;return npos;}else{delete[] tmp;tmp = nullptr;return ptr - _str;}
}
size_t cx::string::find(const char* s, size_t pos ) const
{const char* ptr = strstr(_str + pos, s);if (ptr == nullptr){return npos;}else{return ptr - _str;}
}
size_t cx::string::find(const char* s, size_t pos, size_t n) const
{char* tmp = new char[n];strcpy(tmp, s);tmp[n] = '\0';const char* ptr = strstr(_str + pos, tmp);if (ptr == nullptr){delete[] tmp;tmp = nullptr;return npos;}else{delete[] tmp;tmp = nullptr;return ptr - _str;}
}
size_t cx::string::find(char c, size_t pos ) const
{for (size_t i = pos; i < _size; i++){if (_str[i] == c)return i;}return npos;
}
cx::string cx::string::substr(size_t pos , size_t len) const
{//检查:assert(pos < _size);size_t end = pos + len;if (len == npos || pos + len >= _size){end = _size;}string str;str.reserve(end - pos);for (size_t i = pos; i < end; i++){str += _str[i];}return str;
}//Non - member function overloads:
bool cx::string::operator<(const string& s)
{size_t n = _size > s._size ? s._size : _size;for (size_t i = 0; i < n; i++){if (_str[i] >= s._str[i])return false;}if (n == s._size)return false;elsereturn true;
}
bool cx::string::operator<=(const string& s)
{return !(*this > s);
}
bool cx::string::operator>(const string& s)
{return !((*this == s) || (*this < s));
}
bool cx::string::operator>=(const string& s)
{return !(*this < s);
}
bool cx::string::operator==(const string& s)
{if (_size != s._size)return false;for (size_t i = 0; i < _size; i++){if (_str[i] != s._str[i])return false;}return true;
}
bool cx::string::operator!=(const string& s)
{return !(*this == s);
}//友元:
// 写法一:
//namespace cx
//{
//	ostream& operator<<(ostream& _cout, const cx::string& s)
//	{
//		for (auto e : s)
//		{
//			_cout << e;
//		}
//		return _cout;
//	}
//}
//写法二:
ostream& cx::operator<<(ostream& _cout, const cx::string& s)
{for (auto e : s){_cout << e;}return _cout;
}
istream& cx::operator>>(istream& _cin, cx::string& s)
{s.clear();//清除内容char ch = _cin.get();//建立一个缓冲数组char buff[64];size_t i = 0;while((ch != ' ') && (ch != '\n')){//读入buff中buff[i++] = ch;if (65 == i){buff[i] = '\0';//注意:置零s += buff;//利用operator+=数组i = 0;}ch = _cin.get();}if (i > 0){buff[i] = '\0';s += buff;}return _cin;
}

test.cpp:

#include "string.h"
void test_string()
{cx::string s0("Initial string");std::cout << s0 << std::endl;cx::string s1;std::cout << s1 << std::endl;cx::string s2(s0);std::cout << s2 << std::endl;cx::string s3(s0, 8, 3);std::cout << s3 << std::endl;cx::string s4("A character sequence");std::cout << s4 << std::endl;cx::string s5("Another character sequence", 12);std::cout << s5 << std::endl;cx::string s6(10, 'x');std::cout << s6 << std::endl;cx::string s7(10, 42);std::cout << s7 << std::endl;
}
void test_operator()
{cx::string str("Test string");for (int i = 0; i < str.size(); ++i){std::cout << str[i] << std::endl;}for (int i = 0; i < str.length(); ++i){std::cout << str[i] << std::endl;}
}
void test_capacity()
{cx::string str("Test string");std::cout << str.max_size() << std::endl;std::cout << str.capacity() << std::endl;
}
void test_reserve()
{cx::string str("Test string");std::cout << str.empty() << std::endl;std::cout << str.capacity() << std::endl;str.reserve(50);std::cout << str.capacity() << std::endl;
}
void _string2()
{cx::string s0("Initial string");cout << s0 << std::endl;cx::string s1;cout << s1 << std::endl;cx::string s2(s0);cout << s2 << std::endl;cx::string s3(s0, 8, 3);cout << s3 << std::endl;cx::string s4("A character sequence");cout << s4 << std::endl;cx::string s5("Another character sequence", 12);cout << s5 << std::endl;cx::string s6(10, 'x');cout << s6 << std::endl;cx::string s7(10, 42);cout << s7 << std::endl;
}
void test_s()
{cx::string s0("Initial string");cx::string s3(s0, 8, 3);cout << s3 << std::endl;
}
void test_opertaor()
{cx::string s1 = "hello world";cx::string s2 = "c";cx::string s3 = s1;cout << s1 << std::endl;cout << s2 << std::endl;cout << s3 << std::endl;
}
void test_o()
{cx::string str1, str2, str3;str1 = "Test string: ";   // c-stringstr2 = 'x';               // single character//str3 = str1 + str2;       // stringcout << str1 << std::endl;cout << str2 << std::endl;
}
void test_push()
{cx::string s1 = "hello worl";s1.push_back('d');cout << s1 << std::endl;
}
void test_append()
{cx::string str;cx::string str2 = "Writing ";cx::string str3 = "print 10 and then 5 more";str.append(str2);// "Writing "cout << str << std::endl;str.append(str3, 6, 3);// "10 "cout << str << std::endl;str.append("dots are cool", 5);// "dots "cout << str << std::endl;str.append("here: ");// "here: "cout << str << std::endl;str.append(10u, '.'); // ".........."cout << str << std::endl;
}
void test_oper()
{cx::string name("John");cx::string family("Smith");name += " K. ";cout << name << std::endl;name += family;cout << name << std::endl;name += '\n';cout << name << std::endl;
}
void erase_test()
{cx::string s1 = "hello world";cout << s1.size() << std::endl;cout << s1.capacity() << std::endl;cout << s1 << endl;s1.clear();cout << s1.size() << std::endl;cout << s1.capacity() << std::endl;cout << s1 << endl;
}
void test_cin()
{cx::string s1, s2;cin >> s1;cout << s1 << endl;cin >> s2;s1 += s2;cout << s1 << endl;
}
void test_stringc()
{cx::string s1 = "helloworld";cx::string s2(s1);cout << s2 << endl;
}
void test_op()
{cx::string s1 = "hello world",s2;s2 = s1;cout << s2 << endl;
}
int main()
{test_stringc();return 0;
}

最后,感谢大家的支持!!!

相关文章:

string(三)--实现

大家看了这么久的string了&#xff0c;可能对string的简单实现有兴趣&#xff0c;所以我实现了一个string类的常用接口&#xff0c;大家可以自行查看&#xff1a; 我是分多文件写的&#xff1a; string.h: #pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include <ios…...

textbox跨线程写入

实现实例1 实现效果 跨线程实现 // 委托&#xff0c;用于定义在UI线程上执行的方法签名 //public delegate void SetTextCallback(string text);public void textBoxText(string text){// 检查调用线程是否是创建控件的线程 if (textBox1.InvokeRequired){// 如果不是&#…...

幻兽帕鲁专用服务器搭建之Linux部署配置教程

大家好我是飞飞&#xff0c;上一期我分享了Windows系统的幻兽帕鲁服务器搭建教程。因为幻兽帕鲁这游戏对服务器的配置有一定的要求&#xff0c;很多小伙伴就寻思用Linux系统搭建占用会不会小一点&#xff1f;有计算机基础的小伙伴都知道Linux系统和Windows系统相比&#xff0c;…...

Kubernetes: 本地部署dashboard

本篇文章主要是介绍如何在本地部署kubernetes dashboard, 部署环境是mac m2 下载dashboard.yaml 官网release地址: kubernetes/dashboard/releases 本篇文章下载的是kubernetes-dashboard-v2.7.0的版本&#xff0c;通过wget命令下载到本地: wget https://raw.githubusercont…...

Outlook邮箱IMAP密码怎么填写?账户设置?

Outlook邮箱IMAP密码是什么&#xff1f;Outlook如何设置IMAP&#xff1f; 许多用户会选择通过IMAP协议将邮箱与各种邮件客户端进行连接。而在设置过程中&#xff0c;填写IMAP密码是必不可少的一步。那么&#xff0c;Outlook邮箱的IMAP密码应该如何填写呢&#xff1f;接下来&am…...

[计算机网络]--I/O多路转接之poll和epoll

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、poll函…...

【NTN 卫星通信】卫星和无人机配合的应用场景

1 场景概述 卫星接入网是一种有潜力的技术&#xff0c;可以为地面覆盖差地区的用户提供无处不在的网络服务。然而&#xff0c;卫星覆盖范围对于位于考古或采矿地点内部/被茂密森林覆盖的村庄/山谷/靠近山丘或大型建筑物的用户可能很稀疏。因此&#xff0c;涉及卫星接入和无人驾…...

Git 分布式版本控制系统

Git是一个分布式版本控制系统&#xff0c;可以记录项目文件的变动并管理项目的不同版本。以下是Git的基本概念和使用方式&#xff1a; 仓库&#xff08;Repository&#xff09;&#xff1a;Git用仓库来存储项目文件。仓库可以是本地仓库&#xff0c;也可以是远程仓库&#xff0…...

ng : 无法将ng项识别为 cmdlet、函数、脚本文件或可运行程序的名称

ng : 无法将“ng”项识别为 cmdlet、函数、脚本文件或可运行程序的名称”&#xff0c;出现这种错误&#xff0c;那说明你angular-cli没有下载所以环境变量里没有相应的东西 1、需要在cmd里输入npm install -g angular/cli 2、之后运行angular命令时还可能出现这种错误 “ng : …...

iOS小技能:苹果书签打包教程【WebClip描述文件(WebClip Configuration Profile)】

文章目录 引言I WebClip描述文件1.1 属性说明1.2 利用Apple Configurator 2生成描述文件II 部署方式和签名2.1 对 .mobileconfig 文件进行签名2.2 部署方式引言 WebClip描述文件(WebClip Configuration Profile)是一种用于iOS设备的简易配置文件,它可以在你的iOS设备(如iP…...

Spring Cloud项目合规性注册之-(单元集成测试报告)

用于合规性注册&#xff0c;本文章仅提供模板 这个大纲涵盖了从单元测试到集成测试&#xff0c;再到自动化和持续集成的全方位测试过程。 一、引言 1. 项目概述 "xxxxxx"是一个先进的数据管理和展示平台&#xff0c;旨在提供高效、可靠的数据服务。该平台通过集成各…...

IntelliJ IDEA 常用的插件

IntelliJ IDEA有很多常用的插件&#xff0c;这些插件可以扩展IDE的功能&#xff0c;提高开发效率。以下是一些常用的插件&#xff1a; Maven Helper&#xff1a;这是一款分析Maven依赖冲突的插件。在没有此插件时&#xff0c;查看Maven的依赖树和检查依赖包冲突可能需要输入命…...

超详细红黑树的模拟实现

前言 有人说设计出AVL树的的人是个大牛&#xff0c;那写红黑树&#xff08;RBTree&#xff09;的人就是天才&#xff01; 上一篇文章&#xff0c;我们已经学习了AVL树&#xff0c;牛牛个人认为AVL树已经够优秀了&#xff0c;那让我们一起探究一下&#xff0c;为什么红黑树比AV…...

【亚马逊云科技】通过Amazon CloudFront(CDN)快速访问资源

文章目录 前言一、应用场景二、【亚马逊云科技】CloudFront&#xff08;CDN&#xff09;的优势三、入门使用总结 前言 前面有篇文章我们介绍了亚马逊云科技的云存储服务。云存储服务主要用于托管资源&#xff0c;而本篇文章要介绍的CDN则是一种对托管资源的快速访问服务&#…...

ES-ES的基本概念

ES的基本概念 一、文档 1.1 文档相关概念 ES是面向文档的&#xff0c;文档是所有可搜索数据的最小单位&#xff0c;可以对比理解为关系型数据库中的一条数据 日志文件中的一条日志信息一本电影的具体信息/一张唱片的详细信息 文档会被序列化成JSON格式保存在ES中 JSON对象由…...

排序算法——快速排序的非递归写法

快速排序的非递归 我们写快速排序的时候&#xff0c;通常用的递归的方法实现快速排序&#xff0c;那么有没有非递归的方法实现快速排序呢&#xff1f;肯定是有的。思想还是一样的&#xff0c;不过非递归是看似是非递归其实还是递归。 思路解释 快速排序的非递归使用的是栈这…...

【论文阅读】基于人工智能目标检测与跟踪技术的过冷流沸腾气泡特征提取

Bubble feature extraction in subcooled flow boiling using AI-based object detection and tracking techniques 基于人工智能目标检测与跟踪技术的过冷流沸腾气泡特征提取 期刊信息&#xff1a;International Journal of Heat and Mass Transfer 2024 级别&#xff1a;EI检…...

RabbitMQ讲解与整合

RabbitMq安装 类型概念 租户 RabbitMQ 中有一个概念叫做多租户&#xff0c;每一个 RabbitMQ 服务器都能创建出许多虚拟的消息服务器&#xff0c;这些虚拟的消息服务器就是我们所说的虚拟主机&#xff08;virtual host&#xff09;&#xff0c;一般简称为 vhost。 每一个 vhos…...

python 基础知识点(蓝桥杯python科目个人复习计划56)

今日复习内容&#xff1a;做题 例题1&#xff1a;最小的或运算 问题描述&#xff1a;给定整数a,b&#xff0c;求最小的整数x&#xff0c;满足a|x b|x&#xff0c;其中|表示或运算。 输入格式&#xff1a; 第一行包括两个正整数a&#xff0c;b&#xff1b; 输出格式&#…...

【vue】vue中数据双向绑定原理/响应式原理,mvvm,mvc、mvp分别是什么

关于 vue 的原理主要有两个重要内容&#xff0c;分别是 mvvm 数据双向绑定原理&#xff0c;和 响应式原理 MVC&#xff08;Model-View-Controller&#xff09;&#xff1a; Model&#xff08;模型&#xff09;&#xff1a;表示应用程序的数据和业务逻辑。View&#xff08;视图&…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章

用 Rust 重写 Linux 内核模块实战&#xff1a;迈向安全内核的新篇章 ​​摘要&#xff1a;​​ 操作系统内核的安全性、稳定性至关重要。传统 Linux 内核模块开发长期依赖于 C 语言&#xff0c;受限于 C 语言本身的内存安全和并发安全问题&#xff0c;开发复杂模块极易引入难以…...

Canal环境搭建并实现和ES数据同步

作者&#xff1a;田超凡 日期&#xff1a;2025年6月7日 Canal安装&#xff0c;启动端口11111、8082&#xff1a; 安装canal-deployer服务端&#xff1a; https://github.com/alibaba/canal/releases/1.1.7/canal.deployer-1.1.7.tar.gz cd /opt/homebrew/etc mkdir canal…...

【笔记】AI Agent 项目 SUNA 部署 之 Docker 构建记录

#工作记录 构建过程记录 Microsoft Windows [Version 10.0.27871.1000] (c) Microsoft Corporation. All rights reserved.(suna-py3.12) F:\PythonProjects\suna>python setup.py --admin███████╗██╗ ██╗███╗ ██╗ █████╗ ██╔════╝…...

基于 HTTP 的单向流式通信协议SSE详解

SSE&#xff08;Server-Sent Events&#xff09;详解 &#x1f9e0; 什么是 SSE&#xff1f; SSE&#xff08;Server-Sent Events&#xff09; 是 HTML5 标准中定义的一种通信机制&#xff0c;它允许服务器主动将事件推送给客户端&#xff08;浏览器&#xff09;。与传统的 H…...