C++深入学习string类成员函数(3):访问与修饰

引言

       在 C++ 中,std::string 提供了丰富的成员函数来访问和修改字符串中的字符。通过这些函数,程序员可以灵活地处理字符串中的各个元素,无论是读取特定位置的字符,还是修改字符串的内容。此外,std::string 类还确保了访问的安全性和高效性,例如提供边界检查的函数以防止非法操作。理解这些元素访问与修饰的函数,是编写健壮、灵活的字符串操作代码的基础。

1.string类的元素访问函数

std::string类提供了多种元素访问函数,用来访问或修改字符串中的单个字符,主要的访问函数如下:

1.1 at() 与 front()

1.1.1 at()

       at() 用于通过索引(也称下标)访问字符串中的字符。与 operator[] 不同,at()执行边界检查,如果索引超出范围,会抛出 std::out_of_range 异常,从而提高了操作的安全性。

(1)函数原型 

    char& at (size_t pos);
const char& at (size_t pos) const;

- 通过索引 pos 访问字符串中的字符。
- 如果索引合法,返回对应位置的字符引用。
- 如果索引超出范围,抛出 out_of_range 异常。

(2)示例代码 

#include <iostream>
using namespace std;int main() 
{string str = "Hello";// 安全地访问字符串中的字符try {str.at(1) = 'a'; // 修改字符cout << str << endl; // 输出 "Hallo"// 尝试访问越界的字符,抛出异常cout << str.at(10) << endl;}catch (const out_of_range& e) {cerr << "Exception: " << e.what() << endl;}return 0;
}

(3)优缺点 

优点:提供了边界检查,防止索引超出字符串长度时导致未定义行为。适用于需要严格检查的场景,尤其是在用户输入或动态索引时。

缺点:较 operator[] 稍慢,因为多了一步边界检查。

1.1.2 operator[] (下标操作符)

      operator[] 是 std::string 类中的下标操作符,用于通过索引访问字符串中的字符。

(1)函数原型 

      char& operator[] (size_t pos);
const char& operator[] (size_t pos) const;

 - 它提供了两种形式:非常量版本可以修改字符串中的字符常量版本则只能读取字符

- 与 at() 不同,operator[]不执行边界检查,因此如果访问越界会导致未定义行为。

(2)示例代码 

#include <iostream>
using namespace std;int main()
{string s1 = "Hello";const string s2 = "henu";cout << s1[1] << endl;//es1[1] = 'a';//s2[2] = 'a';//报错,表达式必须是可修改的左值cout << s1 << endl;//Halloreturn 0;
}

(3)注意事项:
- operator[] 的效率很高,因为它不进行边界检查。
- 如果需要更安全的操作,建议使用 at() 函数,它会抛出异常处理越界问题。

1.3 front() 与 back()

(1)front

front()用于返回对字符串的第一个字符的引用。非常量版本可修改字符,常量版本只能读取字符。
只能在非空字符串上调用,如果字符串为空,行为未定义。

      char& front();
const char& front() const;
#include <iostream>
using namespace std;int main()
{string s1 = "Hello";const string s2 = "henu";cout << s1.front() << endl;//Hcout << s2.front() << endl;//hs1.front() = 'L';cout << s1.front() << endl;//Lreturn 0;
}

(2)back()

back()用于返回对字符串的第一个字符的引用。非常量版本可修改字符,常量版本只能读取字符。
只能在非空字符串上调用,如果字符串为空,行为未定义。

char& back();               // 非常量版本,可修改字符
const char& back() const;    // 常量版本,只能读取字符
#include <iostream>
using namespace std;int main()
{string str = "Hello";// 访问最后一个字符cout << str.back() << endl; // 输出 'o'// 修改最后一个字符str.back() = '!';cout << str << endl; // 输出 "Hell!"return 0;
}

总结:
- operator[] 和 at():按索引访问字符串中的字符,at() 提供边界检查。
- front() 和 back():用于访问或修改字符串的第一个和最后一个字符。

这些访问函数提供了灵活的操作方式,既可以修改字符串内容,也可以确保访问的安全性。 

2.string类的修饰函数

2.1 append()


- 功能:append()用于将字符串或其他类型的数据追加到当前字符串对象的末尾。
- 重载形式:append()有多种重载形式,可以追加不同的数据类型,包括C风格字符串、std::string对象、字符数组的指定子串等。
- 返回值:返回对修改后的字符串对象的引用(this),因此可以进行链式调用。

