string接口[小白理解篇]

作文目的

本文是为了加深对string底层函数的一点理解(请勿与底层源码混为一谈),下面从模拟与注意项出发。

一.string 功能化模拟

1.迭代器模拟

迭代器,为实现简单便理解故使用指针的方式(非说明迭代器使用该方法实现)。其中的begin、end都是为了给迭代器提供范围。迭代器也只认该俩函数(不可使用其他名称)。

typedef  char* iterator;
 typedef  const char* const_iterator;
 const_iterator begin()const {
     return _str;
 }
 const_iterator end()const {
     return _str + _size;
 }
 iterator begin(){
        return _str;
  }
 iterator end(){
       return _str + _size;
 }
 char& operator[](size_t pos)const{
     assert(pos<_size);
     return _str[pos]; 
 }
 const char operator[](size_t pos)const{
      assert(pos<_size);
     return _str[pos];
 }

2.reserve模拟

该模拟块的实现在于空间的扩展,该处的空间扩展方案并不受限制 可自行选择。切记释放空间,防止空间浪费(好习惯)。

void reserve(size_t sub){
    if(sub>_capacity){
        char* ret=new char[sub+1];
        delete []_str;
        _str=ret;
        _capacity=sub;
        }
 }

3.resize模拟实现块

该模块的实现需要分清情况,他是要扩大有效值范围,还是缩小范围,如果扩大是否有填充值,最大空间是否能够容纳,如:在不定义填充值时补充缺省值 \0,即不改变数据也扩大了空间,也能在需要时不必重构函数接口。

void resize(size_t size,char ch='\0'){
    if(size<_size){
        _str[size]='\0';
        }
    else{
        //可省略判断
        if(size>_capacity){
        reserve(size);
        }
        for(int i =_size;i<size;i++)
        {
            _str[i]=ch;    
        }
        _str[size]='\0';
     }
     _size=size;
 }

4.insert 模拟实现块

在insert接口,不仅仅要实现单字符的插入,还要可插入字符串的能力;同时不管_str中是否有值

都要追加值,但是如果指定插入点超出实际有效值长时,也必须处理。其次空间不足时也得先扩充空间,不然会出现错误访问。

 void insert(size_t pos, char ch) {
     assert(pos <= _size);
     if (_size == _capacity) {
             reserve(_capacity == 0 ? 4 : 2 * _capacity);
     }
     //腾出一块空间,将pos之后的数据后移
     size_t end = _size + 1;
     while (end > pos) {
         _str[end] = _str[end - 1];
         end--;
     }
     _str[pos] = ch;
     _size++;
 }
 void insert(size_t pos, const char* str) {
     assert(pos <= _size);
     int size = strlen(str);
     if (size + _size > _capacity) {
         reserve(size + _size);
     }
     int end = _size + size;
      //下标
     while (end > _size + size-1) {
         _str[end] = _str[end - size];
         end--;
     }
     //在pos位置开始拷贝插入size个
     strncpy(_str + pos, str,size);
     _size += size;
 }

5.erase模拟实现块

该接口主在优化,当len大于_size,则一定是全删,不必浪费时间去处理,只有有值得有效调动是 才前移数据。

void erase (size_t pos = 0, size_t len = npos)
{
    assert (pos <_size);
    if(len>=_size-pos){  
     _str[pos]='\0';
    }
    else{
        while (_size>pos+len)
        {
            _str[pos]=_str[pos+len];
            pos++;
         }
      }
   _size-=pos
}

6.find模拟实现块

find查找函数,与平时写的查找函数没什么区别,无非就是别越界。

size_t find (char c, size_t pos = 0) const;
{
    assert(pos<_size);
    for(int i=pos;i<_size;i++){
        if(_s[i]==c){
            return i;
        }
    }
    return npos;
}
size_t find (const char* c, size_t pos = 0) const;
{
    assert(pos<_size);
    const char*p=strstr(_str+pos,c);
    if(p)
    return p-_str;
    else
    return npos;
}

7.substr模拟实现块

截取函数,顾名思义就是截取指定长度中有的效数据,当指定截取范围远大于有效范围是就只截取有效范围内的数据。

