引入

STL(Standard Template Library)是 C++ 标准库的核心组成部分,提供了一系列通用的模板类和函数,包括容器、算法、迭代器和函数对象。STL 的设计目标是提高代码复用性和开发效率,其核心思想是将数据结构和算法分离,通过迭代器作为桥梁实现泛型编程。

从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map一大堆,STL也是算法和其他一些组件的集合。比如说中sort函数、中string类。

基本组成

STL从广义上讲分为三类:

  1. 容器(Container),是一种数据结构,如list,vector,和deques ,以模板类的方法提供。为了访问容器中的数据,可以使用由容器类输出的迭代器
  2. 迭代器(Iterator),提供了访问容器中对象的方法。例如,可以使用一对迭代器指定list或vector中的一定范围的对象。迭代器就如同一个指针
    事实上,C++的指针也是一种迭代器。但是,迭代器也可以是那些定义了operator*()以及其他类似于指针的操作符地方法的类对象;
  3. 算法(Algorithm),是用来操作容器中的数据的模板函数。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象,函数本身与他们操作的数据的结构和类型无关,因此他们可以在从简单数组到高度复杂容器的任何数据结构上使用;

string容器

用字符数组存放字符串容易数组越界且难以察觉。因此,C++ 标准模板库设计了 string 数据类型,专门用于字符串处理
要使用 string 对象,须包含头文件
在用 C++ 编程时,要优先考虑用 string 对象来处理字符串,因为其用法比字符数组更简单,而且不容易出错。

初始化

string对象的初始化和普通类型变量的初始化基本相同,只是string作为类,还有类的一些特性(使用构造函数初始化),所以初始化方式有很多,如下(7):

string s1;      //默认初始化
string s2(s1);  //s2是s1的副本(复制过去)
string s3 = s1; //相当于s3(s1),s3是s1的副本
string s4("hello");  //初始化自定义内容
string s5 = "hello"; //等价于上行代码
string s6(1, 'a');   //s6由连续n(此时为1)个字符a组成的字符串
//生成一个临时的string再用临时的string类初始化
string s7 = string("hello");
string s8(string("hello"));
输入输出

== cin遇到空格就终止导致弱输入内容如“hello Amy”,只能读取空格前的内容“hello’。
== getline
读取整行,如读取字符串s1: getline(cin,s1);

比较大小

string可以直接使用 > ,< ,== 等进行比较(按照ASCLL码的大小进行比较多,先比较首个字符,依次往后。若第一个字符不一样,以第一个的比较就能得出比较结果,若相同就继续比下一位,比出结果后就不用再看后面的内容了。)

string s9 = "akl", s10 = "abo";

	int main() {
		if (s9 > s10) {
			cout << "s9>s10" << endl;
		}
		else if (s9 < s10) {
			cout << "s9<s10" << endl;
		}
		else cout << "s9==s10" << endl;
		return 0;
	}
链接

string可以使用== +==来直接链接:

string s9 = "akl", s10 = "abo";
string s11 = s9 + s10;

	int main() {
			cout << "s9+s10=" <<s11<< endl;
		return 0;
	}
获取字符
  1. .使用C++11新特性的for
int main() {
string s1 = "aaacccvvv"; 
for (auto c : s1) {
	cout << c <<" ";
}
		return 0;
	}
  1. 使用运算符[]+size()函数
int main() {
string s1 = "aaacccvvv"; 
for (int i = 0; i < s1.size();i++) {
	cout << s1[i] <<" ";
}
		return 0;
	}
  1. 使用迭代器
int main() {
string s1 = "hello word"; 
for (auto i = s1.begin(); i != s1.end();i++) {
	cout << *i <<" ";
}
		return 0;
	}
拷贝对象

string s(s1,pos); //拷贝s1从下标pos到结尾的内容;
string s(s1,pos,len); //拷贝s1从下标pos开始的len个字符(往后数)。

pos>s1.size()时为未定义行为;
pos=s1.size()时拷贝一个空字符(因为后面没内容)。
在这里插入图片描述
未定义行为或空字符都不输出内容。

int main() {
string s1 = "value"; 
string s2(s1, 1);    //拷贝s1的下标1及之后内容
cout << "s2=" << s2 << endl;
string s3(s1, 2, 4); //拷贝s1从下标2及之后连续4个字符
cout << "s3=" << s3 << endl;
string s4(s1, 1, 8); //对应位置上没内容就不拷贝
cout << "s4=" << s4 << endl;
string s5(s1, 5, 9); //pos=size时为空字符
cout <<"s5="<< s5 << endl;
		return 0;
	}
