【C++】string类的基础操作

💗个人主页💗
⭐个人专栏——C++学习⭐
💫点击关注🤩一起学习C语言💯💫

目录

导读

1. 基本概述

2. string类对象的常见构造

3. string类对象的容量操作

4. string类对象的访问及遍历操作

5. 迭代器

6. string类对象的修改操作

6.1 基本修改操作

6.2 c_str()函数

6.3 find + npos、rfind和substr

7. 输入输出流、关系运算符以及getline

7.1输入输出流

7.2 关系运算符

7.3 getline


导读

今天我们来学习在C++中string类的常见用法,比如构造、容量操作、遍历访问以及一些修改操作。

1. 基本概述

C++中的string类是一个用于处理字符串的标准库类。它提供了一些常用的操作和函数,使得字符串的处理更加方便和高效。

  1. 字符串的表示:string类可以表示一个字符序列,可以包含任意长度的字符。字符串可以由字符数组或者字符串字面值初始化。

  2. 字符串的操作:string类提供了一系列操作函数,包括字符串的连接、复制、查找、比较等。可以通过这些操作函数对字符串进行各种操作。

  3. 字符串的长度:string类提供了成员函数length()和size()来获取字符串的长度,即字符的个数。

  4. 字符串的访问:string类的字符可以通过下标操作符[]来访问,也可以通过at()函数来访问。同时,还可以通过迭代器来遍历字符串。

  5. 字符串的修改:string类的字符可以通过下标操作符[]进行修改,也可以通过成员函数append()、insert()、erase()等进行修改。

  6. 字符串的输入输出:string类可以通过输入输出流进行字符串的输入和输出,可以参与标准的输入输出操作。

  7. 字符串的比较:string类提供了比较操作符==、!=、>、<、>=、<=来比较字符串的大小。

总之,string类是C++中用来处理字符串的一个非常重要的类,提供了丰富的操作函数和方法,方便了字符串的处理和操作。

2. string类对象的常见构造

函数名称功能说明
string()构造空的string类对象,即空字符串
string(const char* s)用C-string来构造string类对象
string(size_t n, char c)string类对象中包含n个字符c
string(const string&s)拷贝构造函数
void test_string1()
{
	string s0;			//使用默认构造函数构造一个空的string对象s0。
	string s1("hello world");//使用字符串字面值构造一个string对象s1
	string s2(s1);//使用s1进行拷贝构造,构造一个新的string对象s2
	string s3(s1, 5, 3);//构造一个从s1的第5个字符开始的长度为3的子串,构造的string对象为s3。
	string s4(s1, 5, 10);//造一个从s1的第5个字符开始的长度为10的子串,
	string s5(s1, 5);//构造一个从s1的第5个字符开始的子串,直到字符串末尾,

	cout << s0 << endl;
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	cout << s5 << endl;

	string s6(10, '#');//使用重复10次的字符'#'构造一个string对象s6。
	cout << s6 << endl;

	s0 = s6;//将s6的值赋给s0
	cout << s0 << endl;
}
int main()
{
	test_string1();
	return 0;
}

​ 

3. string类对象的容量操作

函数名称功能说明
size返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty检测字符串释放为空串,是返回true,否则返回false
clear清空有效字符
reserve为字符串预留空间**
resize将有效字符的个数该成n个,多出的空间用字符c填充
void capacity_operations()
{
    string str = "hello world";

    cout << "Size of the string: " << endl;
    cout << str.size() << endl;

    cout << "Length of the string: " << endl;
    cout << str.length() << endl;

    str.resize(5); // 修改字符串的长度为5
    cout << "After resizing the string: " << endl;
    cout << str << endl;

    str.resize(10, 'a'); // 修改字符串的长度为10,并用字符 'a' 填充剩余部分
    cout << "After resizing and filling the string: " << endl;
    cout << str << endl;

    str.clear(); // 清空字符串
    cout << "After clearing the string: " << endl; 
    cout << str << endl;

    cout << "Is the string empty? " << endl;
    cout << (str.empty() ? "Yes" : "No") << endl;
    
    cout << "Capacity of the string: " << endl;
    cout << str.capacity() << endl;

    str.reserve(20); // 设置容量为20
    cout << "New capacity of the string: " << endl;
    cout << str.capacity() << endl;
}

int main()
{
    capacity_operations();

    return 0;
}

注意:

  1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()。
  2. clear()只是将string中有效字符清空,不改变底层空间大小。
  3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字 符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的 元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大 小,如果是将元素个数减少,底层空间总大小不变。
  4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserver不会改变容量大小。

