【C++第七课-string用法】

2024-05-03 21:44
文章标签 c++ string 用法 第七课

本文主要是介绍【C++第七课-string用法】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这里写自定义目录标题

  • string的初步介绍
  • sring的构造函数
    • string的构造函数-重点掌握
      • 无参的构造函数
      • 用常量字符串来初始化
      • 拷贝构造
    • string的构造函数-非重点掌握
      • 拷贝字符串str从pos位置开始的len个字符
      • 拷贝字符串s的前n个字符
      • 用n个c去初始化
  • string的赋值
  • string的遍历和访问
    • 下标+[ ]
      • 使用[ ]进行读
      • 使用[ ]进行写,对s1进行逆置
    • iterator迭代器
      • 使用reverse算法实现逆置
      • 反向迭代器
      • cbegin、cend、crbegin、crend
    • 范围for遍历
    • at
  • string的容量
    • size、length -- string的有效长度
    • max_size
    • capacity
      • 检查string扩容机制
    • reserve -- 扩容
    • resize
      • n>capacity 扩容+尾插
      • size < n < capacity 尾插
      • n < size 删除数据,保留前n个
  • string的增删查改
      • push_back
      • append
      • +=
      • insert / erase
        • insert
        • erase
      • replace
      • find
      • rfind
      • **将字符串中的空格都替换成20%**
      • pop_back - 尾删
      • c_str
      • copy
      • substr
      • 取出字符串的后缀
      • 强制分离
      • find_first_of
      • find_last_of
      • +
  • 习题
  • 知识点补充
    • 全局swap和对象里面的swap

string的初步介绍

在这里插入图片描述
basic_string是一个类模板
string本质上是basic_string < char >,也就是管理char的,字符数组

sring的构造函数

在这里插入图片描述

string的构造函数-重点掌握

无参的构造函数

string();

用常量字符串来初始化

string (const char* s);

拷贝构造

string (const string& str);
int main()
{string s1;string s2("hello world");string s3 = s2;string s4(s2);return 0;
}

下面是拷贝构造,且这两行代码用法上是等价的

string s3 = s2;
string s4(s2);

打印的时候可以直接cout,因此string重载了流插入和流提取
在这里插入图片描述
在这里插入图片描述

string的构造函数-非重点掌握

拷贝字符串str从pos位置开始的len个字符

Copies the portion of str that begins at the character position pos and spans len characters (or until the end of str, if either str is too short or if len is string::npos).

string (const string& str, size_t pos, size_t len = npos);

在这里插入图片描述

拷贝字符串s的前n个字符

Copies the first n characters from the array of characters pointed by s.

string (const char* s, size_t n);

用n个c去初始化

Fills the string with n consecutive copies of character c.

string (size_t n, char c);

string的赋值

在这里插入图片描述

string的遍历和访问

下标+[ ]

[ ]只有在底层连续的情况下才能实现
const对象会调用const的[ ],但返回值也是const的引用,不能修改
在这里插入图片描述
获取数组的长度,size或length,这两作用一样
size和length都不包含\0
在这里插入图片描述
[ ]既可以读也可以写

使用[ ]进行读

#include<iostream>
#include<string>
using namespace std;int main()
{string s1("hello world");for (size_t i = 0; i < s1.size(); i++){cout << s1[i] << " ";}return 0;
}

在这里插入图片描述

使用[ ]进行写,对s1进行逆置

//逆置s1size_t begin = 0, end = s1.size() - 1;while (begin < end) //当begin==end的时候也不用交换了{char temp = s1[begin];s1[begin] = s1[end];s1[end] = temp;begin++;end--;}cout << "s1逆置:" << s1 << endl;

在这里插入图片描述
简化版的逆置
在这里插入图片描述

//逆置s1size_t begin = 0, end = s1.size() - 1;while (begin < end) //当begin==end的时候也不用交换了{/*char temp = s1[begin];s1[begin] = s1[end];s1[end] = temp;*/swap(s1[begin], s1[end]);begin++;end--;}cout << "s1逆置:" << s1 << endl;

iterator迭代器

用法像指针,但不一定是指针实现的
begin和end是左闭右开,begin指向第一个有效字符,end指向最后一个有效字符的下一个
在这里插入图片描述

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

使用reverse算法实现逆置

在这里插入图片描述

reverse(s1.begin(), s1.end());
cout << s1 << endl;

在这里插入图片描述

const_iterator it 本质保护的是迭代器指向的内容*it不能被修改
const iterator it 本质保护的是迭代器it不能修改
iterator和const_iterator是两个不同的类型

反向迭代器

在这里插入图片描述

	string s1("hello world");string::iterator it = s1.begin();while (it != s1.end()){cout << *it << " ";++it;}cout << endl;string::reverse_iterator rit = s1.rbegin();while (rit != s1.rend()){cout << *rit << " ";++rit;}cout << endl;

这里的string::reverse_iterator很长,可以用auto代替