string substr (size_t pos = 0, size_t len = npos) const
{
    assert(pos<_size);
    string st="";
    if(len>=_size-pos)
    {
        for(int i=pos;i<_size;i++)
        {
              st+=_str[i];      
        }    
    }
    else{
         for(int i=pos;i<pos+len;i++)
        {
              st+=_str[i];      
        }       
    }
    return st;
}

8.输入流

第一个代码并非有错误,但是他不太胜任这份工作,他对接口的调用太过于频繁,产生极大且不必要的浪费,故代码二采用模拟缓冲区的办法减轻对接口的调用浪费。

ps: in.get()是输入流提供的一个接收缓冲区单字符的接口,弥补cin不能读储空字符与换行符的缺点

ps: clear每次插入数据,都是一个新值,故清空空间。

/*istream& operator>> (istream& is, string& str)
 {
     str.clear();
     char ch;
     ch=is.get();
     while(ch!=' '&&ch!='\n'){
     ch=is.get();
     str+=ch;
     }
return str;
}
*/
istream& operator>> (istream& is, string& str)
 {
      str.clear();
     int i=0;char ch;
     char buff[128]="";
     ch=is.get();
     while(ch!=' '&&ch!='\n'){
         buff[i]=ch;
         i++;
         if(i==127)
         {
             buff[127]='\0';
             i=0;
             str+=buff;         
         }
         ch=is.get();
     }
     buff[i]='\0';
     str+=buff;
     return is;
 }
 istream& getlien(istream& is, string& str)
  {
      str.clear();
     int i=0;char ch;
     char buff[128]="";
     ch=is.get();
     while(ch!='\n'){
         buff[i]=ch;
         i++;
         if(i==127)
         {
             buff[127]='\0';
             i=0;
             str+=buff;         
         }
         ch=is.get();
     }
     buff[i]='\0';
     str+=buff;
     return is;
 }

9.拷贝函数

两种方法都是按同一个方向指向,仅方法实现不同。

// s2(s1)
/*string(const string& s)
{
	_str = new char[s._capacity + 1];
	strcpy(_str, s._str);
	_size = s._size;
	_capacity = s._capacity;
}*/

// s1 = s3;
/*string& operator=(const string& s)
{
	char* tmp = new char[s._capacity + 1];
	strcpy(tmp, s._str);

	delete[] _str;
	_str = tmp;
	_size = s._size;
	_capacity = s._capacity;

	return *this;
}*/

string(string &str){
        string tmp(str);
        swap(str);
 }
 string& operator+(string str){
     swap(str);
     return *this;
}

二.完整版

#pragma once
#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<assert.h>
using namespace std;
namespace bit {
    class string {
    public:
        typedef  char* iterator;
        typedef  const char* const_iterator;
        const_iterator begin()const {
            return _str;
        }
        const_iterator end()const {
            return _str + _size;
        }
        iterator begin() {
            return _str;
        }
        iterator end() {
            return _str + _size;
        }
        string(const char* str = " ")
            :_size(strlen(str))
        {
            _str = new char[_size + 1];
            strcpy(_str, str);
            _capacity = _size;
        }
        string(const string &str)
        {
            string tmp(str._str);
            swap(tmp);
           
        }
        string& operator=( string str)
        {
            swap(str);
            return *this;
        }
        ~string(){
            delete[] _str;
            _str= nullptr;
            _size = _capacity = 0;
        }
        size_t size()const {
            return _size;
        }
        const char* c_str()const {
            return _str;
        }
        size_t capacity() {
            return _capacity;
        }
        void clear() {
            _str[0] = '\0';
            _size = 0;
        }
        const char& operator[](size_t i)const {
            assert(i < _size);
            return _str[i];
        }
        char& operator[](size_t i) {
            assert(i < _size);
            return _str[i];
        }
        void reserve(size_t sub) {
            if (sub > _capacity) {
                char* ret = new char[sub + 1];
                strcpy(ret, _str);
                delete[] _str;
                _str = ret;
                _capacity = sub;
            }
        }
        void resize(size_t size, char ch = '\0') {
            if (size <= _size) {
                _str[size] = '\0';
                _size = size;
                
            }
            else {
                if (size > _capacity) {
                    reserve(size);
                }
                for (int i = _size; i < size; i++)
                {
                    _str[i] = ch;
                }
                _str[size] = '\0';
                _size = size;
                
            }
        }
        void insert(size_t pos, char ch) {
            assert(pos <= _size);
            if (_size == _capacity) {
                reserve(_capacity == 0 ? 4 : 2 * _capacity);
            }
            size_t end = _size + 1;
            while (end > pos) {
                _str[end] = _str[end - 1];
                end--;
            }
            _str[pos] = ch;
            _size++;
        }
        void insert(size_t pos, const char* str) {
            assert(pos <= _size);
            int size = strlen(str);
            if (size + _size > _capacity) {
                reserve(size + _size);
            }
            int end = _size + size;
            while (end > pos+size-1) {
                _str[end] = _str[end - size];
                end--;
            }
            strncpy(_str + pos, str, size);
            _size += size;
        }