(1)函数原型 

string (1)	    string& append (const string& str);
substring (2)	string& append (const string& str, size_t subpos, size_t sublen);
c-string (3)	string& append (const char* s);
buffer (4)	    string& append (const char* s, size_t n);
fill (5)	    string& append (size_t n, char c);
range (6)	    template <class InputIterator>string& append (InputIterator first, InputIterator last);
initializer list(7)	string& append (initializer_list<char> il);

(2)深入解析

1. string& append (const string& str)
将整个字符串 str 追加到当前字符串末尾。

	string s1 = "Hello ";string s2 = "henu";s1.append(s2);cout << s1 << endl;//Hello henucout << s2 << endl;//henu

2. string& append (const string& str, size_t subpos, size_t sublen)
从字符串 str subpos位置的字符开始sublen个字符,追加到当前字符。

	string s1 = "Hello ";string s2 = "henu";s1.append(s2, 0, 2);cout << s1 << endl;//Hello hecout << s2 << endl;//henu

3. string& append (const char* s)
将 C 风格的字符串 s 追加到当前字符串。

	string s1 = "Hello ";s1.append("world");cout << s1 << endl;//Hello world

4. string& append (const char* s, size_t n)
将 C 风格字符串 s 的前 n 个字符追加到当前字符串。

	string s1 = "Hello ";s1.append("world!!!", 6);cout << s1 << endl;//Hello world!

5.string& append (size_t n, char c)
将 n 个字符 c 追加到当前字符串。

	string s1 = "Hello ";s1.append(5, 'x');cout << s1 << endl;//Hello xxxxx

6. template <class InputIterator> string& append (InputIterator first, InputIterator last)
将范围 [first, last) 内的元素追加到当前字符串。这可以用于迭代器范围。

	string s1 = "Hello ";string s2 = "henu";s1.append(s2.begin(), s2.end());cout << s1 << endl;//Hello henu

7.string& append (initializer_list<char> il)
使用初始化列表追加字符。

	string s1 = "Hello ";s1.append({ 'W', 'o', 'r', 'l', 'd' });cout << s1 << endl;//Hello World

这些不同形式的append()函数为字符串操作提供了丰富的灵活性,可以根据需求追加整个字符串、子串、字符数组、或者指定范围的字符。

在C++中,std::string类提供了两种常见的方式来将字符串追加到现有字符串:append()函数和operator+=运算符。尽管它们在效果上相似,都用于拼接字符串,但它们在使用上有一些细微差别。  

 2.2 operator+=

- 功能:operator+=运算符也是用于将字符串或其他数据追加到字符串对象末尾的运算符。它的功能和append()类似,但更加简洁,适合简单的字符串拼接操作。
- 重载形式:它同样支持多种数据类型,包括`std::string`对象、C风格字符串和单个字符等。
- 返回值:与append()一样,operator+=返回修改后的字符串对象的引用(*this),支持链式调用。

 (1)函数原型

string (1)	          string& operator+= (const string& str);
c-string (2)	      string& operator+= (const char* s);
character (3)	      string& operator+= (char c);
initializer list (4)  string& operator+= (initializer_list<char> il);

(2)深入解析 

1. string& operator+= (const string& str)
将 std::string 对象 str 追加到当前字符串的末尾。

	string s1 = "Hello ";string s2 = "henu";s1 += s2;cout << s1 << endl;//Hello henu

2. string& operator+= (const char* s)
将C风格字符串 s 追加到当前字符串的末尾。

	string s1 = "Hello ";s1 += " World";cout << s1 << endl;//Hello World

3. string& operator+= (char c)
单个字符 c 追加到当前字符串的末尾。

	string s1 = "Hello ";s1 += "!";cout << s1 << endl;//Hello !

4. string& operator+= (initializer_list<char> il)
将初始化列表中的字符追加到当前字符串的末尾。

	string s1 = "Hello ";s1 += {'W', 'o', 'r', 'l', 'd'}; // str 变为 "Hello World"cout << s1 << endl;

这些运算符重载使得字符串拼接变得更加方便,简洁地处理不同类型的数据(字符串、字符数组、单个字符等)。