//string::reverse_iterator rit = s1.rbegin();
auto rit = s1.begin();

在这里插入图片描述

cbegin、cend、crbegin、crend

使用auto之后就不知道调的是否是const类型了
下面四个就是为了让代码更清晰一点
在这里插入图片描述

范围for遍历

string、list、vector都可以用,范围for底层就是iterator

for (auto e : s1){cout << e << " ";}cout << endl;

at

与[ ]区别:在越界的处理上有些区别

at:抛异常 – 警告式报错
[ ]:断言错误 – 暴力报错

在这里插入图片描述

`int main()
{
string s1(“hello world”);
cout << s1[20] << endl;

return 0;

在这里插入图片描述

int main()
{string s1("hello world");cout << s1.at(20) << endl;return 0;
}

在这里插入图片描述

string的容量

size、length – string的有效长度

在这里插入图片描述

max_size

实践中没有参考和使用价值
string能开的最大个数
Returns the maximum length the string can reach.
在这里插入图片描述

capacity

返回的是有效空间多大,不包含\0
size有效字符数量
在这里插入图片描述

	string s1("hello world");cout << s1.capacity() << endl;cout << s1.size() << endl

在这里插入图片描述

检查string扩容机制

基本上是1.5倍扩容

string s2;size_t old = s2.capacity();for (int i = 0; i < 100; i++){s2.push_back('x');if (old != s2.capacity()){cout << s2.capacity() << endl;old = s2.capacity();}}

在这里插入图片描述

string s2;size_t old = s2.capacity();for (int i = 0; i < 500; i++){s2.push_back('x');if (old != s2.capacity()){cout << s2.capacity() << endl;old = s2.capacity();}}

在这里插入图片描述

reserve – 扩容

reserve只会扩容不会缩容,只影响空间不影响数据
linux下,无数据的时候会缩,但当缩到比现有数据size还要小时,最多缩到size就不会缩了。
reserve的价值:当知道需要多少空间的时候,提前去扩

	string s2;size_t old = s2.capacity();s2.reserve(500);for (int i = 0; i < 500; i++){s2.push_back('x');if (old != s2.capacity()){cout << s2.capacity() << endl;old = s2.capacity();}}

上面s2.reserve(500)中要了500,不一定给开500,这里给开了512
在这里插入图片描述

resize

既影响空间又影响数据
常见使用常见:开空间+初始化
在这里插入图片描述
如果没有c时,插入的是\0,如果y有c则插入c
在这里插入图片描述

n>capacity 扩容+尾插

int main()
{string s1("hello world");cout << "size:" << s1.size() << endl;cout << "capacity:" << s1.capacity() << endl;s1.resize(30, 'x');cout << s1 << endl;cout << "size:" << s1.size() << endl;cout << "capacity:" << s1.capacity() << endl;return 0;
}

在这里插入图片描述

size < n < capacity 尾插

在这里插入图片描述

n < size 删除数据,保留前n个

在这里插入图片描述

string的增删查改

改:[ ]、迭代器
差:[ ]
曾:push_back、append、+=
删:

push_back

只能一个字符一个字符的增加

append

可以增加字符串
在这里插入图片描述

(1)和(3)冗余了

+=

在这里插入图片描述

insert / erase

insert

在pos之前插入,insert是头插,需要移动数据,能少用就少用
在这里插入图片描述

	string s1("hello world");s1.insert(5, "xxxx");cout << s1 << endl;s1.insert(5, "zyh123456", 2, 4);cout << s1 << endl;const char* c1 = "hhh";s1.insert(5, c1);cout << s1 << endl;const char* c2 = "www";s1.insert(5, c2, 2);cout << s1 << endl;s1.insert(5, 3, 'o');cout << s1 << endl;

在这里插入图片描述

erase

在这里插入图片描述
如果不写4,则会默认npos(整型的最大值,size_t = -1),pos后面有多少删多少

	s1.erase(5, 4);cout << s1 << endl;

在这里插入图片描述

replace

在这里插入图片描述

	string s2("hello  world");cout << s2 << endl;s2.replace(5, 1, "%%");cout << s2 << endl;

在这里插入图片描述

find

可以找一个字符/字符串/string,从pos位置开始,找不到就返回npos
在这里插入图片描述

rfind

与find相反,是从字符串后面找
在这里插入图片描述
在这里插入图片描述

将字符串中的空格都替换成20%

方法一:使用find+replace
缺点:replace效率太低,每一次替换都要挨个挪位置

	string s1("Dark light,just light each other");size_t pos = s1.find(' ');while (pos != string::npos){s1.replace(pos, 1, "20%");pos = s1.find(' ', pos + 1);}cout << s1 << endl;

在这里插入图片描述

方法二:创建一个新的字符串

	string s1("Dark light,just light each other");string s2;for (auto e : s1){if (e != ' '){s2 += e;}elses2 += "20%";}cout << s2 << endl;

在这里插入图片描述

pop_back - 尾删

一次只能尾删一个
在这里插入图片描述

	string s1("hello world");s1.pop_back();cout << s1 << endl;

在这里插入图片描述

c_str

把sring转换成字符串,目的是为了使用一些C语言的接口
在这里插入图片描述

	string filename("test.cpp");FILE* fout = fopen(filename.c_str(), "r");char ch = fgetc(fout);while (ch != EOF){cout << ch;ch = fgetc(fout);}

在这里插入图片描述

copy

从当前string字符串pos位置开始,copy下一个长度为len的字串,放到指针s所指的地方
返回值是s中的有效字符长度
在这里插入图片描述

	char b[10];string s1("hello world");size_t length = s1.copy(b, 5, 6);b[length] = '\0';cout << b << endl;

在这里插入图片描述

substr

stringpos位置开始,取长度为len的字串
在这里插入图片描述

取出字符串的后缀

	string s1("Test.cpp");string s2("Test.txt.zip");size_t pos1 = s1.find('.');cout << "s1:" << s1.substr(pos1) << endl;size_t pos2 = s2.rfind('.');cout << "s2:" << s2.substr(pos2) << endl;

在这里插入图片描述

强制分离

	string str("https://cplusplus.com/reference/string/string/swap/");string sub1, sub2, sub3;size_t pos1 = str.find(':');sub1 = str.substr(0, pos1);size_t pos2 = str.find('/', pos1 + 3);sub2 = str.substr(pos1 + 3, pos2 - pos1 - 3);sub3 = str.substr(pos2 + 1);cout << sub1 << endl;cout << sub2 << endl;cout << sub3 << endl;

在这里插入图片描述

find_first_of

查找str/s/c中任意一个字符在string中第一次出现的位置
在这里插入图片描述

	string s1("Life is like a piano. What you get out of it depends on how you play it");size_t pos = s1.find_first_of("adt");while (pos != string::npos){s1[pos] = '*';pos = s1.find_first_of("adt", pos + 1);}cout << s1 << endl;

在这里插入图片描述

find_last_of

在这里插入图片描述

void SplitFilename(const std::string& str)
{std::cout << "Splitting: " << str << '\n';std::size_t found = str.find_last_of("/\\");std::cout << " path: " << str.substr(0, found) << '\n';std::cout << " file: " << str.substr(found + 1) << '\n';
}int main()
{std::string str1("/usr/bin/man");std::string str2("c:\\windows\\winhelp.exe");SplitFilename(str1);SplitFilename(str2);return 0;
}

在这里插入图片描述

+

+是非成员函数
在这里插入图片描述
(2)和(3)交换了参数又写了一遍的目的:为了满足下面的两种用法

	string s1("hello world");string s2 = s1 + "xx";string s3 = "xx" + s1;cout << s2 << endl << s3 << endl;

像之前写的那个日期类的+
date + 100可以这么用,但不能写成100+date
如果想用第二种形式,那就要交换参数,但想要交换参数就不能是成员函数,因为如果是成员函数,那么第一个参数就是this指针。

习题

找字符串中第一个只出现一次的字符
在这里插入图片描述
大数运算
字符串相加
在这里插入图片描述

整型和字符进行运算的时候,是整型和ascii码进行加减

最后一个单词的长度

#include <iostream>
using namespace std;int main() {string a;getline(cin,a);size_t pos = a.rfind(' ');if(pos != string::npos){cout << a.size() - pos - 1 << endl;}else {cout << a.size() << endl;}
}

不能使用cin >> a,因为这样遇到空格就会停下,scanf也是用到空格就停下

知识点补充

全局swap和对象里面的swap

对象里面的swap
在这里插入图片描述

在这里插入图片描述
全局的swap
对于全局的swap则需要创建一个临时对象

swap(s2,s3);

综上来看,全局的swap效率更低

这篇关于【C++第七课-string用法】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/957714

相关文章

IDEA如何将String类型转json格式

《IDEA如何将String类型转json格式》在Java中,字符串字面量中的转义字符会被自动转换,但通过网络获取的字符串可能不会自动转换,为了解决IDEA无法识别JSON字符串的问题,可以在本地对字... 目录问题描述问题原因解决方案总结问题描述最近做项目需要使用Ai生成json,可生成String类型

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

oracle中exists和not exists用法举例详解

《oracle中exists和notexists用法举例详解》:本文主要介绍oracle中exists和notexists用法的相关资料,EXISTS用于检测子查询是否返回任何行,而NOTE... 目录基本概念:举例语法pub_name总结 exists (sql 返回结果集为真)not exists (s

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

Springboot中Jackson用法详解

《Springboot中Jackson用法详解》Springboot自带默认json解析Jackson,可以在不引入其他json解析包情况下,解析json字段,下面我们就来聊聊Springboot中J... 目录前言Jackson用法将对象解析为json字符串将json解析为对象将json文件转换为json

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