        void append(const char* str) {
            insert(_size, str);
        }
        void push_back(const char ch) {
            insert(_size, ch);
        }

        string& operator+= (const char* s) {
            append(s);
            return *this;
        }
        string& operator+= (const char s) {
            push_back(s);
            return *this;
        }
        void erase(size_t pos = 0, size_t len = npos) {
            assert(pos < _size);
            if (len >= _size) {
                _str[pos]= '\0';
            }
            else {
                while (_size > pos + len)
                {
                    _str[pos]=_str[pos + len];
                    pos++;
                }
                _str[pos]= '\0';
            }
            _size -= pos;
        }
        void swap(string& str) {
            std::swap(_str, str._str);
            std::swap(_size, str._size);
            std::swap(_capacity, str._capacity);
        }
        size_t find(char c,size_t pos=0)const
        {
            assert(pos < _size);
            for (int i = pos; i < _size; i++) {
                if (_str[i]== c) {
                    return i;
                }
            }
            return npos;
        }
        size_t find(const char* c, size_t pos = 0) const
        {
            assert(pos <= _size);
            const char* p = strstr(_str + pos, c);
            if (p)
                return p - _str;
            else
                return npos;
        }
        string substr(size_t pos = 0, size_t len = npos) const
        {
            string st = " ";
            assert(pos <= _size);
            
            if (len >= _size- pos)
            {
                for (size_t i = pos; i< _size;i++)
                {
                    st+=_str[i];
                }
            }
            else{
                for (size_t i = pos; i< pos + len;i++)
                {
                    st+=_str[i];
                }
            }
            return st;
        }
        static const int npos;
    private:
        char* _str = nullptr;
        size_t _size = 0;
        size_t _capacity = 0;

    };
    const int string::npos = -1;
    void swap(string& rhs, string& lhs) {
        rhs.swap(lhs);
    }

    bool operator==(const string& rhs, const string& lhs) {
        return !strcmp(rhs.c_str(), lhs.c_str());
    }
    bool operator!=(const string& rhs, const string& lhs) {
        return !(rhs == lhs);
    }
    bool operator>(const string& rhs, const string& lhs) {
        return strcmp(rhs.c_str(), lhs.c_str());
    }
    bool operator>=(const string& rhs, const string& lhs) {
        return rhs == lhs || rhs > lhs;
    }
    bool operator<(const string& rhs, const string& lhs) {
        return !(rhs >= lhs);
    }
    bool operator<=(const string& rhs, const string& lhs) {
        return (rhs == lhs) || (rhs < lhs);
    }
    ostream& operator<<(ostream& os, const string& str)
    {
        for (auto ret :str)
        {
            os << ret;
        }
        return os;
    }
    istream& operator>> (istream& is, string& str)
    {
        str.clear();
        int i = 0; char ch;
        char buff[128] = "";
        ch = is.get();
        while (ch != ' ' && ch != '\n') {
            buff[i]=ch;
            i++;
            if (i == 127)
            {
                buff[128]='\0';
                i = 0;
                str+=buff;
            }
            ch = is.get();
        }
        buff[i]= '\0';
        str+=buff;
        return is;
    }
    istream& getline(istream& is, string& str)
    {
        str.clear();
        size_t i = 0; char ch;
        char buff[128] = "";
        ch = is.get();
        while (ch != '\n') {
            buff[i] = ch;
            i++;
            if (i == 127)
            {
                buff[127] = '\0';
                str += buff;
                i = 0;
                
            }
            ch = is.get();
        }if (i > 0) {
            buff[i] = '\0';
            str += buff;
        }
        return is;
    }
}

 本文多在理解,感谢观看!

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

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

