C++ string类介绍2

at

at 函数是在C++还没有支持运算符重载的时候提供的。

 他可以像 [] 重载运算符一样,找到某个位置的字符:
 

	string s1("hello world");
	s1.at(0) = 'x';
	cout << s1 << endl;

输出:

 [] 重载运算符和 at()的区别就是,在范围处理上不同,如果 访问越界,[] 采用的是断言的方式进行处理的;而 at()采用的是抛出异常。

 抛出异常:

 断言处理:

 那么异常就可以捕获异常,然后对这个异常进行处理,程序可以继续运行;但是断言程序就不能继续执行了。

string类对象的修改操作

函数名称功能说明
push_back在字符串后尾插字符c
append在字符串后追加一个字符串
operator+= (重点)在字符串后追加字符串str
c_str(重点)返回C格式字符串
find + npos(重点)从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回

 += 重载运算符函数,就是在这个字符串之后再追加字符,或者是字符串。

 append()也是在字符串后面追加字符或者是字符串,只不过这个函数有多个接口:

 assign()是在给这个字符串赋值,也就是说,会覆盖掉之前在字符串当中存储的字符串或者字符,从0开始依次覆盖了:

 insert()支持在某下标位置插入字符或者字符串:

 insert()的效率不是很好,所以偶尔用是可以的,频繁用有效率的问题。

 erase()函数可以指定个数,指定位置 删除字符串当中的字符:

 上述给的 1 这个位置的参数就是 要删除的个数,这个位置的参数是有缺省值的,如果我们不给这个参数,那么就默认把这个位置后面的字符删光。

如果我们给的个数,超过了这个字符串的结尾,那么他也不会报错,会把后面的都删光,能删多少删多少。

上述的 erase()也是尽量少用,他也是有效率的问题。

 replace()在某一个区间当中,用传入的字符串替换到原字符串当中:

 c_str() 把这个string类的对象当中的字符串以c形式的方式返回:
 

	string s1("hello world");
	
	string filename = "text.txt";
	FILE* font = fopen(filename.c_str(), "r");

find()查找函数:

 他支持从 pos 位置开始寻找这个字符串或者是字符,这个pos位置是有缺省参数的,不传入pos的话 默认从 0 位置开始找。如果找到了,就返回第一个符合要求的,首字符下标,如果没有找到就返回 npos (-1)

比如下例子,我们要去把网址的 协议,域名,资源名切分出来:

	string url = "https://legacy.cplusplus.com/reference/string/string/find/";
	size_t pos1 = url.find("://");  // "://" 字符串之前的就是协议,其中 find 函数找到的是 ':' 这个字符的下标
	string protocaol;  // 存储域名的string类型的对象

	if (pos1 != string::npos) // find 函数如果寻找失败,返回 npos
	{
		protocaol = url.substr(0, pos1); // 把协议字符串 赋值给 protocaol
	}
	cout << protocaol << endl;

	size_t pos2 = url.find("/", pos1 + 3);
	string domain;
	string uri;

	if (pos2 != string::npos)
	{
		domain = url.substr(pos1 + 3, pos2 - (pos1 + 3));
	}
	cout << domain << endl;

	uri = url.substr(pos2 + 1);
	cout << uri << endl;

输出:

 rfind()函数,这个函数的功能和 find ()的功能完全是类似的,只不过find()是从前往后找,而find()是从后往前找。

 find_first_of()函数:

 传入一个字符串,或者是一个字符,从pos位置开始寻找(pos 缺省值 = 0)和传入的字符或者是字符字符串当中的任意一个字符相等的字符(第一个),找到之后返回这个字符的下标,如下在文档中给出的例子:

要求是把 字符串当中 "a" "e" "i" "o" "u" 的字符,全部改为 "*" :

std::string str ("Please, replace the vowels in this sentence by asterisks.");
  std::size_t found = str.find_first_of("aeiou");
  while (found!=std::string::npos)
  {
    str[found]='*';
    found=str.find_first_of("aeiou",found+1);
  }

  std::cout << str << '\n';

输出:

Pl**s*, r*pl*c* th* v*w*ls *n th*s s*nt*nc* by *st*r*sks.

上述是从前往后找的函数,还有一个函数和上述函数的功能是一样的,find_last_of()函数。

  当然,还有查找 不是传入的 字符串和 字符的函数:find_first_not_of 和 find_last_not_of ;

注意:

  • 在string尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
  • 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。

 string类非成员函数

函数功能说明
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>> (重点)输入运算符重载
operator<< (重点)输出运算符重载
getline (重点)获取一行字符串
relational operators (重点)大小比较

 字符串比较的重载运算符函数:

relational operators

 上述就是对应的接口,其实上述实现的接口,有限冗余,上述一个 重载运算符函数 重载了三个形参不同的函数,分别是 字符串类型 和 string 类 参数类型 变化,其实不用实现这么多,因为 如果是 string& 参数 传入 char* 类型的参数的时候,char* 在传参的时候可以隐式类型转换 为 string& 。

getline()函数和 C当中的 gets 有点像,我们在C++当中使用的 cin 输入流,和 C 当中的scanf()函数一样,当读到 空格 '\n'就会结束读入,那么我们上述cin 就不能读取字符串,所以我们就是用 getline ()来读入字符串。

例子,返回一个字符串当中,最后一个单词的 长度:

	string str;
	getline(cin, str);  // 读取字符串
	size_t pos = str.rfind(' ');
	if (pos != string::npos)
	{
		cout << str.size() - (pos + 1) << endl;
	}
	else
	{
		cout << str.size() << endl;
	}

getline 只 遇到 '\n' 才结束。

to_string  和  stoi

 to_string 可以把 内置类型 转换成string类型,这个函数返回的就是 string类型:
 

	string s1 = to_string(1234);
	string s2 = to_string(1.1);

	cout << s1 << endl;  //1234
	cout << s2 << endl; //1.100000

 如果是在C当中我们使用的是 itoa()函数把 int 类型转换成 字符串类型,但是这个函数不好用在于,接收的字符串类型,需要我们手动开空间。

如果是在 C 当中我们使用的是 atoi()来把 字符串类型转换成 int 类型:

 wstring , u16string ,u32string

 其实string是一个模板 typedef 出来的string。只不过这里面传入的是 char 类型:

 其实本源的类其实是 basic_string 这个类型,所以我们看到 关于string类的报错的时候,会看到     basic_string 字样。

 之所以这样做是因为,还有其他的string类型wstring , u16string ,u32string。

上述的本源也都是 basic_string。

上述三种类型其实不经常用,之所以把他区分开来是因为编码问题。

 我们现在经常使用的 编码格式 是 ascll 表的,就是 底层存储的值,对应的映射关系表。在计算机当中存储的值是二进制的,比如在 ascll 当中,一共就 200 多个,那么 8 个bite 位就可以存储了。存储的不同的二进制的值就代表着不同的字符,比如 0110 0000 对应的十进制是 97,那么这个二进制代表的就是 a 这个字符。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chihiro1122

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值