首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【c++】string类 (一)

【c++】string类 (一)

作者头像
prettyxian
发布2025-12-30 19:09:00
发布2025-12-30 19:09:00
1010
举报
文章被收录于专栏:QTQT

简介

由于c++的历史包袱,c++要兼容c语言,c++的字符串要兼容c语言,在 C++ 中,字符串通常使用两种主要的方式来表示:

C风格字符串(C-style strings)

依然是以 '\0' 结尾的字符数组。这种表示方式与 C 语言中的字符串相同。例如:

代码语言:javascript
复制
const char* str = "Hello, World!";

在内存中,它是一个字符数组,最后一个字符是空字符 '\0'

C++ 的标准库字符串(std::string

C++ 提供了一个 std::string 类型,属于标准库的一部分。它管理自己的内存,并且不需要手动处理 '\0'。使用 std::string 更加方便和安全。例如:

代码语言:javascript
复制
#include <string> 
std::string str = "Hello, World!";

std::string 处理字符串的长度、内存分配和释放,因此开发者可以专注于字符串的内容,而不必担心细节。

c风格类型的字符串我们都已经很熟悉,\0的存在让我们在处理在处理字符串的时候需要时刻小心,在手动拼接或复制字符串时经常会因为\0处理不妥而出错。c++为我们提供了一个全新的string来处理字符串的长度、内存分配和释放,因此开发者可以专注于字符串的内容,而不必担心细节。

在一切开始之前,我们先介绍一个网站。

www.cplusplus.com是一个广受欢迎的C++编程语言资源网站,成立于2000年代初期。开始由一个c++爱好者建立,后来各路大佬汇聚,网站内容也非常成熟,可供我们学习和参考。

string类的常用接口说明

构造函数

c++98就为我们提供了7个构造函数,当然并不要求也没有必要对所有的函数烂熟于心,大多数时候把这个当成词典来使用就可以了,选常用的一部分学习。

学习类和对象很容易大家就能知道上面哪是重要的

不传参的默认构造,拷贝构造和第四个用常量字符串初始化的构造。

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s1;//默认构造
	string s2("123456789");
	string s3(s2);//拷贝构造

	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;

	cin >> s1;
	cout << s1 << endl;
	return 0;
}

我们也可以向里面输入中文

便利string的三种方式

operator[]

string类重载了[],这让我们可以像数组一样访问字符串。

同时注意看,重载后返回的类型是引用,不仅可以减少拷贝,关键在于这样我们能够直接通过下标对字符串进行修改。在重载的时候加入了断言,当pos大于size(越界时),编译器会报错。

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s1;
	string s2("123456789");
	string s3(s2);

	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;

	cout << s2[2] << endl;//可以通过下标访问
	s2[0] = '5';//也可以直接修改
	cout << s2 << endl;
	/*cin >> s1;
	cout << s1 << endl;*/
	return 0;
}

遍历string的第一种方法就是:下标 + []

代码语言:javascript
复制
#include <iostream>
#include <string>

using namespace std;

int main()
{
	string s1;
	string s2("123456789");
	string s3(s2);

	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;

	cout << s2[2] << endl;//可以通过下标访问
	s2[0] = '5';//也可以直接修改
	cout << s2 << endl;
	/*cin >> s1;
	cout << s1 << endl;*/


	for (size_t i = 0; i < s2.size(); i++)
	{
		cout << s2[i] << " ";
	}
	cout << endl;
	return 0;
}
迭代器

迭代器是一种用于遍历容器(如数组、向量、链表等)元素的对象。它提供了一种统一的方法来访问不同类型的容器中的元素(所有的容器都可以由它访问),而无需了解容器的内部结构。

正向迭代器

begin()返回第一个位置;

end()返回最后一个位置的下一个位置。

代码语言:javascript
复制
for (size_t i = 0; i < s2.size(); i++)
{
	cout << s2[i] << " ";
}
cout << endl;

string::iterator it= s2.begin();
while (it != s2.end())
{
	cout << *it << " ";
	++it;
}
cout << endl;
反向迭代器

反向迭代器提供了一个rbegin()指向最后一个位置

rend()指向第一个位置的前一个位置。这里任然要使用++,++被重载了让它能倒着遍历。

代码语言:javascript
复制
string s1;
string s2("123456789");
string s3(s2);

cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
string::reverse_iterator it = s2.rbegin();
while (it != s2.rend())
{
	cout << *it << " ";
	++it;
}
cout << endl;
const迭代器

