首页 > 其他分享 >STL——string类的模拟实现

STL——string类的模拟实现

时间:2024-10-14 09:46:53浏览次数:9  
标签:capacity string STL pos len str 模拟 size

一.STL简介

 1. 1什么是STL 

STL(standard template libaray- 标准模板库 ) : C++ 标准库的重要组成部分 ,不仅是一个可复用的 组件库,而且 是一个包罗数据结构与算法的软件框架

1.2 STL的六大组件

接下来开始模拟实现STL中的常用string类

三个成员变量

char* _str;
size_t _size;
size_t _capacity;

二.string类的构造

 不带参构造,直接在初始化列表初始化即可

string()

:_str[nullptr]

,_size[0]

,_capacity[0]

{}

 

带参构造,先开空间,再构造

string(const char* str)

//如果还全在初始化列表

:_size(strlen(str))

,_capacity(_size)

,_str(new[_size+1])

{

strcpy(_str,str);

}

初始化列表是按成员变量的顺序进行初始化,会先对_str进行初始化,这样写就会报错

 

所以带参构造分开来写

string(const char* str)

:_size(strlen(str))
{
_capacity = _size;
_str = new char[_size + 1];
strcpy(_str, str);
}

三.string类的输出

1.传统字符串输出 

字符串也可以像数组一样用[ ]和下标进行访问

string s("abc");

for(size_t i=0;i<s.size();i++)

{

cout<<s[i]<<endl;

}

2. 迭代器,auto,范围for

auto关键字

c++11中,auto 不再是一个存储类型 指示符,而是作为一个新的类型指示符来指示编译器, auto 声明的变量必须由编译器在编译时期 推导而得 auto 声明指针类型时,用 auto auto* 没有任何区别,但用 auto 声明引用类型时则必须加 & 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际 只对第一个类型进行推导,然后用推导出来的类型定义其他变量auto 不能作为函数的参数,可以做返回值,但是建议谨慎使用。 auto 不能直接用来声明数组。 范围for for 循环后的括号由冒号 分为两部分:第一部分是范围 内用于迭代的变量,第二部分则表示被迭代的范围 ,自动迭代,自动取数据,自动判断结束。 范围 for 可以作用到数组和容器对象上进行遍历 范围 for 的底层很简单,容器遍历实际就是替换为迭代器,这个从汇编层也可以看到。 迭代器用法可以看做和指针一样的用法(不等同于指针),所以可以像指针一样解引用来访问字符串里的元素 

string s("abc");

string::iterator it=s.begin();

for(auto e:it)

{

cout<<*it<<" ";

++it;

}

四.string类对字符串进行修改的相关操作 

assign清空然后重新赋值

assign会把原字符串的内容先全清空,然后再赋值为括号里给的字符串

拷贝构造

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

//传统写法
//s1(s2)
string::string(const string& s)
{
    _str = new char[s._capacity + 1];
    strcpy(_str, s._str);
    _size = s._size;
    _capacity = s._capacity;
}
//现代写法
string::string(const string& s)
{
    string tmp(s._str);
    swap(tmp);
}

赋值 

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

//传统写法
string& string::operator=(const string& s)
{
    if (this != &s)
    {
        delete[]_str;
        _str = new char[s._capacity + 1];
        strcpy(_str, s._str);
        _size = s._size;
        _capacity = s._capacity;
    }
    return *this;
}
//现代写法
string& string::operator=(string s)
{
    swap(s);
    return *this;
}

扩容

void string::reserve(size_t n)
{
    if (n > _capacity)
    {
        char* tmp = new char[n + 1];
        strcpy(tmp, _str);
        delete[] _str;
        _str = tmp;

        _capacity = n;
    }
}

 

尾插

尾插字符

