C++之 string(中)

news2024/11/20 19:42:18

C++之 string

在这里插入图片描述

string类对象的容量操作

resize

将有效字符的个数该成n个,多出的空间用字符c填充

虽然在string里用的不多,但是在vector里面常见

这里有三种情况:

1)resize小于当前的size

2)resize大于当前的size,小于capacity

3)大于capacity

1)resize小于当前的size

本质上就是删除数据

代码如下:

#include <iostream>
#include <string>
using namespace std;
int main()
{
	//初始情况
	string s1("111111");
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
	
	return 0;
}

初始情况:

在这里插入图片描述

再来看下面的代码:

#include <iostream>
#include <string>
using namespace std;
int main()
{
	//初始情况
	string s1("111111");
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
	//小于size
	s1.resize(3);
	cout << s1 << endl;
	
	return 0;
}

在这里插入图片描述

2)resize大于当前的size,小于capacity

本质是插入

using namespace std;
int main()
{
	//初始情况
	string s1("111111");
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
	//小于size
	s1.resize(3);
	cout << s1 << endl;
	//resize大于当前的size,小于capacity
	s1.resize(7,'6');
    //这里相当于给字符串插入字符,如果不给也不会报错,编译器会自己赋初始值
	cout << s1 << endl;
	return 0;
}

在这里插入图片描述

3)大于capacity

using namespace std;
int main()
{
	//初始情况
	string s1("111111");
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;
	//小于size
	s1.resize(3);
	cout << s1 << endl;
	//resize大于当前的size,小于capacity
	s1.resize(7,'6');
	cout << s1 << endl;
	//大于capacity
	s1.resize(16, '3');
	return 0;
}

在这里插入图片描述

本质也是插入,大于也不会报错

总结:

resize小于当前的size本质是删除,resize大于当前的size,小于capacity和大于capacity是插入

注意点:

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

string类对象的修改操作

insert

C++是一个极度追求效率的语言,不希望过多的使用头插,头插会使时间复杂度变大,所以就用insert间接替代

代码示例如下:

#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s1("hello world");
	s1.insert(5, "xxx");
	cout << s1 << endl;
	return 0;
}

打印结果:

在这里插入图片描述

当然最好也是少用,因为影响效率

erase

消除字符串

代码示例如下:

#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s1("hello world");
	s1.insert(5, "xxx");
	cout << s1 << endl;
	s1.erase(5, 5);//前一个表示要从第几个开始删除,第二个参数表示删除几个
	cout << s1 << endl;
	return 0;
}

打印结果:
在这里插入图片描述

注意点:

s1.erase(0, 1);//可以删开头
cout << s1 << endl;
s1.erase(5);//不给删除到第几个,直接后面全删掉
cout << s1 << endl;

打印结果:

在这里插入图片描述

还要注意的是开头的第一个参数不可以越界,会抛异常

s1.erase(55);

replace

只有平替的效率才会高,其余情况不建议使用

示例代码如下:

s1.replace(5, 1, "%%");
cout << s1 << endl;

运行结果如下:

在这里插入图片描述

不推荐的原因在于它会改变位置,影响运行的效率

find

从字符串pos位置开始往后找字符c,返回该字符在字符串中的 位置

代码示例如下:

size_t i = s1.find(" ");
while (i != string::npos)
{
	s1.replace(i, 1, "%%");
	i = s1.find(" ");
}
cout << s1 << endl;

打印结果:

在这里插入图片描述

结合之前的范围for,还有更简便的写法:

string s2;
for (auto ch : s1)
{
	if (ch != ' ')
	{
		s2 += ch;
	}
	else
	{
		s2 += "%%";
	}
}
cout << s2 << endl;

得到的也是同样的结果。

c_str

返回C格式字符串

示例代码如下:

#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s1("hello world");
	cout << s1 << endl;
	cout << s1.c_str() << endl;
	const char* p1 = "xxxx";
	int* p2 = nullptr;
	cout << p1 << endl;//打印不了地址,会自动解引用
	//cout会自动识别类型,printf可以指定
	//想要打印成指针,可以强转(void*)
	cout << (void*)p1 << endl;
	cout << p2 << endl;
	return 0;
}

打印结果:
在这里插入图片描述

