C++STL库String类实现

本文介绍了作者在数据结构课设中实现的一个简易myString类,模仿C++ STL库中的String类,包括扩容策略、输入重载、Find()函数(包括KMP算法实现)以及iterator的简化实现。在扩容时,采用了二倍扩容策略,通过realloc优化内存管理。对于输入重载,使用逐字符读取的方式。此外,还讨论了Find()函数的不同实现方式,以及针对迭代器的简化设计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:按照源码中String类的设计方式实现简单的写了一个myString,参考C++官网中的标准stringAPI完成几乎所有的String类的方法,尽量与源码实现风格类似,有部分没实现有的功能之间相似度较高,重复工作意义不大就没写,有的是没办法写。
在这里插入图片描述
亲自在我写的数据结构课设哈弗曼树中使用,没有出现特殊问题,自己测试也没有出问题,如果哪里有错希望大家可以给我指出来。


(一) 关于扩容

在开始写的时候我先查阅相关资料和源码,对与String的扩容,我发现在源码中String的实现里,它预先会有一个16字节的在栈区的缓冲区,如果你的String对象不到16字节,则不会申请堆区内存使用这部分栈区内存,在所占内存较小的情况下,直接使用栈区内存的会增强运行效率,提高CPU cache命中率,而当你使用的string类占据内存过大时,据我查我的系统(Deepin 15.10.1),默认栈内存只开辟8192KB。
在这里插入图片描述
如果String类对象所占内存过大,很有可能程序直接爆栈,所以,在字符串内存高于16字节时,会开辟堆区内存,在源码中,为了节省空间,在这里使用了一个联合体,下面是该联合体结构。
在这里插入图片描述
我自己模拟的结构

enum
    {
   
        BUF_LEN = 16
    };
    union _Bxty {
   
        char _Buf[BUF_LEN];
        char *_ptr;
    } _Bx;

在扩容的时候,我采用一种二倍扩容的方法,我判断字符串占满以申请的空间,我会使用c语言库函数的realloc函数申请一块之前容量两倍的空间,由于在realloc在实现的时候是如果在你当时字符串后面有足够的内存,则直接扩容,如果没有,则在内存足够大的地方申请够内存,然后将数据复制到新内存,然后在free掉老内存,这样处理的效率比较高,既不会经常分配新内存,也不会因为分配内存的占据过多消耗,当时学长说可以自己写一个内存池来处理,我赶着写课设也就没去实现。
这是函数实现

inline void myString::rrsize(size_t x)
{
   
    if (ssize < x)
        _Bx._ptr = (char *)realloc(_Bx._ptr, x * 2);
}

(二)关于输入重载

这里我没有想到很好的解决方案,就很蠢的将字符一个一个读入到临时字符ch中,每次读一个判断是不是’\n’结束符,如果是就结束,返回,如果不是继续读,我的getline也是这样实现的,感觉效率并不高。
下面是代码实现

std::istream &operator>>(std::istream &in, myString &str)
{
   
    char ch;
    /* size_t oldSize = str.size(); */
    bool hasPrevBlank = false;
    while(in.get(ch))
        if(isblank(ch) || ch == '\n'){
   
            hasPrevBlank = true;
        }
        else
            break;
    in.putback(ch);
    str.clear();
    while (in.get(ch)){
   
			if (ch != EOF && !isblank(ch) && ch != '\n'){
   
				str+=ch;
			}
			else
				break;
		}
    return in;
}

std::istream& getline(std::istream& in, myString& str, char delim){
   
		char ch;
		str.clear();
		while (in.get(ch)){
   
			if (ch == delim)
				break;
			else
				str+=ch;
		}
		return in;
}

(三)关于Find()函数的实现

这里我写了两个find函数的实现,其中一个find()函数是直接调用c库函数strstr(),一个是手写KMP算法的fastfind(),听说c++源代码的find函数是使用的BF算法…我个人认为可能是感觉kmp算法还需要申请一段额外空间给next()数组,所以就没有使用,但是我也没具体查真是原因。
代码实现如下
fastfind

const char *myString::getnext(const char *w)
{
   
    int wlen = strlen(w);

    char *next1 = new char[wlen + 1];
    int j = 0, k = -1;
    next1[0] = -1;

    while (j < wlen)
    {
   
        if (k == -1 || w[k] == w[j])
        {
   
            ++k;
            ++j;
            next1[j] = k;
        }
        else
        {
   
            k = next1[k];
        }
    }
    return next1;
}