void string::push_back(char ch)
{
    if (_size == _capacity)
    {
        reserve(_capacity == 0 ? 4 : 2 * _capacity);
    }
    _str[_size] = ch;
    ++_size;

 尾插字符串

void string::append(const char* str)
{
    size_t len = strlen(str);
    if (_size + len > _capacity)
    {
        size_t newCapacity = 2 * _capacity;
        if (newCapacity < _size + len)
        {
            newCapacity = _size + len;
        }
        reserve(newCapacity);
        
    }
    strcpy(_str + _size, str);
    _size += len;
}

插入

指定位置插入字符

void string::insert(size_t pos,char ch)
{
    assert(pos <= _size);
    if (_size == _capacity)
    {
        reserve(_capacity == 0 ? 4 : 2 * _capacity);
    }
    size_t end = _size + 1;
    while (pos < end)
    {
        _str[end] = _str[end-1];
        --end;
    }
    _str[pos] = ch;
    _size++;

指定位置插入字符串 

void string::insert(size_t pos, const char* str)
{
    assert(pos < _size);
    size_t len = strlen(str);
    if (_size + len > _capacity)
    {
        size_t newCapacity = 2 * _capacity;
        if (_size + len < _capacity)
        {
            _capacity = _size + len;
        }
        reserve(newCapacity);
    }
    size_t end = _size + len;
    while (end > pos + len - 1)
    {
        _str[end] = _str[end - len];
        --end;
    }
    for (size_t i = 0; i < len ; i++)
    {
        _str[pos + i] = str[i];

    }
    _size += len;
}

 

删除 

删除指定位置后的len个字符

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

查找 

查找字符

size_t string::find(char ch, size_t pos)
{
    assert(pos < _size);
    for (size_t i = 0; i < _size; i++)
    {
        if (_str[i] = ch)
        {
            return i;
        }

    }
    return npos;
}

 

查找字符串

 size_t string::find(const char* str, size_t pos)
{
    assert(pos < _size);
    const char* ptr = strstr(_str + pos, str);
    if (ptr == nullptr)
    {
        return npos;
    }
    else
    {
        return ptr - _str;
    }
}

提取 

提取字符串的一部分

string string::substr(size_t pos, size_t len)
{
    assert(pos < _size);
    if (len > (_size - pos))
    {
        len = _size - pos;
    }
    bit::string sub;
    sub.reserve(len);
    for (size_t i = 0; i < len; i++)
    {
        sub += _str[pos + i];

    }
    return sub;
}

 

五.string类对象的容量操作  

  • size() 
    size() 方法返回的是 std::string 对象中当前存储的字符数(不包括结尾的空字符 '\0')。

  •  capacity() 
    capacity() 方法返回的是 std::string 对象在不需要重新分配内存的情况下可以存储的字符的最大数量。这通常是一个大于或等于 size() 的值,因为 std::string 可能会为了效率而预先分配额外的内存空间。 

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;

  • sizeof 运算符
    sizeof 运算符返回的是对象或类型在内存中所占用的字节数。对于 std::string 对象,sizeof 返回的是 std::string 类实例(包括其成员变量,如指向字符数组的指针、大小、容量等)的大小,而不是它实际存储的字符数组的大小。因为 std::string 使用动态内存分配来存储字符数据,所以 sizeof 不会反映这些数据的大小。

标签:capacity,string,STL,pos,len,str,模拟,size
From: https://blog.csdn.net/2401_84107961/article/details/142908281

相关文章

  • 2024/9/16 CSP-S模拟赛试题
    A这题是很有意思的一个题,思路就是你考虑kt的位置只可能在四个角,因为这种情况下,他的距离才会最远对吧,所以你就暴力找另一个人fengwu的点的位置,然后计算他们之间的距离然后你求一个\(\max\)即可,然后记录一下这些\(\max\)的值,最后排个序就好了。代码:#include<bits/stdc++.h>usi......
  • 通过多元蒙特卡罗模拟来预测股票价格的日内波动性
    作者:老余捞鱼原创不易,转载请标明出处及原作者。写在前面的话:    日内价格波动对交易策略的重要性不言而喻,尤其是美跨式交易策略(TheAmericanstraddle)。由于无法预测所有影响股价的因素,本文采用多元蒙特卡罗模拟来测试不同的价格路径,以评估交易策略的成功概率......
  • CSP2024 前集训:多校A层冲刺NOIP2024模拟赛06
    前言写晚了,忙着打abc和scp了。scpT1送,T2T3T4防AK。T1小Z的手套二分答案,双指针进行转移,若差值在\(mid\)范围内则转移,\(O(n\log(v))\)。点击查看代码#include<bits/stdc++.h>#definelllonglong#defineendl'\n'#definesortstable_sortusingnamespace......
  • StringUtils Java字符串工具类
    在我们的代码中经常需要对字符串判空,截取字符串、转换大小写、分隔字符串、比较字符串、拼接字符串、使用正则表达式等等。如果只用String类提供的那些方法,我们需要手写大量的额外代码,不然容易出现各种异常。现在有个好消息是:org.apache.commons.lang3包下的StringUtils工......
  • 【C++】list(STL)
    list的介绍list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。list与forward_list非常相似:最主要的不同在于......
  • Java【String类】
    字符串的本质是字符数组,是由字母、数字、汉字、下划线组成的一串字符。在Java中字符串属于对象。字符串是常量,内容用双引号括起来,在创建之后不能更改,但是可以使用其他变量重新赋值的方法进行更改。目录1.String类创建方式1.1直接创建1.2用new关键字创建2.String类的A......
  • NZOJ 模拟赛7
    T1字符串小X十分热爱学习。有一天,他刚学完“漂亮的k字符串”的概念:给定长度为n的字符串和整数k,k能整除n,如果该字符串满足以下两个条件:s是一个回文串,即对于任意1≤i≤n,Si=Sn+1-i(其中Si表示字符串中第i个字母)s以k为周期,即对于任意1≤i≤n-k,Si=Sk+i(其中Si表示字符串中......
  • C++STL~~map
    文章目录序列式容器和关联式容器一、map的概念二、map的使用三、map&multimap的差异四、map的练习五、总结序列式容器和关联式容器序列式容器前面已经接触过STL中的部分容器如:string、vector、list、deque、array、forward_list等,这些容器统称为序列式容器,因为逻辑......
  • 每日OJ题_牛客_NC101压缩字符串(一)_模拟_C++_Java
    目录牛客_NC101压缩字符串(一)_模拟题目解析C++代码Java代码牛客_NC101压缩字符串(一)_模拟压缩字符串(一)_牛客题霸_牛客网(nowcoder.com)描述:        利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2bc5a3。......
  • 基于Java的ATM机模拟程序设计与实现
    一、引言随着金融行业的发展,ATM机已经成为人们日常生活中不可或缺的一部分。为了更好地理解ATM机的工作原理,本文设计并实现了一个基于Java的ATM机模拟程序。该程序通过模拟ATM机的操作流程,使用户能够体验到ATM机的基本功能。二、系统设计与实现1.用户登录模块用户登录模块......