由于权限,普通迭代器可读可写,无法访问const对象,const对象要用const迭代器,只读不写。

代码语言:javascript
复制
	const string s2("hello world!");
	//正向
	string::const_iterator cit = s2.begin();
	while (cit != s2.end())
	{
		cout << *cit << " ";
		++cit;
	}
	cout << endl;
	//反向
	string::const_reverse_iterator rcit = s2.rbegin();
	while (rcit != s2.rend())
	{
		cout << *rcit << " ";
		++rcit;
	}
	cout << endl;
范围for

字符赋值,自动迭代,自动判断结束,底层由迭代器实现。适用于容器和数组。

代码语言:javascript
复制
for (size_t i = 0; i < s2.size(); i++)
{
	cout << s2[i] << " ";
}
cout << endl;

string::iterator it= s2.begin();
while (it != s2.end())
{
	cout << *it << " ";
	++it;
}
cout << endl;

for (auto ch : s2)
{
	cout << ch << " ";
}
cout << endl;

但是由于范围for()是给ch这个局部变量赋值,并不能直接改变s2,而迭代器是直接可以改变s2的。

代码语言:javascript
复制
string::iterator it = s2.begin();
while (it != s2.end())
{
	*it += 2;
	cout << *it << " ";
	++it;
}
cout << endl;

for (auto ch : s2)
{
	ch -= 2;
	cout << ch << " ";
}
cout << endl;

cout << s2 << endl;

如果要使用范围for()来改变传入的形参,在传入时加上引用,这样就不会生成拷贝而是直接修改传入的形参。

capacity

不同编译器对内存空间的处理是不一样的

代码语言:javascript
复制
string s;
size_t sz = s.capacity();

cout << "original capacity:" << sz << endl;
for (int i = 0; i < 100; i++)
{
	s.push_back('c');
	if (sz != s.capacity())
	{
		sz = s.capacity();
		cout << "capacity changed: " << sz << endl;
	}
}

在vs中有一个buff数组,该开始中string中的数据是储存在buff中的,当要储存的数据空间大于15时才会额外开空间,该开始要把buff中的数据拷贝出来一共开了两倍空间,后边都是开的1.5倍空间。c++只规定了开空间,但是怎么开空间没有做具体的要求。其他的编译器开空间的方式可能会不同。

频繁的扩容会导致效率低下,为解决这一问题,c++提供了reserve()可以预留空间。

代码语言:javascript
复制
string s("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");

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

s.reserve(10);
cout << s.size() << endl;
cout << s.capacity() << endl << endl;
s.reserve(30);
cout << s.size() << endl;
cout << s.capacity() << endl << endl;
s.reserve(40);
cout << s.size() << endl;
cout << s.capacity() << endl << endl;
s.reserve(50);
cout << s.size() << endl;
cout << s.capacity() << endl << endl;

但是c++标准并没有规定具体怎么处理空间,不同的编译器也不一样。

仅仅反转字母

https://leetcode.cn/problems/reverse-only-letters/

题目解析:

题目中让我们仅仅反转字母,首先我们要分类-----字母和非字母;很简单所有的字母并不多,我们只需要筛选出字母就好,写一个函数实现这个功能 。要实现反转首先就要有两个位置,使用双指针,从首尾开始遍历。基本框架已经确定,接下来就是敲定判断的细节了。首先考虑极限条件,输入的没有字母left会一直加,越界了;所以处理left和right时要加上判断条件。

代码语言:javascript
复制
class Solution {
public:
     bool Isletter(char ch)
    {
	     if (ch >= 'a' && ch <= 'z')
	    {
	     	return true;
	    }
	      if (ch >= 'A' && ch <= 'Z')
	     {
	    	return true;
	       }
	return false;
       }
    string reverseOnlyLetters(string s) {
        if (s.empty())
        {
            return s;
        }
        size_t left = 0;
        size_t right = s.size() - 1;
        while(left < right)
        {
            while(left < right && !Isletter(s[left]))
            {
                left++;
            }
            while(left < right && !Isletter(s[right]))
            {
                right--;
            }
            swap(s[left++],s[right--]);
        }
        return s;
    }
};
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-10-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • string类的常用接口说明
    • 构造函数
    • 便利string的三种方式
      • operator[]
      • 迭代器
      • 范围for
    • capacity
  • 仅仅反转字母
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档