const char *myString::fastfind(const myString &w)
{
   

    int tlen = w.ssize;
    const char *next1 = getnext(w.c_str());

    int i = 0, j = 0;
    while (j < tlen)
    {
   
        if (i == -1 || w[i] == at(j))
        {
   
            i++;
            j++;
        }
        else
        {
   
            i = next1[i];
        }
    }
    if (next1 != NULL)
    {
   
        delete[] next1;
    }

    if (j == tlen)
    {
   
        return (char *)&at(i - j);
    }
    else
    {
   
        return NULL;
    }
}

find

const char *myString::find(const myString &w) const
{
   
    return strstr(c_str(), w.c_str());
}

(四)关于iterator的实现

因为完整迭代器的实现实在是过于复杂,因此实现了一个比较小的模板类,里面有一套接口是重载了一些比较基础的符号,由于std::string的迭代器属于随机迭代器(Random Access Iterator),我是在写自己的myString,但是由于在写迭代器的过程中,由于很多地方需要判断操作是否合适,我简单写了一个异常处理捕捉到异常时返回一个字符串。

    bool operator>=(const iTerator<value_type> &rhs)
    {
   
        try
        {
   
            if (it != rhs.it)
            {
   
                throw string("迭代器不同,>=无法比较");
            }
            else
            {
   
                return (index >= rhs.index);
            }
        }
        catch (string tp)
        {
   
            std::cerr << tp << std::endl;
        }
    }

就不多说了,直接看源码比较好

iTerator.hpp

#ifndef ITERATOR_HPP
#define ITERATOR_HPP
#include <iostream>

template <typename T>
class iTerator
{
   
public:
    typedef T value_type;
    typedef ptrdiff_t difference_type;
    typedef T *pointer;
    typedef T &reference;

    iTerator():it(nullptr),index(0) {
   }
    iTerator(const value_type *sp):it(sp),index(0) {
   }
    iTerator(const iTerator<value_type> &rhs):it(rhs.it),index(rhs.index){
   }
    iTerator(const value_type *sp, int n):it(sp),index(n) {
   }
    ~iTerator() {
    it = NULL; }

    char operator*(){
   return *(it->data() + index);}

    iTerator<value_type> operator++(int)
    {
   
        iTerator<value_type> copy(*this);
        operator++();
        return copy;
    }

    iTerator<value_type> &operator++()
    {
   
        try
        {
   
            if (it == NULL)
            {
   
                throw "迭代器未初始化";
            }
            else
            {
   
                index++;
                if (index > it->size())
                    it = NULL;
            }
        }
        catch (const char * tp)
        {
   
            std::cerr << tp << std::endl;
        }
        return *this;
    }

    iTerator<value_type> operator--(int)
    {
   
        iTerator<value_type> copy(*this);
        operator--();
        return copy;
    }

    iTerator<value_type> &operator--()
    {
   
        try
        {
   
            if (it == NULL)
            {
   
                throw "迭代器未初始化";
            }
            else
            {
   
                index--;
                if (index > it->size() || index < 0) //越界
                    it = NULL;
            }
        }
        catch (const char * tp)
        {
   
            std::cerr << tp << std::endl;
        }
        return *this;
    }

    bool operator==(const iTerator<value_type> &rhs)
    {
   
        try
        {
   
            if (it != rhs.it)
            {
   
                throw "迭代器不同,==无法比较";
            }
            else
            {
   
                return (it == rhs.it && index == rhs.index);
            }
        }
        catch (const char * tp)
        {
   
            std::cerr << tp << std::endl;
        }
    }

    bool operator!=(const iTerator<value_type> &rhs)
    {
   
        try
        {
   
            if (it != rhs.it)
            {
   
                throw "迭代器不同,!=无法比较";
            }
            else
            {
   
                return !(*this == rhs);
            }
        }
        catch (const char * tp)
        {
   
            std::cerr << tp << std::endl;
        }
    }

    bool operator<(const iTerator<value_type> &rhs)
    {
   
        try
        {
   
            if (it != rhs.it)
            {
   
                throw "迭代器不同,<无法比较";
            }
            else
            {
   
                return (index < rhs.index);
            }
        }
        catch (const char * tp)
        {
   
            std::cerr << tp << std::endl;
        }
    }

    bool operator<=(const iTerator<value_type> &rhs)
    {
   
        try
        {
   
            if (it != rhs.it)
            {
   
                throw "迭代器不同,<=无法比较";
            }
            else
            {
   
                return (index <= rhs.index);
            }
        }
        catch (co
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Randy__Lambert

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值