因为C++也是兼容C语言的,但是它有的不会接收C++的接口,所以要用到c_str,如文件的读:

#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s1("hello world");
	cout << s1 << endl;
	cout << s1.c_str() << endl;
	const char* p1 = "xxxx";
	int* p2 = nullptr;
	cout << p1 << endl;//打印不了地址,会自动解引用
	//cout会自动识别类型,printf可以指定
	//想要打印成指针,可以强转(void*)
	cout << (void*)p1 << endl;
	cout << p2 << endl;
	string s2("2024_09_23.cpp");
	FILE* fout = fopen(s2.c_str(), "r");//不能没有后面的,C语言里这个第一个参数必须
	//是const*修饰的
	char ch = fgetc(fout);
	while (ch!=EOF)
	{
		cout << ch; 
		ch = fgetc(fout);
	}
	return 0;
}

打印结果:

在这里插入图片描述

rfind

从字符串pos位置开始往前找字符c,返回该字符在字符串中的 位置

应用场景如:找文件名后缀

string s3("test.cpp.zip");
size_t pos = s3.rfind('.');
if (pos != string::npos)
{
	string sub = s3.substr(pos);
	cout << sub << endl;
}

打印结果:
在这里插入图片描述

注意点在于我这里也用了个新接口

substr

在str中从pos位置开始,截取n个字符,然后将其返回

find_first_of

代码示例如下:

// string::find_first_of
#include <iostream>       // std::cout
#include <string>         // std::string
#include <cstddef>        // std::size_t

int main()
{
	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';

	return 0;
}

在这里插入图片描述

任意一个在里面的值用*替换

not的话就是相当于它的补集关系,其实叫any更好,任意的意思

总的来说:需要重点掌握的接口有以下,以一张思维导图的形式表现:

在这里插入图片描述

上面这些属于不看文档都必须要知道其基本用法的。

一道OJ题:字符串中的第一个唯一字符

给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1

示例 1:

输入: s = "leetcode"
输出: 0

示例 2:

输入: s = "loveleetcode"
输出: 2

示例 3:

输入: s = "aabb"
输出: -1

提示:

  • 1 <= s.length <= 105
  • s 只包含小写字母

代码:

class Solution {
public:
    int firstUniqChar(string s) {
       int count[26]={0};
        //统计次数
        for(auto ch:s)
        {
            //间接映射
            count[ch-'a']++;
        }
        //再遍历索引(下标)
        for(size_t i=0;i<s.size();++i)
        {
            if(count[s[i]-'a']==1)
            {
                return i;
            }
        }
       return -1;
    }
};

一道OJ题:字符串最后一个单词的长度

描述

计算字符串最后一个单词的长度,单词以空格隔开,字符串长度小于5000。(注:字符串末尾不以空格为结尾)

输入描述:

输入一行,代表要计算的字符串,非空,长度小于5000。

输出描述:

输出一个整数,表示输入字符串最后一个单词的长度。

示例1

输入:
hello nowcoder
输出:
8
说明:
最后一个单词为nowcoder,长度为8

代码:

#include <iostream>
using namespace std;
#include<string>
int main() {
   string str;
// 不要使用cin>>line,因为会它遇到空格就结束了
// while(cin>>line)
   getline(cin,str);
   size_t pos=str.rfind(' ');
   cout<<str.size()-(pos+1)<<endl;
    //左闭右开,减出来才是个数
   return 0;
    
}

这里我们需要来介绍一个接口:getline

获取一行字符串

遇到换行的时候会自动结束

像我们之前遇到的scanf,cin都是连续地从流中提取数据,因为它会把数据放到缓冲区里,默认空格,换行是分割,因为一个一个字符地区提取效率会很低

来看下面代码示例:

#include <iostream>
#include <string>
using namespace std;
int main()
{
	string s1, s2;
	cin >> s1 >> s2;
	cout << s1 << endl;
	cout << s2 << endl;
	return 0;
}

打印结果:
在这里插入图片描述

另外一种情况:

string str;
getline(cin, str, '#');
//指定字符,遇到这个字符就会停止流输入

在这里插入图片描述

一道OJ题:验证回文串

如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串

字母和数字都属于字母数字字符。

