[C++初阶]string类

1.为什么要学习string****类

1.1 C语言中的字符串

C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP(面向对象)的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
在OJ中,有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本都使用string类,很少有人去使用C库中的字符串操作函数。

2.标准库中的string****类

2.1 string****类的了解

string类的文档介绍

  1. 字符串是表示字符序列的类
  2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
  3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信息,请参阅basic_string)。
  4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
  1. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
    总结:
  2. string是表示字符串的字符串类
  3. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作
  4. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
  5. 不能操作多字节或者变长字符的序列。
    使用string类时,必须包含#include头文件以及using namespace std;

2.2 string****类的常用接口说明

我们看string类的文档可以发现

有以下几种接口:

内容选自:string::string - C++ Reference (cplusplus.com)

2.2.1 string() ---- 无参构造函数

cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s;
	cout << s <<endl;

	return 0;
}

运行结果:

2.2.2 string (const string& str)-----复制构造函数

代码:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s("Iamchineseprson");
	string s1(s);
	cout << s << endl;
	cout << s1 << endl;

	return 0;
}

运行结果:

2.2.3 string(const string& str, size_t pos, size_t len = npos);----复制从字符位置 pos 开始并跨越 len 字符的 str 部分(如果任一 str 太短或 lenstring::npos,则复制 str 的末尾)

代码示例:

运行结果:

2.2.4 string(const char*)---- 用char*构造函数

cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("Iamchineseperson");
	cout << s << endl;

	return 0;
}

2.3 string对象的容量操作

2.3.1size函数

代码示例:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s("Iamchineseprson");

	cout << s.size() << endl;

	return 0;
}

运行结果:

2.3.2 length函数

返回字符串有效字符长度 size() 与 length() 方法底层实现原理完全相同, 引入 size() 的原因是为了与其他容器的接口保持一致, 一般情况下基本都是用 size()。

代码示例:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
    string s("Iamchineseprson");

	cout << s.length() << endl;

	return 0;
}

2.3.3 capacity函数

代码示例:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s("Iamchineseprson");

	cout << s.capacity() << endl;

	return 0;
}

运行结果:

2.3.4 empty函数

检测字符串释放为空串,是返回true,否则返回false

代码示例:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s1("Iamchineseprson");
	string s2;
	cout << s1.empty() << endl;
	cout << s2.empty() << endl;

	return 0;
}

运行结果:

2.3.5 clear函数

clear()清空有效字符

clear()只是将string中有效字符清空,不改变底层空间大小。

代码示例:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
    string s("Iamchineseprson");

	cout << s.length() << endl;

	s.clear();

	cout << s.length() << endl;

	return 0;
}

运行结果:

2.3.6 reserve函数

作用:为字符串预留空间

写法:reserve(size_t res_arg=0):

特点:为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量小。

代码示例:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s("Iamchineseprson");
	cout << s.capacity() << endl;
	s.reserve(30);
	cout << s.capacity() << endl;
	return 0;
}

运行结果:

2.3.7 resize函数

resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用 '\0' 来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。
注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s("Iamchineseprson");
	cout << s << endl;
	s.resize(30,'L');
	cout << s << endl;
	return 0;
}

运行结果:

2.4 string对象的访问及遍历接口

cpp 复制代码
//迭代器
string::iterator being();//返回第一个位置的迭代器
string::iterator end();//返回结束位置下一个位置的迭代器
reverse_iterator rbeign();//返回结束位置的迭代器
reverse_iterator rend();//返回开始的前一个位置的迭代器

//at访问位置的值
char& at (size_t pos);	//返回pos位置的值
const char& at (size_t pos) const;	//返回const修饰的pos位置的位置的值

//重载 [] 
char& operator[] (size_t pos);
const char& operator[] (size_t pos) const; 

2.4.1 operator[]

作用:返回pos位置的字符,const string对象调用

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s("Iamchineseprson");
	for (int i = 0; i < s.size(); i++)
	{
		printf("[%d] : %c\n", i, s[i]);
	}
	cout << endl;
	return 0;
}

运行结果:

2.4.2 迭代器 beginend

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s("Iamchineseprson");
	string::iterator it = s.begin();
	while (it < s.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
	return 0;
}

运行结果:

2.4.3 迭代器 rbeginrend

cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("iamchineseprson");

	string::reverse_iterator it = s.rbegin();
	while (it != s.rend())
	{
		cout << *it << ' ';
		it++;
	}

	cout << endl;

	return 0;
}

运行结果:

2.4.4 at

cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("iamchineseprson");
	for (int i = 0; i < s.size(); i++)
	{
		cout << s.at(i) << " ";
	}
	cout << endl;
	cout << endl;

	return 0;
}

运行结果:

2.4.5 范围for

这里是遍历,自然我们也能用前面学习的范围for

cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("iamchineseperson");

	for (const char ch : s)
	{
		cout << ch << ' ';
	}

	cout << endl;

	return 0;
}

运行结果:

但这里ch的类型是char,我们可能吃不准,所以,很多时候我们都会选择用auto类型

cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("iamchineseperson");

	for (auto ch : s)
	{
		cout << ch << ' ';
	}

	cout << endl;

	return 0;
}

