【c++】string类的使用

2023-12-24 23:36:24

目录

一、标准库中的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;
    }
};

文章来源:https://blog.csdn.net/libj2023/article/details/135096121
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。