(3)与append()的区别与使用场景:
1. 简洁性:operator+=通常用于简洁的拼接操作,尤其适合简单的字符或字符串拼接;而`append()`可以提供更灵活的重载版本,适合更复杂的场景。
   
2. 重载灵活性:append()的重载更多,能更精细地控制如何拼接字符串。例如,指定要追加子串的起始位置和长度等。
   
3. 代码可读性:operator+=运算符在某些情况下代码更简洁、更易读,尤其是单个字符或简单字符串的拼接;而`append()`适合需要明确控制拼接逻辑的场合。

性能方面:
从性能上看,append()和operator+=基本没有明显的差异,除非在某些特定的优化场景下。编译器通常会对这两者进行类似的优化。

2.3 assign() 

assign()函数用来将一个新值赋给字符串对象。支持多种重载形式。需要注意的是,assign的作用是赋值而不是拼接,会修改原字符串的内容

(1)函数原型

string (1)	
string& assign (const string& str);
substring (2)	
string& assign (const string& str, size_t subpos, size_t sublen);
c-string (3)	
string& assign (const char* s);
buffer (4)	
string& assign (const char* s, size_t n);
fill (5)	
string& assign (size_t n, char c);
range (6)	
template <class InputIterator>string& assign (InputIterator first, InputIterator last);
initializer list(7)	
string& assign (initializer_list<char> il)

(2)深入解析

1.string& assign (const string& str)

从另一个字符串赋值

	string s1 = "Hello";string s2 = "henu";s1.assign(s2);cout << s1 << endl;//henucout << s2 << endl;//henu

2.string& assign (const string& str, size_t subpos, size_t sublen);
赋值部分字符串

	string s1 = "Hello";string s2 = "henu";s1.assign(s2, 0, 4);cout << s1 << endl;//henu

3.string& assign (const char* s)

从 C 风格字符串赋值

	string s2 = "henu";s2.assign("Hello World");cout << s2 << endl;//Hello World

4.string& assign (size_t n, char c)
用指定字符重复赋值

	string s1 = "Hello";s1.assign(5, 'x');cout << s1 << endl;//xxxxx

5.string& assign (const char* s, size_t n)
从字符指针赋值指定长度的字符串

	string s1 = "Hello";s1.assign("World", 5);cout << s1 << endl;//World

6.string& assign (InputIterator first, InputIterator last)

使用迭代器赋值

	string s1 = "Hello";string s2 = ", henu";s1.assign(s2.begin() + 2, s2.end());cout << s1 << endl;//henu

 7.string& assign (initializer_list<char> il)

使用初始化列表为字符串赋值

	string str = "Hello";str.assign({ 'W','o','r','l','d' });cout << str << endl;//World


assign()函数灵活多样,可以根据不同的需求从字符串、字符指针、部分字符串、重复字符等来赋值给 std::string 对象。

2.4 insert()

insert()用于在字符串中的指定位置插入字符或字符串,注意,这里是插入,插入的字符不会覆盖原来的字符。

(1)函数原型 

string (1)	    string& insert (size_t pos, const string& str);
substring (2)	string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);                        
c-string (3)	string& insert (size_t pos, const char* s);
buffer (4)	    string& insert (size_t pos, const char* s, size_t n);
fill (5)	    string& insert (size_t pos, size_t n, char c);void insert (iterator p, size_t n, char c);single character (6)	iterator insert (iterator p, char c);
range (7)	         template <class InputIterator>void insert (iterator p, InputIterator first, InputIterator last);
initializer list (8)	string& insert (const_iterator p, initializer_list<char> il)

(2)深入解析 

好的,以下将每个 insert() 的示例分开写出,确保每个示例独立运行,便于理解与复制:

1.string& insert (size_t pos, const string& str)

插入整个字符串

	string s1 = "Hello";string s2 = " henu ";s1.insert(5, s2);cout << s1 << endl;//Hello henu

2.string& insert (size_t pos, const string& str, size_t subpos, size_t sublen)

在指定位置插入另一个字符串的的子串,该子串从subpos位置开始插入sublen个字符

	string s1 = "Hello";string s2 = " henu ";s1.insert(5, s2, 0, 4);cout << s1 << endl;//Hello hen

3.string& insert (size_t pos, const char* s)

插入 C 风格字符串

	string s1 = "Hello";s1.insert(5, " World");cout << s1 << endl;//Hello World