相关文章

【论文笔记合集】ARIMA 非平稳过程通过差分转化为平稳过程

本文作者&#xff1a; slience_me 文章目录 ARIMA 非平稳过程通过差分转化为平稳过程文章原文具体解释详解参照 ARIMA 非平稳过程通过差分转化为平稳过程 文章原文 Many time series forecasting methods start from the classic tools [38, 10]. ARIMA [7, 6] tackles the fo…

爬虫入门到精通_框架篇16(Scrapy框架基本使用)_名人名言的抓取

1 目标站点分析 抓取网站&#xff1a;http://quotes.toscrape.com/ 主要显示了一些名人名言&#xff0c;以及作者、标签等等信息&#xff1a; 点击next&#xff0c;page变为2&#xff1a; 2 流程框架 抓取第一页&#xff1a;请求第一页的URL并得到源代码&#xff0c;进行下…

避免阻塞主线程 —— Web Worker 示例项目

前期回顾 迄今为止易用 —— 的 “盲水印“ 实现方案-CSDN博客https://blog.csdn.net/m0_57904695/article/details/136720192?spm1001.2014.3001.5501 目录 CSDN 彩色之外 &#x1f4dd; 前言 &#x1f6a9; 技术栈 &#x1f6e0;️ 功能 &#x1f916; 如何运行 ♻️ …

Linux 部署 Samba 服务

一、Ubuntu 部署 Samba 1、安装 Samba # 更新本地软件包列表 sudo apt update# 安装Samba sudo apt install samba# 查看版本 smbd --version2、创建共享文件夹&#xff0c;并配置 Samba 创建需要共享的文件夹&#xff0c;并赋予权限&#xff1a; sudo mkdir /home/test sud…

深度学习PyTorch 之 LSTM-中文多分类

LSTM 代码流程与RNN代码基本一致&#xff0c;只是这里做了几点优化 1、数据准备 数据从导入到分词&#xff0c;流程是一致的 # 加载数据 file_path ./data/news.csv data pd.read_csv(file_path)# 显示数据的前几行 data.head()# 划分数据集 X_train, X_test, y_train, y_…

【UE5】非持枪趴姿移动混合空间

项目资源文末百度网盘自取 创建角色在非持枪状态趴姿移动的动画混合空间 在BlendSpace文件夹中单击右键选择 动画(Animation) 中的混合空间(Blend Space) 选择SK_Female_Skeleton 命名为BS_NormaProne 打开BS_NormaProne 水平轴表示角色的方向&#xff0c;命名为Directi…

Vue2 父子组件某一属性的双向绑定

原本&#xff1a;父组件使用props传值给孩子组件初始化&#xff0c;触发事件子组件使用$emit传值给父组件&#xff0c;很麻烦后来&#xff1a;使用computed和$event例子代码&#xff1a; <template><div class"box">grandpa <el-input v-model"…

pta—剪切粘贴

使用计算机进行文本编辑时常见的功能是剪切功能&#xff08;快捷键&#xff1a;Ctrl X&#xff09;。请实现一个简单的具有剪切和粘贴功能的文本编辑工具。 工具需要完成一系列剪切后粘贴的操作&#xff0c;每次操作分为两步&#xff1a; 剪切&#xff1a;给定需操作的起始位置…

《深入解析 C#》—— C# 2 部分

文章目录 第二章 C# 22.1 泛型&#xff08;*&#xff09;2.2 default 和 typeof&#xff08;*&#xff09;2.3 可空值类型2.3.1 Nullable<T> 结构体&#xff08;framework 支持&#xff09;2.3.2 装箱&#xff08;CLR 支持&#xff09;2.3.3 “?”后缀&#xff08;语法支…

