Bootstrap

跟我从零开始学STL(STL代码基础01)---string容器

引言

  小伙伴们大家好,又到了新的篇章了,感谢大家的支持!今天我们要学一个新的篇章,STL。在编程领域,STL(Standard Template Library,标准模板库)是C++语言中非常重要的一部分。它为我们提供了大量常用数据结构和算法的模板实现,极大地提高了编程效率。

  今天,小杨将带领大家从零开始学习STL,首先为大家介绍的是string容器。string容器在日常生活中有着广泛的应用,如文本处理、字符串操作等。希望通过本文,能让您对string容器有一个初步的了解,为后续学习打下坚实基础。好了,废话不多说,小伙伴们跟着小杨同学一起,让我们开始吧!

  冲冲冲!!!!冲呀!!!

STL介绍

  STL(standard template library),叫做标准模板库,可以帮我们建立一套数据结构和算法的标准,提高复用性。STL中大量使用了模板技术。

STL中有三大部分:
容器:container,存放数据的地方,STL中实现了很多种数据结构的容器。
算法:algorithm,操作数据的方法,解决问题的方法。
迭代器:iterator,迭代器就是操作容器中数据的指针,它是对原始指针的封装,本质上是一个类模板,同时重载了指针的各种运算符。

String容器

1.概念

  string是STL中的一种容器,是一种特殊的容器,它的元素只能char类型,本质上是个类。
string和char*的区别:

  • 1.har*是指针,string是一个类,类内部封装了char*
  • 2.string管理char*所分配的内存,不用担心越界的问题
  • 3.string类内部提供了很多方法供我们使用string类提供的函数

2.string构造

  • string();//创建一个空的字符串
  • string(const char* s);//使用字符串s来初始化string对象
  • string(const string& str);//使用string对象str来初始化string对象
  • string(int n,char c);//使用n个字符c来初始化string对象
  • 代码示例:
void test01()
{
	string s1;//无参构造
	cout << "s1=" << s1 << endl;

	const char* str = "hello world";
	string s2(str);
	cout << "s2=" << s2 << endl;

	string s3(s2);
	cout << "s3=" << s3 << endl;

	string s4(10, 'a');//10个a组成的字符串
	cout << "s4=" << s4 << endl;
}

3.string赋值操作

  • 重载赋值运算符:
    • string& operator=(const char* s);//字符串常量赋值
    • string& operator=(const string& s);//string对象的赋值
    • string& operator=(char c);//单个字符赋值
  • 赋值函数assign():
    • string& assign(const char* s);//字符串常量赋值
    • string& assign(const char* s,int n);//将字符串s的前n个字符赋值给string
    • string& assign(const string& s);//使用string对象完成赋值
    • string& assign(int n,char c);//使用n个字符c来赋值
  • 代码示例:
void test02()
{
	//赋值运算符
	string str1;
	str1 = "hello world";
	cout << "str1=" << str1 << endl;
	string str2;
	str2 = str1;
	cout << "str2=" << str2 << endl;
	string str3;
	str3 = 'A';
	cout << "str3=" << str3 << endl;

	//赋值函数assign
	string str4;
	str4.assign("hello C++");
	cout << "str4=" << str4 << endl;
	string str5;
	str5.assign("hello C++", 5);
	cout << "str5=" << str5 << endl;
	string str6;
	str6.assign(str5);
	cout << "str6=" << str6 << endl;
	string str7;
	str7.assign(5, 'x');
	cout << "str7=" << str7 << endl;
}

4.string字符串拼接

  • 在字符串末尾拼接字符串
    重载运算符+=:
    string& operator+=(const char* s);
    string& operator+=(const string& str);
    string& operator+=(char c);

  • append函数:
    string& append(const char* s);
    string& append(const char* s,int n);//把字符串s的前n个字符拼接到string字符串

  • 代码示例:

void test03()
{
	//运算符+=
	string str1 = "我";
	str1 += "爱玩游戏";
	cout << "str1=" << str1 << endl;
	str1 += ':';
	cout << "str1=" << str1 << endl;
	string str2 = "LOL DNF";
	str1 += str2;
	cout << "str1=" << str1 << endl;

	//拼接函数append
	string str3 = "I";
	str3.append(" like ");
	str3.append("play game such as ", 10);
	str3.append(str2, 4, 3);
	cout << "str3=" << str3 << endl;
}