4.string& insert (size_t pos, const char* s, size_t n)

插入字符缓冲区

	string s1 = "Hello";const char* but = " World!!!";s1.insert(5, but, 7);cout << s1 << endl;//Hello World!

5. string& insert (size_t pos, size_t n, char c);
                void insert (iterator p, size_t n, char c)

插入重复字符

	string s1 = "Hello";s1.insert(0, 5, 'x');s1.insert(s1.end(), 5, 'x');cout << s1 << endl;//xxxxxHelloxxxxx

6.iterator insert (iterator p, char c)

在迭代器位置插入单个字符

	string s1 = "Hello";s1.insert(s1.begin() + 1, 'a');cout << s1 << endl;//Haello

7. void insert (iterator p, InputIterator first, InputIterator last)

插入范围

	string s1 = "代码";string s2 = "编写";s1.insert(s1.begin() + 2, s2.begin(), s2.end());cout << s1 << endl;//代码编写

8. initializer list (8)    
 string& insert (const_iterator p, initializer_list<char> il)

通过初始化列表在字符串的指定位置插入一组字符

	string str = "Hello, ";str.insert(str.begin() + 7, { 'W','o','r','l','d' });cout << str << endl;//Hello, World

2.5 replace()

replace用于替换字符串中的某些字符或字符串。

(1)函数原型

string (1)	
string& replace (size_t pos,  size_t len,  const string& str);
string& replace (iterator i1, iterator i2, const string& str);
substring (2)	
string& replace (size_t pos,  size_t len,  const string& str,size_t subpos, size_t sublen);
c-string (3)	
string& replace (size_t pos,  size_t len,  const char* s);
string& replace (iterator i1, iterator i2, const char* s);
buffer (4)	
string& replace (size_t pos,  size_t len,  const char* s, size_t n);
string& replace (iterator i1, iterator i2, const char* s, size_t n);
fill (5)	
string& replace (size_t pos,  size_t len,  size_t n, char c);
string& replace (iterator i1, iterator i2, size_t n, char c);
range (6)	
template <class InputIterator>string& replace (iterator i1, iterator i2,InputIterator first, InputIterator last);
initializer list (7)	
string& replace (const_iterator i1, const_iterator i2, initializer_list<char> il);

(2) 深入解析

1.替换字符串

string& replace (size_t pos,  size_t len,  const string& str);
string& replace (iterator i1, iterator i2, const string& str);
	string s1 = "Hello, henu";string s2 = "World";s1.replace(7, 4, s2);//s1从索引为7的字符开始后的4个字符用s2替换cout << s1 << endl;//Hello, Worlds1.replace(s1.begin(), s1.end(), s2);cout << s1 << endl;//World

 2.替换子字符串

string& replace (size_t pos,  size_t len,  const string& str,size_t subpos, size_t sublen);
	string s1 = "Hello, henu";string s2 = "World";s1.replace(7, 4, s2, 1, 4);cout << s1 << endl;//Hello, orld

3. 替换C风格字符串

string& replace (size_t pos,  size_t len,  const char* s);
string& replace (iterator i1, iterator i2, const char* s);
	string s1 = "Hello, henu";s1.replace(7, 4, "World");cout << s1 << endl;//Hello, Worlds1.replace(s1.begin() + 7, s1.end(), "henu");cout << s1 << endl;//Hello, henu

 4.替换缓冲区的指定字符数

string& replace (size_t pos,  size_t len,  const char* s, size_t n);
string& replace (iterator i1, iterator i2, const char* s, size_t n);
	string s1 = "Hello, henu";const char* s2 = "World";s1.replace(7, 4, s2, 4);//用s2的前四个字符替换cout << s1 << endl;//Hello, Worls1.replace(s1.begin() + 7, s1.end(), "henu", 4);cout << s1 << endl;//Hello, henu

 5.用字符填充

string& replace (size_t pos,  size_t len,  size_t n, char c);
string& replace (iterator i1, iterator i2, size_t n, char c);
	string s1 = "Hello, henu";s1.replace(7, 4, 5, 'x');cout << s1 << endl;//Hello, xxxxxs1.replace(s1.begin() + 7, s1.end(), 4, 'a');cout << s1 << endl;//Hello, aaaa

 6.替换范围