2.5 string的增删查改

1.增

1.连接

(1)函数原型:

cpp 复制代码
//重载 +=
string& operator+= (const string& str);	//在结尾处连接字符串str
string& operator+= (const char* s);		//在结尾处连接字符串s
string& operator+= (char c);			//在结尾处连接字符c

//append 在字符串结尾连接	
string& append (const string& str);	//在结尾处连接字符串str
string& append (const char* s);	//在结尾处连接字符串s
//连接从迭代器first 到 last 这个区间到结尾 左闭右开
template <class InputIterator>	
string& append (InputIterator first, InputIterator last);
cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("iamchineseperson");

	s += '1';
	cout << s << endl;

	s += "666666";
	cout << s << endl;

	string ss("2333");

	s += ss;
	cout << s << endl;
	return 0;
}

运行结果:

2.尾插

push_back 函数

cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("iamchineseprson");

	s.push_back('1');
	cout << s << endl;

	s.push_back('2');
	cout << s << endl;

	s.push_back('3');
	cout << s << endl;

	return 0;
}

运行结果:

3.append函数
cpp 复制代码
#include <iostream>
#include <string>

using namespace std;
int main()
{
	string s("iamchineseperson");

	// 追加n个字符
	s.append(1, '1');
	cout << s << endl;

	// 追加一个字符串
	s.append("12345");
	cout << s << endl;

	// 追加一个字符串的前n个
	s.append("12345678", 3);

	cout << s << endl;
	return 0;
}

运行结果:

4.insert 函数

cpp 复制代码
string& insert (size_t pos, const string& str);
//insert函数能够在字符串任意位置插入一个string容器内的字符串

string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);
//insert函数能够在字符串任意位置插入一个string对象内的字符串的一段字符串

string& insert (size_t pos, const char* s);
//insert函数能够在字符串一段字符串

string& insert (size_t pos, const char* s, size_t n);
//insert 函数还能够在字符串任意位置插入字符串的前 n 个

string& insert (size_t pos, size_t n, char c);
//insert 函数还能够在字符串任意位置插入n个字符
cpp 复制代码
//插入
int main()
{
	string s1("iamchineseperson");
	string s2("hello");

	//在pos位置插入string
	s1.insert(0, s2);
	cout << s1 << endl;

	//在pos位置插入char*
	s1.insert(0, "hehe");
	cout << s1 << endl;

	// 在最后插入string的一部分
	s1.insert(s1.size(), s2, 0, 2);
	cout << s1 << endl;


	// 在第一个位置插入string
	s1.insert(0, "sadasdxzczasd");
	cout << s1 << endl;

	return 0;
}

至于其他情况这里我就不多展示了。

2.删

cpp 复制代码
//清空
clear()

//尾删
pop_back();

//erase 删除
//删除从pos位置开始删除len个
string& erase (size_t pos = 0, size_t len = npos);
//删除迭代器p位置	
iterator erase (iterator p);
//删除迭代器区间左闭右开
iterator erase (iterator first, iterator last);
1. erase 函数
cpp 复制代码
string& erase (size_t pos = 0, size_t len = npos);

erase 函数能够删除第 n 个位置后面长度为 len 的字符串

如果没有传 len 或是 第 n 个位置后面的字符数小于 len ,则n后面的字符全部删除

cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("iamaperson");

	s.erase(3, 2);
	cout << s << endl;

	s.erase(1);
	cout << s << endl;

	return 0;
}

运行结果:

2.尾删

pop_back()

cpp 复制代码
#include <iostream>
#include <string>

int main ()
{
  std::string str ("hello world!");
  str.pop_back();
  std::cout << str << '\n';
  return 0;
}

运行结果:

3.clear()
cpp 复制代码
// string::clear
#include <iostream>
#include <string>

int main ()
{
  char c;
  std::string str;
  std::cout << "Please type some lines of text. Enter a dot (.) to finish:\n";
  do {
    c = std::cin.get();
    str += c;
    if (c=='\n')
    {
       std::cout << str;
       str.clear();
    }
  } while (c!='.');
  return 0;
}

该程序重复用户引入的每一行,直到一行包含一个点 ('.')。每个换行符 ('\n') 都会触发行的重复和当前字符串内容的清除。

这里我就不运行了

3.查

cpp 复制代码
//find从pos位置向后查找  找到返回下标位置,找不到返回npos
//查找字符串str
size_t find (const string& str, size_t pos = 0) const;
//查找字符串s
size_t find (const char* s, size_t pos = 0) const;
//查找字符c
size_t find (char c, size_t pos = 0) const;

//rfind 从pos位置向前找 找到返回下标位置,找不到返回npos
size_t rfind (const string& str, size_t pos = npos) const;
size_t rfind (const char* s, size_t pos = npos) const;	
size_t rfind (char c, size_t pos = npos) const;
1.find()
cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("i am  a studentt");
	string str("student");

	// 查找 str --> 找得到
	int pos = s.find(str, 0);
	cout << "str pos : " << pos << endl;

	// 查找字符串 --> 找得到
	pos = s.find("a", 0);
	cout << "a pos : " << pos << endl;

	// 查找字符串 --> 找不到
	pos = s.find("A", 0);
	cout << "A pos : " << pos << endl;

	// 查找字符 --> 找得到
	pos = s.find('s', 0);
	cout << "s pos : " << pos << endl;

	// 查找字符 --> 找不到
	pos = s.find('I', 0);
	cout << "I pos : " << pos << endl;

	return 0;
}