在这里可能有小伙伴们注意到了

为什么capacity返回的容量会比我们实际的多一些?

capacity() 函数返回当前字符串的容量,即字符串在不重新分配内存的情况下可以容纳的字符数。容量包括字符串实际存储的字符数以及额外的预留空间

预留空间是为了避免频繁地进行内存重新分配操作,当字符串的空间不足时,string 类会自动分配一块更大的内存空间,并将原来的字符拷贝到新的内存中。

需要注意的是,capacity() 返回的容量不一定和实际分配的内存大小相等。实际分配的内存大小可以通过 sizeof(string) 来获得,这个大小包括了除了存储字符之外的其他开销,比如指针、长度信息等。

4. string类对象的访问及遍历操作

函数名称功能说明
operator[ ] 返回pos位置的字符,const string类对象调用
begin+ end begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
rbegin + rend begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
范围forC++11支持更简洁的范围for的新遍历方式
void access_string()
{
    string str = "hello world";

    // 使用下标访问单个字符
    cout << "Using index access:";
    for (size_t i = 0; i < str.size(); i++)
    {
        cout << str[i] << " ";
    }
    cout << endl;

    // 使用迭代器访问单个字符
    cout << "Using iterator access:";
    for (auto it = str.begin(); it != str.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    // 使用范围-based for循环遍历字符
    cout << "Using range-based for loop:";
    for (char ch : str)
    {
        cout << ch << " ";
    }
    cout << endl;
}

int main()
{
    access_string();

    return 0;
}

operator[]是C++中用于访问容器或数组中元素的运算符。

使用operator[]访问字符串中的字符时,如果索引越界,行为是未定义的。因此,在使用operator[]之前,应该确保索引在有效范围内。可以使用size()函数获取字符串的长度,并将索引与长度进行比较来确保不越界。

rbegin() 和 rend() 是用于反向遍历字符串的迭代器 

rbegin() 函数返回一个指向字符串最后一个字符的逆向迭代器,即反向起始迭代器,而 rend() 函数返回一个指向字符串第一个字符的前一个位置的逆向迭代器,即反向结束迭代器。

范围for循环是C++11引入的一种语法糖,用于迭代一个范围内的元素。 

我们使用范围for循环来遍历字符串str中的字符。在每次迭代时,当前字符被赋值给变量ch,然后我们将其输出。

范围for循环会自动处理迭代器的初始化和结束条件,并且会在循环内部按顺序遍历范围内的所有元素。

5. 迭代器

迭代器是一种用于访问容器(如数组、链表、字符串等)中元素的对象。它类似于指针,可以用来遍历容器中的元素,并进行读取、修改等操作。

在 C++ 中,string 类也提供了迭代器来遍历字符串中的每个字符。

string类提供了多种类型的迭代器,包括正向迭代器、反向迭代器和常量迭代器。

int main() 
{
    string str = "Hello, World!";

    // 正向迭代器
    string::iterator it;
    for (it = str.begin(); it != str.end(); ++it) 
    {
        cout << *it; // 输出当前字符
    }

    cout << endl;

    // 反向迭代器
    string::reverse_iterator rit;
    for (rit = str.rbegin(); rit != str.rend(); ++rit) 
    {
        cout << *rit; // 输出当前字符
    }
    cout << endl;

    // 使用常量迭代器遍历字符串
    string::const_iterator its;
    for (its = str.begin(); its != str.end(); ++its) 
    {
        cout << *its << " ";
    }
    cout << endl;

    return 0;
}

使用常量迭代器可以确保在遍历字符串时不会修改字符串的内容。常量迭代器可以通过使用const_iteratorconst_reverse_iterator类型来声明。

6. string类对象的修改操作

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

6.1 基本修改操作

int main() 
{
    string str = "Hello";

    // 使用赋值运算符修改字符串的内容
    str = "Hello World";
    cout << str << endl;

    //使用push_back函数在字符串的末尾添加一个字符。
    str.push_back('?');
    cout << str << endl;

    // 使用+=运算符进行字符串追加
    str += "!";
    cout << str << endl;

    // 使用append函数进行字符串追加
    str.append(" Welcome");
    cout << str << endl;

    // 使用insert函数在指定位置插入字符或子字符串
    str.insert(6, " to");
    cout << str << endl;

    // 使用erase函数删除指定位置的字符或子字符串
    str.erase(11, 8);
    cout << str << endl;

    // 使用replace函数替换指定位置的字符或子字符串
    str.replace(6, 2, "everybody");
    cout << str << endl;

    //使用assign函数将字符序列赋值给字符串对象
    str.assign(" xxxxx");
    cout << str << endl;

    //将字符序列的一部分赋值给字符串对象
    str.assign("Hello World", 5);
    cout << str << endl;

    return 0;
}

insert/erase/replace能少用就要少用,因为基本都要挪动数据,效率不高。

6.2 c_str()函数

c_str()是string类的一个成员函数,用于返回一个指向string对象中字符数组的指针。一般情况下,我们使用c_str()来将string对象转换为C风格字符串。

int main() 
{
    string str = "Hello, World!";
    const char* cstr = str.c_str();

    cout << cstr << endl;

    return 0;
}

6.3 find + npos、rfind和substr

find+npos:

find函数用于在字符串中查找指定子串的位置。npos是string类的静态成员常量,它的值是一个特殊的无效位置(通常为-1)。

int main() 
{
    string str = "Hello, World!";
    string subStr = "World";

    size_t found = str.find(subStr);
    if (found != string::npos) 
    {
        cout << "子字符串所在位置: " << found << endl;
    }
    else {
        cout << "没有找到" << endl;
    }

    return 0;
}

需要注意的是,npos的值是一个特殊值,可以用于与find函数的返回值比较,以判断子串是否找到。在大多数情况下,npos的值是一个非法的位置 。


rfind 函数:

用于在字符串中从后往前查找子串的位置。rfind函数返回子串最后一次出现的位置,如果未找到则返回一个特殊的值npos

int main() 
{
    string str = "Hello, Hello, World!";

    size_t found = str.rfind("Hello");
    if (found != string::npos) 
    {
        cout << "Last occurrence found at position: " << found << endl;
    }
    else 
    {
        cout << "Substring not found." << endl;
    }

    return 0;
}


substr函数:

substr函数用于从一个字符串中提取子串

它接受两个参数:开始位置和要提取的子串的长度。

int main() 
{
    string str = "Hello, World!";

    // 提取从位置7开始的子串
    string sub1 = str.substr(7);
    cout << "Substring 1: " << sub1 << endl;

    // 提取从位置0开始长度为5的子串
    string sub2 = str.substr(0, 5);
    cout << "Substring 2: " << sub2 << endl;

    return 0;
}

注意:

如果提供的位置超出了字符串的长度,或者指定的长度超出了可用的子串长度,都会导致未定义行为。因此,在使用substr函数时需要确保提供的参数符合字符串的有效范围。

7. 输入输出流、关系运算符以及getline

函数功能说明
operator>>输入运算符重载 
operator<< 输出运算符重载
getline获取一行字符串
relational operators 大小比较

7.1输入输出流

operator>>operator<<都是C++中的重载运算符,用于对输入流和输出流进行操作。

operator>>是输入流运算符,用于从输入流中读取数据。

istream& operator>>(istream& is, T& value);

其中,is是输入流对象,value是要读取数据的变量或对象。operator>>函数返回一个输入流对象,并将读取到的数据存储到value中。

operator<<是输出流运算符,用于向输出流中写入数据。

ostream& operator<<(ostream& os, const T& value);

其中,os是输出流对象,value是要写入输出流中的变量或对象。operator<<函数返回一个输出流对象。

 这两个运算符可以重载为类成员函数或非成员函数。当重载为类成员函数时,第一个参数是隐式的,表示调用运算符的对象;当重载为非成员函数时,可以在函数的参数列表中指定输入/输出流对象。

class Point 
{
public:
    int x, y;
};

//非成员函数
ostream& operator<<(ostream& os, const Point& p) 
{
    os << "(" << p.x << ", " << p.y << ")";
    return os;
}

//非成员函数
istream& operator>>(istream& is, Point& p) 
{
    is >> p.x >> p.y;
    return is;
}

int main() 
{
    Point p;
    cout << "Enter x and y coordinates: ";
    cin >> p;
    cout << "You entered: " << p << endl;
    return 0;
}

operator<<被重载为非成员函数,用于将Point对象的坐标输出到输出流中;operator>>也被重载为非成员函数,用于从输入流中读取坐标并存储到Point对象中。在main()函数中,程序首先提示用户输入坐标,然后使用operator>>运算符将读取到的坐标存储到Point对象p中,最后使用operator<<运算符将p对象的值输出到屏幕上。


7.2 关系运算符

在C++中,string 类型可以使用关系运算符(relational operators)进行比较。以下是string 类型可用的关系运算符:

  • ==:检查两个字符串是否相等。
  • !=:检查两个字符串是否不相等。
  • <:检查第一个字符串是否小于第二个字符串(按字典顺序比较)。
  • >:检查第一个字符串是否大于第二个字符串(按字典顺序比较)。
  • <=:检查第一个字符串是否小于等于第二个字符串(按字典顺序比较)。
  • >=:检查第一个字符串是否大于等于第二个字符串(按字典顺序比较)。
int main() 
{
    string str1 = "hello";
    string str2 = "world";

    if (str1 == str2) 
    {
        cout << "The strings are equal" << endl;
    }
    else if (str1 < str2) 
    {
        cout << "str1 is less than str2" << endl;
    }
    else 
    {
        cout << "str1 is greater than str2" << endl;
    }

    return 0;
}

7.3 getline

getline 函数,用于从输入流(如键盘、文件)中读取一行字符串。

getline(istream& input_stream, string& str, char delimiter);
  • input_stream 是输入流,可以是 cin(键盘输入)或 ifstream(文件输入)等。
  • str 是用于存储读取的字符串的变量,它必须是 string 类型的引用。
  • delimiter 是一个可选参数,表示行结束的分隔符,默认值为换行符 \n
int main() 
{
    string str;
    cout << "Enter a line of text: ";
    getline(cin, str);

    cout << "You entered: " << str << endl;

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/437646.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【智能家居入门1之环境信息监测】(STM32、ONENET云平台、微信小程序、HTTP协议)

作为入门本篇只实现微信小程序接收下位机上传的数据&#xff0c;之后会持续发布如下项目&#xff1a;①可以实现微信小程序控制下位机动作&#xff0c;真正意义上的智能家居&#xff1b;②将网络通讯协议换成MQTT协议再实现上述功能&#xff0c;此时的服务器也不再是ONENET&…

IPSEC VPN 网关模式实验

要求&#xff1a;FW1与FW3建立IPSEC通道&#xff0c;保证10.0.2.0/24网段能访问192.168.1.0/24网段 因为FW1与FW3都处于边界&#xff0c;所以使用网关部署模式来建立IPSEC VPN FW1 这里选择主模式跟隧道模式 FW3与FW1配置类似&#xff0c;与FW1的源目地址反过来&#xff0c;…

-bash: unzip: 未找到命令的解决方案

遇到 -bash: unzip: 未找到命令 这样的错误信息&#xff0c;表示你的系统中没有安装 unzip 工具。unzip 是一个常用的解压工具&#xff0c;用于解压缩 .zip 文件。你可以通过系统的包管理器安装它。 根据你使用的 Linux 发行版&#xff0c;安装 unzip 的命令会有所不同。下面是…

图形系统开发实战课程:进阶篇(上)——10.应用实例:交通路网

图形开发学院&#xff5c;GraphAnyWhere 课程名称&#xff1a;图形系统开发实战课程&#xff1a;进阶篇(上)课程章节&#xff1a;“图形样式”原文地址&#xff1a;https://www.graphanywhere.com/graph/advanced/2-10.html 第十章 应用实例&#xff1a;交通路网 \quad 在前面几…

老师如何发布已点评的学生在校表现,并让家长留言反馈?

教师想要在线上发布已点评过的成绩单&#xff0c;同时想让家长在线留言反馈&#xff0c;还要做到只能查自己孩子的成绩&#xff0c;应该如何实现&#xff1f; 可以使用易查分制作一个学生在校表现查询系统&#xff0c;家长自主查询&#xff0c;有问题可留言向班主任反馈&#x…

什么是工业协议网关?作用是什么?

在工业自动化和智能制造领域&#xff0c;数据的采集、传输和处理是实现设备监控、远程控制和优化的关键。而工业协议网关&#xff0c;作为连接工业设备与上层管理系统的桥梁&#xff0c;发挥着至关重要的作用。今天&#xff0c;我们就来深入解析一下HiWoo Box这一工业协议网关的…

银行数字化转型导师坚鹏:银行数字化转型案例研究

银行数字化转型案例研究 课程背景&#xff1a; 数字化背景下&#xff0c;很多银行存在以下问题&#xff1a; 不清楚银行科技金融数智化案例&#xff1f; 不清楚银行供应链金融数智化案例&#xff1f; 不清楚银行普惠金融数智化案例&#xff1f; 不清楚银行跨境金融数智…

ACM题解Day10|总结篇|进制转化,GCD ,LCM ,二分答案

&#x1f525;博客介绍&#xff1a; 27dCnc [Cstring中find_first_not_of()函数和find_last_not_of()函数-CSDN博客] 方差,期望 概率 今日打卡: 算法周总结 ACM题解Day3| To Crash or not To Crash,Integer Prefix ,I don’t want to pay for the Late Jar-CSDN博客 第3题:…

温室气体排放控制中的DNDC模型建模技术及双碳应用

由于全球变暖、大气中温室气体浓度逐年增加等问题的出现&#xff0c;“双碳”行动特别是碳中和已经在世界范围形成广泛影响。国家领导人在多次重要会议上讲到&#xff0c;要把“双碳”纳入经济社会发展和生态文明建设整体布局。同时&#xff0c;提到要把减污降碳协同增效作为促…

蓝牙 | 软件: Qualcomm BT Audio 问题分析(4)----检查MIPS使用情况

大家好&#xff01; 我是“声波电波还看今朝”成员的一位FAE Devin.wen&#xff0c;欢迎大家关注我们的账号。 今天给大家大概讲解“如何排查Qualcomm BT Audio”的疑难杂症&#xff08;四&#xff09;&#xff1a;MIPS检查。 如果大家还没有注册我们大大通的账号&#xff0c…

彻底理解Java并发:乐观锁、悲观锁和CAS

一、悲观锁与乐观锁 锁的一种宏观分类方式是悲观锁和乐观锁。悲观锁与乐观锁并不是特指某个锁&#xff08;Java 中没有哪个 Lock 实现类就叫 PessimisticLock 或 OptimisticLock&#xff09;&#xff0c;而是在并发情况下的两种不同策略。 1、乐观锁&#xff08;Optimistic L…

RK3568平台 USB数据包的收发格式

一.USB硬件拓扑结构 compound device &#xff1a;多个设备组合起来&#xff0c;通过HUB跟Host相连composite device &#xff1a;一个物理设备有多个逻辑设备(multiple interfaces) 在软件开发过程中&#xff0c;我们可以忽略Hub的存在&#xff0c;硬件拓扑图简化如下&#x…

git revert 撤回之前的几个指定的提交

文章目录 Intro操作命令-n 选项 参考 Intro 在开发过程中&#xff0c;有的时候一开始只是一个小需求&#xff0c;可以改着改着事情超出了控制&#xff0c;比如说我一开始只是想调整一个依赖包的版本&#xff0c;可是改到后来类库不兼容甚至导致项目无法启动。 这个时候我就想&…

(二十二)devops持续集成开发——jenkins服务代理Agent搭建

前言 在Jenkins 中&#xff0c;代理&#xff08;Agent&#xff09;是一种用于执行构建、部署和其他任务的计算节点。代理节点可以是物理机器、虚拟机或容器&#xff0c;它们负责接收 Jenkins 主控节点委派的任务并执行这些任务。通过使用代理节点&#xff0c;可以有效地分担Je…

基于WebDriverAgent代理服务,实现iOS手机app自动化测试的框架搭建

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

[数据结构初阶]队列

鼠鼠我呀&#xff0c;今天写一个基于C语言关于队列的博客&#xff0c;如果有兴趣的读者老爷可以抽空看看&#xff0c;很希望的到各位老爷观点和点评捏&#xff01; 在此今日&#xff0c;也祝各位小姐姐女生节快乐啊&#xff0c;愿笑容依旧灿烂如初阳&#xff0c;勇气与童真永不…

每日五道java面试题之springMVC篇(一)

目录&#xff1a; 第一题. 什么是Spring MVC&#xff1f;简单介绍下你对Spring MVC的理解&#xff1f;第二题. Spring MVC的优点第三题. Spring MVC的主要组件&#xff1f;第四题. 什么是DispatcherServlet?第五题. 什么是Spring MVC框架的控制器&#xff1f; 第一题. 什么是S…

JavaScript 作用域详解:如何影响变量生命周期

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Linux系统——Keepalive群集部署及认识

目录 一、Keepalive的认识 1.Keepalive基础——VRRP 2.Keepalived工具介绍 2.1Keepalived介绍 2.2Keepalived架构 2.2.1用户空间核心组件 2.2.2WatchDog&#xff1a;监控进程&#xff08;整个架构是否有问题&#xff09; 二、安装Keepalived及相关配置文件详解 1.安装…

python 输入和输出

在 Python 中&#xff0c;输入和输出是最基本的操作之一。你可以使用内置函数 input() 来获取用户输入&#xff0c;使用 print() 函数来输出信息到控制台。 输入&#xff08;Input&#xff09; input() 函数用于从用户那里获取输入。这个函数会将用户的输入作为字符串返回。 示…