template <class InputIterator>string& replace (iterator i1, iterator i2,InputIterator first, InputIterator last);
	string s1 = "Hello, henu";string s2 = "World";s1.replace(s1.begin() + 7, s1.end(), s2.begin(), s2.end());cout << s1 << endl;//Hello, World

7.用初始化列表替换

 

initializer list (7)	
string& replace (const_iterator i1, const_iterator i2, initializer_list<char> il);
	string str = "Hello, henu";str.replace(str.begin() + 7, str.end(), {'W','o','r','l','d'});cout << str << endl;//Hello, World

2.6其它成员函数

(1)push_back()

push_back用于添加字符到字符串的末尾,是字符串的长度加一

void push_back (char c);
#include <iostream>
using namespace std;int main()
{string s1 = "Hello, hen";s1.push_back('u');cout << s1 << endl;//Hello, henureturn 0;
}

(2)pop_back()

pop_back用来删除字符串最后一个字符,字符串长度减一

void pop_back();
#include <iostream>
using namespace std;int main()
{string s1 = "Hello, henua";s1.pop_back();cout << s1 << endl;//Hello, henureturn 0;
}

通过对 C++ std::string 类的访问函数和修饰函数的深入了解,我们可以更灵活、有效地处理字符串操作。在编程实践中,选择合适的函数不仅能提高代码的可读性,还能提升程序的执行效率。掌握这些字符串操作的方法,能够帮助我们在应对复杂的字符串处理需求时游刃有余。

更多string成员函数:string::find - C++ Reference (cplusplus.com)

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

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

相关文章

农牧场可视化管理:精准监测与优化运营

利用图扑可视化技术实现农牧场的实时数据监测和分析&#xff0c;优化资源配置&#xff0c;提高生产效率和可持续发展能力。

无需安装移动端的互传工具“快速分享”

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 前不久给大家介绍过 Windows 自带的 Nearby Sharing 附近分享&#xff0c;只需要在手机上安装个 App 就可以与 Windows 进行互传。而今天介绍的“快速分享”正好相反&#xff0c;是在 Windows 上安装 Goog…

tomcat安装与部署

一、基础准备 1. 节点规划 IP 主机名 节点 192.168.200.70 tomcat Tomcat 2. 环境准备 准备一台虚拟机&#xff0c;镜像为CentOS-7-x86_64&#xff0c;下载两个软件包&#xff0c;apache-tomcat-9.0.95.tar.gz&#xff1b;zrlog WAR包。 二、安装Tomcat 1.基础环境配…

【C++篇】从零实现 `list` 容器:细粒度剖析与代码实现

文章目录 从零实现 list 容器&#xff1a;细粒度剖析与代码实现前言1. list 的核心数据结构节点结构分析 2 迭代器设计与实现2.1 为什么 list 需要迭代器&#xff1f;2.2 实现一个简单的迭代器2.3 测试简单迭代器解释&#xff1a; 2.4 增加后向移动和 -> 运算符关键点&#…

多模态——基于XrayGLM的X光片诊断的多模态大模型

0.引言 近年来&#xff0c;通用领域的大型语言模型&#xff08;LLM&#xff09;&#xff0c;如ChatGPT&#xff0c;已在遵循指令和生成类似人类的响应方面取得了显著成就。这些成就不仅推动了多模态大模型研究的热潮&#xff0c;也催生了如MiniGPT-4、mPLUG-Owl、Multimodal-G…

Synchronized和 ReentrantLock有什么区别?

目录 一、java中的线程同步 二、Synchronized 使用方式 底层原理 synchronized 同步代码块的情况 synchronized 修饰方法的情况 总结 synchronized 和 volatile 有什么区别&#xff1f; 三、ReentrantLock 底层原理 使用方式 四、Synchronized和 ReentrantLock有什…

GPIO端口的使用

目录 一. 前言 二. APB2外设时钟使能寄存器 三. GPIO端口的描述 四. GPIO端口使用案例 一. 前言 基于库函数的开发方式就是使用ST官方提供的封装好的函数。而如果没有添加库函数&#xff0c;那就是基于寄存器的开发方式&#xff0c;这种方式一般不是很推荐。因为由于ST对寄存…

docker pull 超时的问题如何解决

