STL容器-----string

本文深入探讨了C++标准库中的string类,对比了string与char*的区别,讲解了string的各种操作方法,如push_back、append、find、substr等,并提供了string与wstring的转换方法。同时,还介绍了string类的内部实现原理。

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

string:STL中字符串类型,通常用于表示字符串

string和char*的区别:

string不用考虑内存释放和越界的问题

string类的字符串操作:

const char & opeartor [](int n) const;

const char & at (int n)const;

--------------------------------------------------------------------------

char & operator[](int n);

char & at(int n);

---------------------------------------------------------------------------

char c = str A[3](operator[])

char c = str A.at(5) (at())

正如上面表示的,可是operator和at又有什么区别呢?

区别:

    at在越界会抛异常,operator[]在刚好越界会返回(char)0,再越界会编译错误

如果你想try,catch捕获异常,建议使用at

string和wstring的区别:

string是对char*管理,一个字符占一个字节,一个汉字占两个字节,AS CII 编码

wstring是对wchar_t* 的管理,一个字符占两个字节,一个汉字占两个字节,Unicode编码

string与wstring的转换:

        调用API函数:widechar To MultiByte()和MultiByte To widechar()

        使用ATL的CAZW类与CWAZ类或AZW与WAZ宏

        跨平台:使用CRT库的mbstowcs()和wcstombs(),需设定Locale。

下来我们来关于string的使用和实现

先是了解string各个函数的用法及参数

#include<iostream>
#include"string"
 
//#include"String.h"
//#include"string.cpp"
using namespace std;
void String()
 
{
    string s1;
    string s2("hello");
    string s3(5, 'a');
    string s4(s2);
    string s5(s2, 1);
    cout << s2 << endl;
    cout << s2.capacity() << endl;
    s1 += "sttr";
    cout << s1 << endl;
}
void String1()
{
    string str;
    str.push_back(' '); 
    str.append("hello"); 
    str += 'b'; 
    str += "it"; //追加字符串
    cout << str << endl;
    cout << str.c_str() << endl; // 以C语言的方式打印字符串
 
                                 // 获取file的后缀
    string file1("string.cpp");
    size_t pos = file1.rfind('.');
    string suffix(file1.substr(pos, file1.size() - pos));
    cout << suffix << endl;
 
    string url("http://www.cplusplus.com/reference/string/string/find/");
    cout << url << endl;
    size_t start = url.find("://");
    if (start == string::npos)
    {
        cout << "invalid url" << endl;
        return;
    }
    start += 3;
    size_t finish = url.find('/', start);
    string address = url.substr(start, finish - start);
    cout << address << endl;
 
    // 删除url的协议前缀
    pos = url.find("://");
    url.erase(0, pos + 3);
    cout << url << endl;
}
int main()
{
    String1();
}


注意:调用string时头文件一定引入并且一定要有using naemspace std;

接下来是string的模拟实现:

下面是头文件(.h)

#pragma once
 
#include<iostream>
#include<assert.h>
using namespace std;
namespace bit
{
    class String
    {
    public:
        typedef char* iterator;
        typedef const char* iterator;
        iterator begin()
        {
            return _str;
        }
        iterator end()
        {
            return _str + _size;
        }
        String(const char* str="")
        {
            _size = strlen(str);
            _capacity = _size > 15 ? _size : 15;
            _str = new char[_capacity + 1];
            strcpy(_str, str);
        }
        ~String()
        {
            delete[] _str;
            _str = nullptr;
            _size = _capacity = 0;
        }
        String(const String&s)
            :_str(nullptr)
            , _size(0)
            , _capacity(0)
        {
            String tmp(s._str);
            this->Swap(tmp);
        }
        String& operator=(String s)
        {
            this->Swap(s);
            return *this;
        }//s1 = s2
        char& operator[](size_t pos)
        {
            assert(pos < _size);
            return _str[pos];
        }
        char& operator[](size_t pos)const
        {
            assert(pos < _size);
            return _str[pos];
        }
        size_t Size() const
        {
            return _size;
        }
        size_t capacity()const
        {
            return _capacity;
        }
        const char* c_str()
        {
            return _str;
        }
 
        void Reserve(size_t n);
        void Resize(size_t n, char ch = '\0');
        void PushBack(char ch);
        void Append(const char* str);
        String& operator+=(char ch);
        String& operator+=(const char* str);
        size_t Find(char ch, size_t pos = 0);
        size_t RFind(char ch, size_t pos = npos);
 