substr函数

s.substr(pos,n);
返回一个string对象,返回的对象包含s从pos下标开始的n个字符。pos和n均为可选参数。
pos默认为下标0;n默认为s.size()-pos

int main() {
	string s("value");
	string s1 = s.substr();  //默认pos=0,n=s.size()-pos
	string s2 = s.substr(2); //仅输入一个数默认为pos,且n=s.size()-pos
	string s3 = s.substr(1, 3); //pos=1,n=3
	string s4 = s.substr(1, 7); //s4为"alue",大小为4,多余位为空
	string s5 = s.substr(7, 8); //pos>size时报错
	cout << s1 << " " << s2 << " " << s3 << " "<<s4;
		return 0;
	}
insert函数
  1. iterator insert( iterator pos, CharT ch ) //在位置pos上加上‘ch’
  2. void insert( iterator pos, size_type count, CharT ch ) //在pos上加count个’ch’
  3. void insert( iterator pos, InputIt first, InputIt last ) //在pos上加 [s.begin(), ++s.begin()) 的内容
  4. 插入初始化列表
int main() {
	string s("value");
	s.insert(s.begin(),'s');  //执行结果“svalue”
	s.insert(s.begin(),1,'s'); //执行结果“ssvalue”
	s.insert(s.end(), { '1','2' });//执行结果“ssvalue12”
	s.insert(s.begin(), s.begin(), ++s.begin());
	cout << s << endl;  //执行结果“sssvalue12”
	
		return 0;
	}

3中加的内容范围为 [s.begin(), ++s.begin()) :
包含:第一个字符 ‘s’
不包含:第二个字符 ‘s’
所以实际上只插入了一个字符 ‘s’

erase函数

basic_string & erase(size_type pos=0, size_type n=npos)

删除s从pos下标开始的n个字符,并返回删除后的s。当pos > s.size()时报错。

iterator erase(const_iterator position)

删除s迭代器position位置的字符,并返回下一个字符的迭代器。

iterator erase(const_iterator first, const_iterator last)

删除s迭代器[first,last)区间的字符,并返回last字符的迭代器

int main() {
	string s("value");
	string s1("value");
	string s2("value");
	string s3("value");

	s.erase(0, 2); //lue
	s1.erase(s1.begin()); //alue
	s2.erase(); //为空
	s3.erase(s3.begin(), ++s3.begin());
	//删除从 begin() 到 ++begin() 范围内的字符,范围是左闭右开的
	//所以只删除了‘v’,输出"alue"
	cout << s<<" " << s1<<" " << s2 <<" " << s3;
	return 0;
	}
append函数

append是在string对象的末尾进行插入操作。这一点使用+运算符也能实现。

int main() {
	string s("value");
	s.append("value"); //执行完s="valuevalue";
	cout << s;
	return 0;
	}
replace函数
int main() {
	string s = "i very love China!";
	const char* cp1 = "truly";
	const char* cp2 = "truly!!!";

	string str1 = "really";

	//从s下标2开始删除4个元素后在下标2位置上插入cp1
	s.replace(2, 4, cp1); 
	cout << s << endl; //输出 "i truly love China!"
	//从s下标2开始删除5个元素后在下标2位置上插入cp2的前5个字符
	s.replace(2, 5, cp2, 5);
	cout << s << endl; //输出 "i truly love China!"
	//从s下标2开始删除5个元素后在下标2位置上插入str1的下标0开始的6个字符
	s.replace(2, 5, str1, 0, 6); 
	cout << s << endl; //输出"i really love China!"
	//从s下标2开始删除6个元素后在下标2位置上插入4个‘*’
	s.replace(2, 6, 4, '*');
	cout << s << endl; //输出"i **** love China!"
	return 0;
	}

练习

输入一串带有标点符号的字符串,去除字符串中的标点符号。
判断字符是否是标点符号用ispunct();

int main() {
	string s;
	cin >> s;
	//auto:自动类型推断,让编译器自动推断变量类型
	//each:循环变量名,在每次迭代中代表字符串中的一个字符
	for (auto each : s) { 
		if (!ispunct(each)) { //判断不是符号时输出
			cout << each;
		}
	}
	return 0;
	}

更多推荐