5.string查找和替换

  查找:查找指定的字符串是否存在,找到会返回对应的位置,找不到返回-1(-1即string::npos),查找是常函数

  • 从左往右查找:find
    int find(const string& str,int pos=0) const;//查找字符串str,返回它第一次出现的位置,从pos位置开始找,pos默认值是0,即开头位置
    int find(const char* s,int pos=0) const;
    int find(const char* s,int pos=0,int n) const;//从pos位置开始查找字符串s的前n个字符第一次出现的位置
    int find(char c,int pos=0) const;//从pos位置查找字符c第一次出现的位置

  • 从右往左查找:rfind
    int rfind(const string& str,int pos=npos) const;//从右往左查找str最后一次出现的位置,从pos位置开始查找,pos默认值是npos,npos是string类的静态常量,表示字符串结束
    int rfind(const char* s,int pos=npos) const;
    int rfind(const string& s,int pos=npos,int n) const;//从pos开始从右往左查找s字符串的前n个字符最后一次出现的位置
    int rfind(char c,int pos=npos) const;

  • 替换:在指定的位置替换字符串
    string& replace(int pos,int n,const string& str);//从pos位置开始的n个字符被替换为字符串str
    string& replace(int pos,int n,const char* s);//从pos位置开始的n个字符被替换为字符串s

  • 代码示例:

void test04()
{
	//从左往右找
	string str1 = "abcdefgde";
	int pos=str1.find("de");
	cout << "第一个de的位置:" << pos << endl;//3
	pos = str1.find("de", 5);
	cout << "第二个de的位置:" << pos << endl;//7
	pos = str1.find("fgde",0,2);
	cout << "fg的位置:" << pos << endl;//5
	pos = str1.find('f');
	cout << "f的位置:" << pos << endl;//5

	//从右往左找
	cout << "从右往左找:" << endl;
	pos = str1.rfind("de");
	cout << "第一个de的位置:" << pos << endl;//7
	pos = str1.rfind("de", 5);
	cout << "第二个de的位置:" << pos << endl;//3
	pos = str1.rfind("fgde",-1,2);
	cout << "fg的位置:" << pos << endl;//5
	pos = str1.rfind('d');
	cout << "d的位置:" << pos << endl;//7

	//替换
	str1.replace(1,3,"888");
	cout << "被替换后,str1=" << str1 << endl;
}

6.string字符串比较

  比较方式:是按照字符串中每个字符的ASCII码逐个比较,如果比较出大小就返回结果,如果直到结束都没有比较出大小,证明两个字符串相等。
  所以,比较方法主要的作用就是判断两个字符串是否相等,至于大小没实际意义。
返回值:相等的时候返回0,大于的时候返回1,小于返回-1

int compare(const string& str) const;//当前字符串跟字符串str比较
int compare(const char* s) const;//当前字符串跟字符串s比较
  • 代码示例:
void test05()
{
	string s1 = "hello";
	string s2 = "hello";
	string s3 = "Hello";
	cout << s1.compare(s2) << endl;//0
	cout << s1.compare(s3) << endl;//1
}

7.string插入和删除

  • 插入:
    string& insert(int pos,const char* s);//在pos位置插入字符串s
    string& insert(int pos,const string& str);//在pos位置插入字符串str
    string& insert(int pos,int n,char c);//在pos位置插入n个字符c

  • 删除:
    string& erase(int pos,int n);//删除从pos开始的n个字符

  • 代码示例:

void test06()
{
	string str = "hello world";
	str.insert(1, "888");
	cout << "str=" << str << endl;
	str.insert(1, 3, 'a');
	cout << "str=" << str << endl;

	str.erase(1, 6);
	cout << "str=" << str << endl;
}

8.string截取子字符串

  从字符串中截取想要的子字符串
string& substr(int pos,int n=npos) const;//返回从pos开始的n个字符组成的子字符串,n的默认值是npos,代表最后

9.获取长度

  size():获取字符串的长度,也就是字符数

  • 代码示例:

void test07()
{
	string str = "abcdefg";
	string subString1 = str.substr(1, 3);
	cout << subString1 << endl;
	string subString2 = str.substr(3);//第二个参数取默认值npos,代表截取到最后
	cout << subString2 << endl;
	cout << "str的长度:" << str.size() << endl;
}

10.string元素的存取

string中单个字符存取可以通过下面两个方式:

  • char& operator[](int n);//运算符重载,通过[index]取值,index代表下标
  • char& at(int n);//通过at成员函数取值,n也是下标
  • 代码示例:
void test08()
{
	//取,查询
	string str = "hello world";
	cout << str[6] << endl;//w
	cout << str << endl;
	//逐个输出每个字符
	for (int i = 0; i < str.size(); i++)
	{
		cout << str[i];
	}
	cout << endl;
	cout << str.at(6)<<endl;

	//存,修改
	str[0] = 'H';
	str.at(6) = 'W';
	cout << str << endl;
}

小练习:

  • 练习1:完成string类型字符串和char*类型字符串之间的相互转换
  • 代码注解:
void test09()
{
	//char*转string,构造函数即可完成
	const char* s1 = "welcome to china!";
	string s2(s1);
	cout << s2 << endl;

	//string转char*,string是对char*的封装,而字符串用的是首字符的地址来表示,
	//所以只需要拿到string中首个字符的地址,就是原始字符串的表示方式
	string s3 = "hello world";
	char* s= &s3[0];
	cout << s << endl;

	//还可以利用c_str()函数完成转换
	string s4 = "let it be";
	const char* c = s4.c_str();
	cout << c << endl;
}
  • 练习2:写一个函数,将一个string邮箱地址的用户名取出来并返回,比如[email protected],返回hello
  • 代码注解:
string get_email_username(string& s)
{
	//思路:用户名即首字符到@符之间的字符,查找@,找到@的下标位置,然后根据这个位置截取
	int pos = s.find('@');
	string username = s.substr(0,pos);
	return username;
}
void test10()
{
	string email_1 = "[email protected]";
	string email_2 = "[email protected]";
	cout << get_email_username(email_1) << endl;
	cout << get_email_username(email_2) << endl;
}
  • 练习3.实现string字符串的大小写转换
  • 代码注解:
//思路:利用ASCII码将某个英文字符转换成它对应的大小写,大小写字母的ASCII码只差是32
void upper_or_lower(string& str)
{
	for (int i = 0; i < str.size(); i++)
	{
		//区分大小写
		if (str[i]>=65 and str[i]<=90)//大写,就转小写,ASCII码+32
		{
			str[i] = str[i] + 32;
		}
		else//小写,就转大写,-32
		{
			str[i] = str[i] - 32;
		}
	}
}
//除了ASCII码,还可以通过两个函数完成单个字符的大小写转换:tolower()和toupper()
void upper_or_lower_def(string& str)
{
	for (int i = 0; i < str.size(); i++)
	{
		//区分大小写
		if (str[i] >= 65 and str[i] <= 90)//大写,就转小写,ASCII码+32
		{
			str[i] = tolower(str[i]);
		}
		else//小写,就转大写,-32
		{
			str[i] = toupper(str[i]);
		}
	}
}
void test11()
{
	string s1 = "hello";
	string s2 = "WORLD";
	//upper_or_lower(s1);
	//upper_or_lower(s2);
	upper_or_lower_def(s1);
	upper_or_lower_def(s2);
	cout << s1 << endl;
	cout << s2 << endl;
}

结语

  经过本文的介绍和练习,相信小伙伴们对string容器已经有了一定的认识。掌握string容器的基本用法,能让我们在处理字符串问题时更加得心应手。当然,STL的内容非常丰富,string容器只是其中的一小部分。

  在今后的学习中,我们将继续探讨其他容器和算法,逐步揭开STL的神秘面纱。希望大家能跟着我的步伐,一起探索C++编程的乐趣。如有疑问,欢迎在评论区留言交流,我们共同进步!谢谢阅读,下期再见!

  学到这里的同学给自己鼓掌👏👏👏👏👏👏👏👏👏

;