【c++】string类的使用

目录

一、标准库中的string类

1、简单介绍string类

2、string类的常用接口注意事项

2.1、string类对象的常用构造

2.2、string类对象的容量操作

2.3、string类对象的访问及遍历操作

2.4、string类对象的修改操作

二、string类的模拟实现


一、标准库中的string类

1、简单介绍string类

        (1)string是表示字符串的字符串类;

        (2)string类的接口与常规容器的接口基本相同,在添加了一些专门用来操作string的常规操作;

        (3)string的底层实际是:basic_string模板类的别名,typedef basic_string<char,char_traits,allocator> string;

        (4)不能操作多字节或者变长字符的序列。

2、string类的常用接口注意事项

2.1、string类对象的常用构造

        标准库给出的string类对象常用的构造函数有很多,我们经常用到的主流构造方式有三种:用模板提供的默认构造函数构造空的string类对象、用常量字符串构造string类对象以及用现有的string类对象进行拷贝构造string类对象。

2.2、string类对象的容量操作

        (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的底层空间总大小时,reserve不会改变容量的大小。

2.3、string类对象的访问及遍历操作

        string类对象的访问方式有三种:下标访问、迭代器访问、范围for访问。这里主要讨论迭代器访问方式。

        迭代器是一个类,现阶段可以把迭代器当成一个指针来使用(实际上不一定是指针),迭代器是在类的里边定义的,即内部类,使用方式如:string::iterator。string类中与迭代器搭配使用的成员函数包括begin()、end()、rbegin()、rend()。

2.4、string类对象的修改操作

        string类提供了很多字符串修改接口,需要说的是:在string尾部追加自字符时,s.push_back(c)/s.append(1,c)/s+='c'三种实现方式几乎一样,一般情况下更多的选用+=操作,+=操作不仅可以连接单个字符,还可以连接字符串;对string操作时,如果能够大概预估到待存储字符串的长度,可以先通过reserve把空间预留好。

二、string类的模拟实现

#pragma once
#include<iostream>
using namespace std;
#include<assert.h>

namespace lbj
{
    class string
    {
        friend ostream& operator<<(ostream& _cout, const string& s);
        friend istream& operator>>(istream& _cin, string& s);
        typedef char* iterator;
    public:
        string(const char* str = "")
        {
            _size = strlen(str);
            _capacity = _size;
            _str = new char[_capacity + 1];
            strcpy(_str, str);
        }
        string(const string& s) : _str(nullptr), _size(0), _capacity(0)
        {
            string tmp(s._str);
            this->swap(tmp);
        }
        string& operator=(const string& s)
        {
            if (this != &s)
            {
                string temp(s);
                this->swap(temp);
            }
            return *this;
        }
        ~string()
        {
            if (_str)
            {
                delete[] _str;
                _str = nullptr;
            }
        }

        //

        // iterator
        iterator begin()
        {
            return _str;
        }
        iterator end()
        {
            return _str + _size;
        }


        /

        // modify
        void push_back(char c)
        {
            if (_size == _capacity)
                reserve(_capacity * 2);
            _str[_size++] = c;
            _str[_size] = '\0';
        }
        string& operator+=(char c)
        {   
            push_back(c);
            return *this;
        }
        void append(const char* str)
        {
            int len = strlen(str);
            if (_size + len > _capacity)
            {
                reserve(_size + len);
                //_capacity = _size + len;
            }
            strcpy(_str + _size, str);   //strcpy()会将‘\0’也拷贝过来,所以不需要手动添加'\0'
            _size += len;
        }
        string& operator+=(const char* str)
        {
            append(str);
            return *this;
        }
        void clear()
        {
            _size = 0;
            _str[_size] = '\0';
        }

        void swap(string& s)
        {
            std::swap(_str, s._str);
            std::swap(_size, s._size);
            std::swap(_capacity, s._capacity);
        }

        const char* C_Str()const
        {
            return _str;
        }



        /

        // capacity
        size_t size()const
        {
            return _size;
        }

        size_t capacity()const
        {
            return _capacity;
        }

        bool empty()const
        {
            return _size == 0;
        }

        void resize(size_t newSize, char c = '\0')
        {
            if (newSize > _size)
            {
                // 如果newSize大于底层空间大小,则需要重新开辟空间
                if (newSize > _capacity)
                {
                    reserve(newSize);
                }
                memset(_str + _size, c, newSize - _size);
            }
            _size = newSize;
            _str[newSize] = '\0';
        }

        void reserve(size_t newCapacity)
        {
            // 如果新容量大于旧容量,则开辟空间
            if (newCapacity > _capacity)
            {
                char* str = new char[newCapacity + 1];
                strcpy(str, _str);
                // 释放原来旧空间,然后使用新空间
                delete[] _str;
                _str = str;
                _capacity = newCapacity;
            }
        }



        /

        // access
        char& operator[](size_t index)
        {
            assert(index < _size);
            return _str[index];
        }

        const char& operator[](size_t index)const
        {
            assert(index < _size);
            return _str[index];
        }



        /

        //relational operators
        bool operator<(const string& s)const
        {
            int res = strcmp(_str, s._str);
            if (res < 0)
                return true;
            return false;
        }

        bool operator<=(const string& s)const
        {
            return !(*this > s);
        }

        bool operator>(const string& s)const
        {
            int res = strcmp(_str, s._str);
            if (res > 0)
                return true;
            return false;
        }

        bool operator>=(const string& s)const
        {
            return !(*this < s);
        }

        bool operator==(const string& s)const
        {
            int res = strcmp(_str, s._str);
            if (res == 0)
                return true;
            return false;
        }

        bool operator!=(const string& s)const
        {
            return !(*this == s);
        }



        // 返回c在string中第一次出现的位置
        size_t find(char c, size_t pos = 0) const
        {
            for (size_t i = pos; i < _size; ++i)
            {
                if (_str[i] == c)
                    return i;//找到,返回下标
            }
            return -1;//未找到
        }

        // 返回子串s在string中第一次出现的位置
        size_t find(const char* s, size_t pos = 0) const
        {
            assert(s);
            assert(pos < _size);
            const char* src = _str + pos;
            while (*src)
            {
                const char* match = s;//如果不匹配,返回子串起始处重新查找
                const char* cur = src;
                while (*match && *match == *cur)//结束条件
                {
                    ++match;
                    ++cur;
                }
                if (*match == '\0')//找到子串
                {
                    return src - _str;//返回下标
                }
                else
                {
                    ++src;
                }
            }
            return -1;//未找到
        }

        // 在pos位置上插入字符c/字符串str,并返回该字符的位置
        string& insert(size_t pos, char c)
        {
            assert(pos <= _size);
            if (_size > _capacity)
            {
                //扩容
                char* newstr = new char[_capacity * 2 + 1];//开空间
                strcpy(newstr, _str);
                delete[] _str;
                _str = newstr;
                _capacity *= 2;
                //Expand(_capacity * 2);
            }

            //移数据
            for (int i = _size; i >= (int)pos; --i)
            {
                _str[i + 1] = _str[i];
            }
            _str[pos] = c;
            _size++;
            return *this;
        }

        string& insert(size_t pos, const char* str)
        {
            size_t len = strlen(str);
            if (_size + len > _capacity)//扩容
            {
                //扩容
                char* newstr = new char[_capacity * 2 + 1];//开空间
                strcpy(newstr, _str);
                delete[] _str;
                _str = newstr;
                _capacity *= 2;
                //Expand(_size + len);
            }

            //后移数据
            for (int i = _size; i >= (int)pos; --i)
            {
                _str[len + i] = _str[i];
            }

            //拷贝字符串
            while (*str != '\0')
            {
                _str[pos++] = *str++;
            }
            _size += len;
            return *this;
        }

        // 删除pos位置上的元素,并返回该元素的下一个位置
        string& erase(size_t pos, size_t len)
        {
            assert(pos < _size);
            if (pos + len >= _size)//pos位置之后全为0
            {
                _str[pos] = '\0';
                _size = pos;
            }
            else
            {
                strcpy(_str + pos, _str + pos + len);
                _size -= len;
            }
            return *this;
        }

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

    //输入流重载
    istream& operator>>(istream& _cin, string& s)
    {
        //预分配100个空间
        char* str = (char*)malloc(sizeof(char) * 100);
        char* buf = str;
        int i = 1;
        //预处理:跳过流里面的所有空格和回车
        while ((*buf = getchar()) == ' ' || (*buf == '\n'));
        for (; ; ++i)
        {
            if (*buf == '\n') //回车跳出
            {
                *buf = '\0';
                break;
            }
            else if (*buf == ' ') //空格跳出
            {
                *buf = '\0';
                break;
            }
            else if (i % 100 == 0) //空间不足
            {
                i += 100; //追加100个空间
                str = (char*)realloc(str, i);
            }
            else  //每次getchar()一个值
            {
                buf = (str + i);//为了避免realloc返回首地址改变,不使用++buf,而是用str加上偏移.
                //每次读取一个字符
                *buf = getchar();
            }
        }
        //输入完成,更新s
        s._str = str;
        s._capacity = s._size = i;
        return _cin;
    }

    //输出流重载
    ostream& operator<<(ostream& _cout, const string& s)
    {
        for (size_t i = 0; i < s.size(); ++i)
        {
            _cout << s[i];
        }
        return _cout;
    }
};

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

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

相关文章

jQuery: 整理3---操作元素的内容

1.html("内容") ->设置元素的内容&#xff0c;包含html标签&#xff08;非表单元素&#xff09; <div id"html1"></div><div id"html2"></div>$("#html1").html("<h2>上海</h2>") …

【期末考试】计算机网络、网络及其计算 考试重点

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 计算机网络及其计算 期末考点 &#x1f680;数…

Flink 客户端操作命令及可视化工具

Flink提供了丰富的客户端操作来提交任务和与任务进行交互。下面主要从Flink命令行、Scala Shell、SQL Client、Restful API和 Web五个方面进行整理。 在Flink安装目录的bin目录下可以看到flink&#xff0c;start-scala-shell.sh和sql-client.sh等文件&#xff0c;这些都是客户…

面向船舶结构健康监测的数据采集与处理系统(一)系统架构

世界贸易快速发展起始于航海时代&#xff0c;而船舶作为重要的水上交通工具&#xff0c;有 其装载量大&#xff0c;运费低廉等优势。但船舶在运营过程中出现的某些结构处应力值 过大问题往往会给运营部门造成重大的损失&#xff0c;甚至造成大量的人员伤亡和严重 的环境污染…

【网络安全/CTF】unseping 江苏工匠杯

该题考察序列化反序列化及Linux命令执行相关知识。 题目 <?php highlight_file(__FILE__);class ease{private $method;private $args;function __construct($method, $args) {$this->method $method;$this->args $args;}function __destruct(){if (in_array($thi…

Kali Linux—借助 SET+MSF 进行网络钓鱼、生成木马、获主机shell、权限提升、远程监控、钓鱼邮件等完整渗透测试(三)

钓鱼邮件 当攻击者制作了钓鱼网站、木马程序后&#xff0c;便会想法设法将其传给受害者&#xff0c;而常见的传播方式便是钓鱼网站了。安全意识较差的用户在收到钓鱼邮件后点击邮件中的钓鱼链接、下载附件中的木马程序&#xff0c;便可能遭受攻击&#xff01; 工具简介 Swak…

Altium Designer(AD24)新工程复用设计文件图文教程及视频演示

&#x1f3e1;《专栏目录》 目录 1&#xff0c;概述2&#xff0c;复用方法一视频演示2.1&#xff0c;创建工程2.2&#xff0c;复用设计文件 3&#xff0c;复用方法二视频演示4&#xff0c;总结 欢迎点击浏览更多高清视频演示 1&#xff0c;概述 本文简述使用AD软件复用设计文件…

Adobe Photoshop Lightroom各版本安装指南

下载链接​ https://pan.baidu.com/s/1FiqQUcMJu3TrLRWFpaaX3A?pwd0531 #2024版 1.鼠标右击【Lrc2024(64bit)】压缩包&#xff08;win11及以上系统需先点击“显示更多选项”&#xff09;【解压到 Lrc2024(64bit)】。 2.打开解压后的文件夹&#xff0c;鼠标右击【Setup】选择…

2024-AI人工智能学习-安装了pip install pydot但是还是报错

2024-AI人工智能学习-安装了pip install pydot但是还是报错 出现这样子的错误&#xff1a; /usr/local/bin/python3.11 /Users/wangyang/PycharmProjects/studyPython/tf_model.py 2023-12-24 22:59:02.238366: I tensorflow/core/platform/cpu_feature_guard.cc:182] This …

基于YOLOv7算法的高精度实时海洋生物检测识别系统(PyTorch+Pyside6+YOLOv7)

摘要&#xff1a;基于YOLOv7算法的高精度实时海洋生物目标检测系统可用于日常生活中检测与定位海胆、海参、扇贝和海星&#xff0c;此系统可完成对输入图片、视频、文件夹以及摄像头方式的目标检测与识别&#xff0c;同时本系统还支持检测结果可视化与导出。本系统采用YOLOv7目…

嵌入式开发——DMA外设到内存

学习目标 加强理解DMA数据传输过程加强掌握DMA的初始化流程掌握DMA数据表查询理解源和目标的配置理解数据传输特点能够动态配置源数据学习内容 需求 uint8_t data; 串口接收(&data);data有数据了 实现串口的数据接收,要求采用dma的方式。 数据交互流程 CPU配置好DMA外…

jvm对象探究

hostpot虚拟机对象探究 jvm虚拟机创建对象的流程 ava虚拟机&#xff08;JVM&#xff09;创建对象的过程包括以下步骤&#xff1a; 类加载&#xff1a; 首先&#xff0c;JVM会检查对象的类是否已经被加载。如果该类还没有被加载&#xff0c;JVM会通过类加载器加载该类的字节码…

实在没货,简历(软件测试)咋写?

简历咋写&#xff0c;这是很多没有【软件测试实际工作经验】的同学们非常头疼的事情。 简历咋写&#xff1f;首先你要知道简历的作用。 简历的作用是啥呢&#xff1f; 一句话就是&#xff1a;让HR小姐姐约你。 如何让HR看你一眼&#xff0c;便相中你的简历&#xff0c;实现在众…

50 个具有挑战性的概率问题 [01/50]:袜子抽屉

一、说明 我最近对与概率有关的问题产生了兴趣。我偶然读到了弗雷德里克莫斯特勒&#xff08;Frederick Mosteller&#xff09;的《概率论中的五十个具有挑战性的问题与解决方案》&#xff08;Fifty Challenge Problems in Probability with Solutions&#xff09;一书。我认为…

React AntDesign form表单文件上传 nodejs formidable 接受参数并把文件放置后端项目相对目录指定文件夹下面

umijs/max 请求方法 // 上传文件改成form表单 export async function uploadFile(data, options) {return request(CMMS_UI_HOST /api/v1/uploadFile, {method: POST,data,requestType: form,...(options || {}),}); }前端调用方法 注意upload组件上传 onChange的如下方法&am…

51单片机的羽毛球计分器系统【含proteus仿真+程序+报告+原理图】

1、主要功能 该系统由AT89C51单片机LCD1602显示模块按键等模块构成。适用于羽毛球计分、乒乓球计分、篮球计分等相似项目。 可实现基本功能: 1、LCD1602液晶屏实时显示比赛信息 2、按键控制比赛的开始、暂停和结束&#xff0c;以及两位选手分数的加减。 本项目同时包含器件清…

不同文化背景下,如何调整绩效管理策略以适应不同的价值观和工作习惯

在不同文化背景下调整绩效管理策略以适应不同的价值观和工作习惯是一个复杂而关键的过程。以下是一些建议&#xff1a; 了解并尊重文化差异&#xff1a; 首先&#xff0c;需要深入了解不同文化背景下的价值观、工作习惯、沟通方式等。这包括对个人空间、权威、时间观念、团队…

Skywalking 中 Agent 自动同步配置源码解析

文章目录 前言正文实现架构实现模型OAP 同步 ApolloConfigWatcherRegisterConfigChangeWatcher Agent 侧 前言 本文代码 OAP 基于 v9.7&#xff0c;Java Agent 基于 v9.1&#xff0c;配置中心使用 apollo。 看本文需要配合代码“食用”。 正文 Skywalking 中就使用这种模型…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Image图片组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Image图片组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Image组件 Image 用来加载并显示图片的基础组件&#xff0c;它支持从内存、本…