给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false

示例 1:

输入: s = "A man, a plan, a canal: Panama"
输出:true
解释:"amanaplanacanalpanama" 是回文串。

示例 2:

输入:s = "race a car"
输出:false
解释:"raceacar" 不是回文串。

示例 3:

输入:s = " "
输出:true
解释:在移除非字母数字字符之后,s 是一个空字符串 "" 。
由于空字符串正着反着读都一样,所以是回文串。

提示:

  • 1 <= s.length <= 2 * 105
  • s 仅由可打印的 ASCII 字符组成

代码如下:

class Solution {
public:
    bool isLetterOrNumber(char ch)
    {
        return (ch>='0'&&ch<='9')
        ||(ch>='a'&&ch<='z')
        ||(ch>='A'&&ch<'Z');
    }
    bool isPalindrome(string s) {
        for(auto&ch:s)
        {
            if(ch>='a'&&ch<='z')
                ch-=32;
        }
        int begin=0,end=s.size()-1;
        while(begin<end)
        {
            while(begin<end&&!isLetterOrNumber(s[begin]))
                ++begin;
            while(begin<end&&!isLetterOrNumber(s[end]))
                --end;
                if(s[begin]!=s[end])    
                {
                    return false;
                }
                else
                {
                    ++begin;
                    --end;
                }
        }
        return true;
    }
};

string类的模拟实现

在面试中,面试官总喜欢让 学生自己来模拟实现string类,最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析 构函数。

下面是关于构造,析构,迭代器,尾插的模拟实现

string.h

#pragma once
#include <iostream>
#include <assert.h>
#include <string>
using namespace std;
namespace Tzuyu
{
	class string
	{
	public:
		string(const char* str = " ");
		~string();
		void reserve(size_t n);
		void push_back(char ch);
		void append(const char* str);
		string& operator+=(char ch);//不建议过多使用,因为是全局变量
		string& operator+=(const char* str);
		char& operator[](size_t i)
		{
			assert(i < _size);
			return _str[i];
		}

		const char& operator[](size_t i) const
		{
			assert(i < _size);
			return _str[i];
		}
		using iterator = char*;
		using const_iterator = const char*;
		iterator begin()//范围for底层是迭代器,必须要规范,如这里的begin,如果是Begin就不行,范围for会报错
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}
		const_iterator begin() const
		{
			return _str;
		}
		const_iterator end() const
		{
			return _str + _size;
		}
		size_t size() const
		{
			return _size;
		}
		const char* c_str() const
		{
			return _str;
		}

	private :
		char* _str;
		size_t _size;
		size_t _capacity;
	};
}

string.cpp

#include "string.h"
namespace Tzuyu
{
	string::string(const char* str)
		:_size(strlen(str))
	{
		_capacity = _size;
		_str = new char[_size + 1];
		strcpy(_str, str);
	}
	string::~string()
	{
		delete[]_str;
		_str = nullptr;
		_size = 0;
		_capacity = 0;
	}
	void string::push_back(char ch)
	{
		if (_size == _capacity)
		{
			reserve(_capacity == 0 ? 4 : _capacity * 2);
		}
		_str[_size] = ch;
		_size++;
	}
	void string::append(const char* str)
	{
		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			size_t newCapacity = 2 * _capacity;
			//扩2倍不够,则需多少扩多少
			if (newCapacity < _size + len)
				newCapacity = _size + len;
			reserve(newCapacity);
		}
		strcpy(_str + _size, str);
		_size += len;
	}
	void string::reserve(size_t n)
	{
		if (n > _capacity)
		{
			char* tmp = new char[n + 1];//预留一个空间,因为reserve是内外都好用
			strcpy(tmp, _str);
			delete[]_str;
			_str = tmp;
			_capacity = n;
		}
	}
	string&string:: operator+=(char ch)
	{
		push_back(ch);
		return*this;
	}
	string& string:: operator+=(const char* str)
	{
		append(str);
		return*this;
	}
}

test.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include "string.h"