蓝桥杯(1):python排序

1 基础 1.1 输出 1.1.1 去掉输出的空格 print("Hello","World",123,sep"") print("hello",world,123,sep) print(hello,world,123) #输出结果 #HelloWorld123 #helloworld123 #hello world 123 1.1.2 以不同的方式结尾 print(&quo…

【Android】AOSP 架构

Android 官网对 AOSP 结构图进行了更新&#xff0c;如下所示&#xff1a; Android 应用&#xff08;Android Apps&#xff09; 完全使用 Android API 开发的应用。在某些情况下&#xff0c;设备制造商可能希望预安装 Android 应用以支持设备的核心功能。 特权应用&#xff08…

先验分布、后验分布、极大似然的一点思考

今天和组里同事聊天的时候&#xff0c;无意中提到了贝叶斯统计里先验分布、后验分布、以及极大似然估计这三个概念。同事专门研究如何利用条件概率做系统辨识的&#xff0c;给我画了一幅图印象非常深刻&#xff1a; 其中k表示时序关系。上面这个图表示后验分布是由先验分布与似…

怎样在CSDN赚点零花钱

请教一下各位大佬&#xff0c;看到你们在CSDN很多都几万粉丝以上&#xff0c;能不能分享一下有什么涨粉的经验&#xff0c;还有怎样转化为额外收益……感谢各位提供宝贵的经验&#xff0c;谢谢……

rviz上不显示机器人模型(模型只有白色)

文档中的是base_footprint&#xff0c;需要根据自己所设的坐标系更改&#xff0c;我的改为base_link 如何查看自己设的坐标系&#xff1a; 这些parent父坐标系就是 同时打开rviz后需要更改成base_link

Kubernetes operator系列:kubebuilder 实战演练 之 开发多版本CronJob

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 Kubernetes operator学习 系列文章&#xff0c;本节会在上一篇开发的Cronjob基础上&#xff0c;进行 多版本Operator 开发的实战 本文的所有代码&#xff0c;都存储于github代码库&#xff1a;https://github.c…

几何相互作用GNN预测3D-PLA

预测PLA是药物发现中的核心问题。最近的进展显示了将ML应用于PLA预测的巨大潜力。然而,它们大多忽略了复合物的3D结构和蛋白质与配体之间的物理相互作用,而这对于理解结合机制至关重要。作者提出了一种结合3D结构和物理相互作用的几何相互作用图神经网络GIGN,用于预测蛋白质…

Android studio 性能调试

一、概述 Android studio 的Profiler可用来分析cpu和memory问题&#xff0c;下来进行说明介绍。 二、Android studio CPU调试 从开发模拟器或设备中启动应用程序&#xff1b; 在 Android Studio 中&#xff0c;通过选择View > Tool Windows > Profiler启动分析器。 应…

VMware workstation的安装

VMware workstation安装&#xff1a; 1.双击VMware-workstation-full-9.0.0-812388.exe 2.点击next进行安装 选择安装方式 Typical&#xff1a;典型安装 Custom&#xff1a;自定义安装 选择程序安装位置 点击change选择程序安装位置&#xff0c;然后点击next 选择是否自动…

D-Star 寻路算法

D-Star 寻路算法 下面简写 D-Star 为 D* D算法&#xff1a;D 算法”的名称源自 Dynamic A Star,最初由Anthony Stentz于“Optimal and Efficient Path Planning for Partially-Known Environments”中介绍。它是一种启发式的路径搜索算法&#xff0c; 适合面对周围环境未知或者…

借助 Terraform 功能协调部署 CI/CD 流水线-Part2

在第一部分的文章中&#xff0c;我们介绍了3个步骤&#xff0c;完成了教程的基础配置&#xff1a; 使用 Terraform 创建 AWS EKS Infra在 EKS 集群上部署 ArgoCD 及其依赖项设置 Bitbucket Pipeline并部署到 ECR Repo 本文将继续完成剩余的步骤&#xff0c;以实现 Terraform 编…