docker不能使用&#xff0c;使用之前的阿里云镜像失败。。。 搜了各种解决方法&#xff0c;感谢B站UP主 <iframe src"//player.bilibili.com/player.html?isOutsidetrue&aid113173361331402&bvidBV1KstBeEEQR&cid25942297878&p1" scrolling"…

维护左边枚举右边

前言&#xff1a;一开始遇到这个题目的时候没啥思路&#xff0c;但是当我看到值域在1000的时候我想着直接暴力从右边枚举不就行了吗&#xff0c;时间复杂度刚刚好&#xff0c;试一下就过了 正解应该是啥呢&#xff0c;其实也是维护一遍&#xff0c;运行另外一边 O ( n ) O(n)…

所有测试人,下半年的新方向(大模型),赢麻了!!!

现在做测试&#xff0c;真的挺累的。 现在测试越来越难做&#xff0c;晋升困难&#xff0c;工资迟迟不涨……公司裁员&#xff0c;测试首当其冲&#xff01;&#xff01; 做测试几年了&#xff0c;还没升职&#xff0c;就先到了“职业天花板”。 想凭工作几年积累的经验&…

Linux进程:fork函数深度剖析

目录 一、初识fork函数 二、fork函数的返回值 三、fork之后&#xff0c;父子进程谁先运行 四、fork的使用示例 一、初识fork函数 在linux中fork函数时非常重要的函数&#xff0c;它从已存在进程中创建一个新进程。新进程为子进程&#xff0c;而原进程为父进程。 进程调用fork…

Apache POI快速入门

介绍 Apache POl是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是&#xff0c;我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。 一般情况下&#xff0c;POI都是用于操作 Excel 文件。 Apache POI的主要组件包括&#xff1a; HS…

监控易监测对象及指标之:全面监控Sybase_New数据库

随着企业数据量的不断增长和业务的复杂化&#xff0c;数据库的稳定性和性能成为了保障业务连续性的关键因素。Sybase_New数据库作为众多企业选择的数据管理解决方案&#xff0c;其稳定性和性能对于企业的运营至关重要。 为了确保Sybase_New数据库的稳定运行和高效性能&#xff…

单体到微服务架构服务演化过程

架构服务化 聊聊从单体到微服务架构服务演化过程 单体分层架构 在 Web 应用程序发展的早期&#xff0c;大部分工程是将所有的服务端功能模块打包到单个巨石型&#xff08;Monolith&#xff09;应用中&#xff0c;譬如很多企业的 Java 应用程序打包为 war 包&#xff0c;最终会形…

基于vue框架的刺梨销售管理系统pgl49(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,刺梨分类,刺梨产品,刺梨新闻 开题报告内容 基于Vue框架的刺梨销售管理系统开题报告 一、引言 随着现代农业的快速发展和消费者对健康食品需求的日益增长&#xff0c;刺梨这一富含营养价值的水果逐渐受到市场的青睐。然而&#x…

学习Python的难点分析

一、语法灵活性带来的困惑 缩进规则 Python使用缩进来表示代码块&#xff0c;而不是像其他编程语言&#xff08;如C或Java&#xff09;使用大括号。这虽然使代码看起来简洁&#xff0c;但对于初学者来说可能会造成困扰。例如&#xff1a; if True:print("This is insid…

网站建设中,营销型网站与普通网站有什么区别

营销型网站与普通网站在建站目的、交互设计以及结构优化等方面存在区别。以下是具体分析&#xff1a; 建站目的 营销型网站&#xff1a;以销售和转化为主要目标&#xff0c;通过专业的市场分析和策划来吸引潜在客户&#xff0c;并促使其采取购买行动。普通网站&#xff1a;通常…

零基础学Servlet

零基础学Servlet 一。介绍&#xff1a; servlet是一种比较古老的编写网站的方式&#xff0c;在2010年之前比较流行&#xff0c;在此之后&#xff0c;有一堆大佬创造了Spring&#xff08;一种框架&#xff09;&#xff0c;Spring是针对Servlet进行进一步封装&#xff0c;从而让…

OpenSource - 开源日历库tui.calendar

文章目录 强大且灵活的开源日历库推荐&#xff1a;tui.calendar多视图支持&#xff1a; Monthly, Weekly, Daily and Various View Types支持拖拽: Dragging and Resizing a Schedule事件管理支持多语言集成与扩展高度定制化其他功能地址总结 强大且灵活的开源日历库推荐&#…