int main()
{
	Tzuyu::string s2;
	cout << s2.c_str() << endl;
	Tzuyu::string s1("hello world");
	cout << s1.c_str() << endl;
	s1[0] = 'x';
	cout << s1.c_str() << endl;
	Tzuyu::string::iterator it1 = s1.begin();
	while (it1 != s1.end())
	{
		(*it1)--;
		++it1;
	}
	cout << endl;
	it1 = s1.begin();
	while (it1 != s1.end())
	{
		cout << *it1 << " ";
		++it1;
	}
	cout << endl;
	for (auto& ch : s1)
	{
		ch++;
	}
	for (auto ch : s1) 
	{
		cout << ch << " ";
	}
	cout << endl;
	const string s3("xxxxxxxx");
		for(auto& ch : s3)
		{
			//ch++;//不可以这样进行操作,因为auto自动推导的时候发现的是const修饰的,不能修改
			cout << s3 << " ";
		}
		cout << endl;
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自适应企业网站建站系统源码 带完整的安装代码包以及搭建部署教程

系统概述 传统的建站方式往往需要耗费大量的时间和资源&#xff0c;而且对于非专业人士来说&#xff0c;操作难度较大。为了满足企业快速建站的需求&#xff0c;自适应企业网站建站系统源码应运而生。该源码的开发团队致力于打造一款功能齐全、易于操作的建站系统&#xff0c;…

PingCastle:一款针对活动目录AD的安全强化工具

关于PingCastle PingCastle是一款针对活动目录AD的安全强化工具&#xff0c;可以帮助广大研究人员提升活动目录的安全性&#xff0c;该工具甚至可以做到在 20% 的时间内实现 80% 的AD安全性。 Ping Castle 是一种旨在使用基于风险评估和成熟度框架的方法快速评估活动目录AD 安…

power bi制作各季度收入累加柱状图——日期表、calculate、datesytd

一、数据介绍&#xff1a; 2017-2019年订单销售收入数据&#xff08;订单日期&#xff0c;销售收入&#xff09; 二、效果展示&#xff1a; 三、操作步骤&#xff1a; 1、建立日期表 &#xff08;1&#xff09;建立原因 本次度量值编写需要运用到datesytd这一时间智能函数…

2024 IDEA软件 部署tomcat 十二步 运行web页面(html类似的)(中英文对照版本)新手小白易上手

目录 一、准备工作&#xff08;三必备&#xff09;&#xff1a; 1、自己的web项目 2、idea软件&#xff08;我是2023.1.2版本&#xff09; 3、tomcat X.X版本 二 、正式开始步骤&#xff0c;不废话&#xff01;&#xff01; 1、 点击菜单栏中 “File”&#xff08;文件&…

2024年双十一值得入手的好物有哪些?五大性价比拉满闭眼入好物盘点

随着2024年双十一购物狂欢节的临近&#xff0c;消费者们纷纷开始关注各类好物&#xff0c;期待在这一天能够以最优惠的价格入手心仪的商品&#xff0c;在这个特殊的时刻&#xff0c;我们为大家盘点了五大性价比拉满的闭眼入好物&#xff0c;这些产品不仅品质卓越&#xff0c;而…

geoserver发布shp地图

创建新的 存储仓库 file:///var/lib/tomcat9/webapps/geoserver/shp/shengdao/省道.shp 发布图层后&#xff0c;可以看到这个图层的重要attribute 复制&#xff0c;或者 创建新的样式style 这个属性比较讨厌 是 中文的 省 <sld:TextSymbolizer><sld:Label><og…

尚品汇-H5移动端整合系统(五十五)

目录&#xff1a; &#xff08;1&#xff09;运行前端页面 &#xff08;2&#xff09;启动前端页面 &#xff08;3&#xff09;添加搜索分类接口 &#xff08;4&#xff09;购物车模块修改 &#xff08;5&#xff09;登录模块 &#xff08;6&#xff09;订单模块 &#…

ubuntu安装libtorch

Ubuntu20.04安装libtorch 〇、前期准备1、查看NVIDIA显卡算力和CUDA版本支持的算力2、查看CUDA与显卡驱动的版本对应 一、NVIDIA显卡驱动安装1、下载显卡驱动2、安装驱动A. 安装依赖B. 禁用nouveau驱动C. 显卡驱动安装 3、参考 二、CUDA安装1、下载安装CUDA2、测试CUDA是否安装…

今年双11哪些东西值得买?分享五款实用耐用的好物,不再乱花钱!

随着一年一度的1111购物节脚步渐近&#xff0c;是否还在为挑选商品而犹豫不决&#xff1f;别担心&#xff0c;我们贴心整理了一份双十一必买好物推荐&#xff0c;专为追求品质生活的您量身打造。跟随这份清单&#xff0c;让您的数字生活更加丰富多彩&#xff0c;无需多虑&#…

四川财谷通信息技术有限公司抖音小店领域的新势力

在当今这个数字化浪潮汹涌的时代&#xff0c;电子商务已成为推动经济发展的重要引擎&#xff0c;而短视频平台抖音的崛起&#xff0c;更是为电商行业注入了前所未有的活力与机遇。在这片充满无限可能的蓝海中&#xff0c;四川财谷通信息技术有限公司凭借其敏锐的市场洞察力和强…

zabbix监控某特定进程是否挂掉

我现在已经在被监控机器&#xff08;A&#xff09;上装好了zabbix-agent&#xff0c;同时也在zabbix-server网页端添加了机器A 1&#xff0c;确定好要监控的进程 假如我想监控机器A上面的salt-minion这个进程&#xff0c;首先通过ps -ef 找到这个进程的命令启动行。 2&#x…

828华为云征文 | 云服务器Flexus X实例,Docker集成搭建FC-web模拟器

828华为云征文 | 云服务器Flexus X实例&#xff0c;Docker集成搭建FC-web模拟器 华为云端口放行 服务器放行对应端口9995 Docker安装并配置镜像加速 1、购买华为云 Flexus X 实例 Flexus云服务器X实例-华为云 (huaweicloud.com) 2、docker安装 yum install -y docker-ce3、验证…

vue2+elementUI实现handleSelectionChange批量删除-前后端

功能需求&#xff1a;实现选中一个或多个执行批量删除操作 在elementUI官网选择一个表格样式模板&#xff0c;Element - The worlds most popular Vue UI framework 这里采用的是 将代码复制到前端&#xff0c;这里是index.vue <template><el-button type"dang…

JavaScript类型转换和相等性详解

类型转换 10"objects" //10objects,数字10转换为字符串 "7"*"4" //28&#xff0c;两个字符串均转为数字,只要不是加&#xff0c;其他都按两个数字算 var n 1-"x"// NaN&#xff0c;字符串x无法转化为数字 n"objects"//…

眼镜检测系统源码分享

眼镜检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

基础的点云转换

对于点云处理而言&#xff0c;最简单也逃不过的就是点云转换了&#xff0c;我们就从点云转换开始&#xff0c;来一步步完成点云加速的学习。点云基础转换是3D点云处理中的一个重要步骤。它的主要目的是将点云从一个坐标系转换到另一个坐标系中&#xff0c;通常是为了方便后续处…

数据结构:搜索二叉树

前言 在前面我们已经学习了二叉树的基础操作&#xff0c;但是&#xff0c;仅仅是二叉树&#xff0c;没有太大的作用啊&#xff0c;存数据效果没有顺序表和链表好&#xff0c;那为啥还要学二叉树呢&#xff1f; 这不就来了嘛&#xff0c;给二叉树增加一些性质&#xff0c;作用不…

徐州网站建设的最新趋势与技术

随着徐州经济的快速发展&#xff0c;网站建设在当地越来越受到重视。不同类型的企业和组织都希望通过优化他们的在线形象来吸引更多客户。因此&#xff0c;了解目前的趋势与技术是实现高效网站建设的关键。 1. 响应式设计 响应式设计是当前网站建设的核心趋势之一。无论是桌面…

毕业设计选题:基于ssm+vue+uniapp的校园失物招领小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…

基于VITA57.1标准的4通道2.8GSPS 16位JESD204B接口DAC播放子卡

板卡概述 FMC171是一款基于VITA57.1标准的4通道2.8GSPS采样率16位分辨率JESD204B接口DAC回放子卡模块。该板卡采用ADI公司的AD9144&#xff0c;实现4路模拟输出&#xff0c;数字接口通过8通道的JESD204B进行互联。 该板卡支持本地参考时钟、外部输入参考时钟、外部VCO时钟以及…