运行结果:

2.rfind()
cpp 复制代码
//rfind 从pos位置向前找 找到返回下标位置,找不到返回npos
size_t rfind (const string& str, size_t pos = npos) const;
size_t rfind (const char* s, size_t pos = npos) const;	
size_t rfind (char c, size_t pos = npos) const;
cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("i am  a studentt");
	string str("student");

	// 查找 str --> 找得到
	int pos = s.rfind(str);
	cout << "str pos : " << pos << endl;

	// 查找字符串 --> 找得到
	pos = s.rfind("a");
	cout << "a pos : " << pos << endl;

	// 查找字符串 --> 找不到
	pos = s.rfind("a", 0);
	cout << "A pos : " << pos << endl;

	// 查找字符 --> 找得到
	pos = s.rfind('s',8);
	cout << "s pos : " << pos << endl;

	// 查找字符 --> 找不到
	pos = s.rfind('s', 5);
	cout << "I pos : " << pos << endl;

	return 0;
}

4.改

cpp 复制代码
//assign 全部替换
//用字符串str替换原来的内容
string& assign (const string& str);
//用字符串s替换原来的内容
string& assign (const char* s);	
//迭代器first到迭代器last这个区间替换原来的内容 左闭右开
template <class InputIterator>
   string& assign (InputIterator first, InputIterator last);

//replace替换一部分
//将pos到len位置替换成str
string& replace (size_t pos,  size_t len,  const string& str);
//将迭代器i1到i2替换成str
string& replace (iterator i1, iterator i2, const string& str);
 //将pos到len位置替换成s
string& replace (size_t pos,  size_t len,  const char* s);
//将迭代器i1到i2替换成s 左闭右开
string& replace (iterator i1, iterator i2, const char* s);
1.assign()
cpp 复制代码
int main()
{
	string s1("i am  a studentt");
	string s2("student");

	//修改stirng
	s1.assign(s2);
	cout << s1 << endl;
	//修改char *
	s1.assign("he");
	cout << s1 << endl;

	//迭代器
	s1.assign(s2.begin(), s2.end());
	cout << s1 << endl;

	return 0;
}

运行结果:

2.replace()

cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s1("i am  a student");
	string s2("person");
	//将pos到len位置替换string
	s1.replace(8, 15, s2);
	cout << s1 << endl;

	//将pos到len位置替换char*
	s1.replace(0, 0, "asdsd");
	cout << s1 << endl;
	return 0;
}

运行结果:

2.6 一些小东西的介绍

1. npos

npos的值通常是一个很大的正数,等于-1(当作为无符号数解释时或等于string::size_type的最大可能值。

2.c_str 函数

作用:返回C格式字符串

C++中,printf 是一个C语言函数,它不支持直接打印std::string类型的内容。这是因为 printf 是一个可变参数函数,而 std::string 不是基本数据类型,因此需要转换为C风格字符串才能由 printf 输出。

cpp 复制代码
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s("Hello world");

	printf("%s\n", s);
	printf("%s\n", s.c_str());

	return 0;
}

运行结果:

3.substr()

cpp 复制代码
string substr (size_t pos = 0, size_t len = npos) const;

在字符串中从第pos个位置开始截取len个字符返回

cpp 复制代码
// string::substr
#include <iostream>
#include <string>

int main ()
{
  std::string str="We think in generalities, but we live in details.";
                                           // (quoting Alfred N. Whitehead)

  std::string str2 = str.substr (3,5);     // "think"

  std::size_t pos = str.find("live");      // position of "live" in str

  std::string str3 = str.substr (pos);     // get from "live" to the end

  std::cout << str2 << ' ' << str3 << '\n';

  return 0;
}
相关推荐
明月看潮生8 分钟前
青少年编程与数学 02-003 Go语言网络编程 15课题、Go语言URL编程
开发语言·网络·青少年编程·golang·编程与数学
南宫理的日知录19 分钟前
99、Python并发编程:多线程的问题、临界资源以及同步机制
开发语言·python·学习·编程学习
逊嘘36 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
van叶~38 分钟前
算法妙妙屋-------1.递归的深邃回响:二叉树的奇妙剪枝
c++·算法
Half-up39 分钟前
C语言心型代码解析
c语言·开发语言
knighthood20011 小时前
解决:ros进行gazebo仿真,rviz没有显示传感器数据
c++·ubuntu·ros
Source.Liu1 小时前
【用Rust写CAD】第二章 第四节 函数
开发语言·rust
monkey_meng1 小时前
【Rust中的迭代器】
开发语言·后端·rust
余衫马1 小时前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng1 小时前
【Rust中多线程同步机制】
开发语言·redis·后端·rust