        size_t Find(const char* str, size_t pos = 0);
        void Insert(size_t pos, char ch);
        void Insert(size_t pos, const char* str);
        void Erase(size_t pos, size_t len = npos);
        String Substr(size_t pos, size_t len = npos);
        void Swap(String& s)
        {
            swap(_str, s._str);
            swap(_size, s._size);
            swap(_capacity, s._capacity);
        }
 
    private:
        char* _str;
        size_t _size;
        size_t _capacity;
    public:
        static const size_t npos;
 
    };
}


之后就是各个函数的实现(.cpp)

using bit::String;
 
const size_t String::npos = -1;
void String::Reserve(size_t n)
 
{
    if (n > _capacity)
    {
        char* new_str = new char[n + 1];
        strcpy(new_str, _str);
        delete[] _str;
        _str = new_str;
        _capacity = n;
 
    }
}
void String::Resize(size_t n, char ch = '\0')
{
    if (n <= _size)
    {
        _str[n] = '/0';
        _size = n;
    }
    else 
    {
        if (n > _capacity)
        {
            Resize(n);
        }
        size_t pos = _size;
        while (pos < n)
        {
            _str[pos] = ch;
            ++pos;
        }
        _size = n;
        _str[n] = '/0';
    }
}
void String::PushBack(char ch)
{
    /*if (_size == _capacity)
    {
        Resize(1.5*_capacity);
    }
    _str[_size] = ch;
    _size++;
    _str[_size] = '/0';*/
    Insert(_size,ch);
}
void String::Append(const char* str)
{
    /*size_t len = strlen(str);
    if (len + _size > _capacity)
    {
        Resize(len + _size);
    }
    strcpy(_str + _size, str);
    _size += len;*/
    Insert(_size, str);
}
String& String::operator+=(char ch)
{
    this->PushBack;
    return *this;
}
String& String::operator+=(const char* str)
{
    this->Append;
    return *this;
}
size_t String::Find(char ch, size_t pos = 0)
{
    assert(pos < _size);
    while (pos < _size)
    {
        if (_str[pos] = ch)
        {
            return pos;
        }
        pos++;
    }
    return String::npos;
}
size_t String::RFind(char ch, size_t pos = npos)
{
    int end = _size - 1;
    if (pos != String::npos)
    {
        assert(pos < _size);
        end = pos;
    }
    while (end >= 0)
    {
        if (_str[end] = ch)
        {
            return end;
        }
        end--;
    }
    return String::npos;
}
size_t String::Find(const char* str, size_t pos )
{
    assert(pos < _size);
    char* p = strstr(_str + pos, str);
    if (p == nullptr)
    {
        return String::npos;
    }
    else
    {
        return p - _str;
    }
 
 
}
String String::Substr(size_t pos, size_t len)
{
    if (_size - pos < len)
    {
        len = _size - pos;
    }
 
    String sub;
    sub.Reserve(len);
    for (size_t i = pos; i < pos + len; ++i)
    {
        sub += _str[i];
    }
 
    return sub;
}
void String::Insert(size_t pos, char ch)
{
    assert(_size > pos);
    if (_size == _capacity)
    {
        Reserve(1.5*_capacity);
    }
    int end = _size;
    while (end >= (int)pos)
    {
        _str[end + 1] = _str[end];
        --end;
    }
    _str[end] = ch;
    _size++;
 
}
void String::Insert(size_t pos, const char* str)
{
    assert(_size > pos);
    size_t len = strlen(str);
    if (_size = _capacity)
    {
        Reserve(1.5*(_size + len));
    }
    int end = _size;
    while (end > (int)pos)
    {
        _str[end + len] = _str[end];
        --end;
    }
    while (*str)
    {
        _str[pos++] = *str++;
    }
    _size += len;
 
}
void String::Erase(size_t pos, size_t len)
{
    assert(pos < _size);
    if (pos == npos || pos + len > _size)
    {
        _str[pos] = '/0';
        _size = pos;
    }
    else
    {
        for (int i = 0; i < len; i++)
        {
            _str[pos] = _str[pos + len];
            pos++;
        }
        _size -=len;
        _str[_size] = '/0';
 
    }
}


总结:

1. string是表示字符串的字符串类
2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> 
string;
4. 不能操作多字节或者变长字符的序列
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值