c++的string一键介绍

简介: 这篇文章旨在帮助读者回忆如何使用string,并提醒注意事项。它不是一篇详细的功能介绍,而是一篇润色文章。先展示重载函数,如果该函数一笔不可带过,就先展示英文原档(附带翻译),最后展示代码实现与举例可以直接去看英文文档,也可以看本篇文章,但是更建议去看英文原档。那么废话少说直接开始进行挨个介绍。


前言:
这篇文章旨在帮助读者回忆如何使用string,并提醒注意事项。它不是一篇详细的功能介绍,而是一篇润色文章。

先展示重载函数,如果该函数一笔不可带过,就先展示英文原档(附带翻译),最后展示代码实现与举例

这里先提供c++官网相关链接:cplusplus.com/reference/string/

可以直接去看英文文档,也可以看本篇文章,但是更建议去看英文原档。

那么废话少说直接开始进行挨个介绍

Member functions:
1:std::basic_string::basic_string构造函数
进行初始化,c++的官方给了很多的初始化重载函数,也完美应对了我们不同的要求,看来c++祖师爷还是很细心的。

include

include

using namespace std;

int main()
{
string s0("Initial string");

// constructors used in the same order as described above:
string s1;
string s2(s0);
string s3(s0, 8, 3);
string s4("A character sequence", 6);
string s5("Another character sequence");
string s6(10, 'x');
string s7a(10, 42);
string s7b(s0.begin(), s0.begin() + 7);

cout << "s1: " << s1 << "\ns2: " << s2 << "\ns3: " << s3;
cout << "\ns4: " << s4 << "\ns5: " << s5 << "\ns6: " << s6;
cout << "\ns7a: " << s7a << "\ns7b: " << s7b << '\n';
return 0;

}

2:std::basic_string::~basic_string析构函数
析构函数官方没有给详细解释,应该走的是默认析构

那么这里展示我写的析构函数:

class string
{
public:
~string()
{
delete[]_str;
_str = nullptr;
_size = _capacity = 0;
}
private:
char* _str;
size_t _size;
size_t _capacity;
const static size_t npos = -1;//可以先忽略
};

3:std::basic_string::operator=运算符=
官方给出了三个重载

第一个就是将string类型赋值给string类型

第二个是将字符串赋值给string类型

第三个是单个字符赋值给string类型

需要注意的是自己实现的时候要进行深拷贝,而不是浅拷贝

string& operator= (const string& str)
{
if (this != &str)
{
char* tmp= new char[str._capacity + 1];
strcpy(tmp, str._str);
delete[] _str;
_str = tmp;
_size = str._size;
_capacity = str._capacity;
}
}

也可以借助swap函数进行优化:

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

Iterators:
1:begin
iterator begin();
const_iterator begin() const;
官方解释就是Returns an iterator pointing to the first character of the string.

也就是返回一个指向第一个字符的string迭代器

反之对应的就是end,最后一个

2:end
iterator end();
const_iterator end() const;
需要注意的是返回的是最后一个元素的下一个,不是最后一个,

就比如说如果string里面存的是 abcdef 那么end返回的是指向f下一个位置的迭代器。

begin与end都说完了,那么结合两者进行实现迭代器遍历:

include

include

using namespace std;

int main()
{
string t("abcdef");
string::iterator it = t.begin();
while (it != t.end())
{
cout << *it << " ";
it++;
}
cout << endl;
return 0;
}

运行结果:
3:rbegin与rend
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
两个是对应的begin与end其中r为reverse逆置的意思

返回的都是字符串反向端的反向迭代器。

include

include

using namespace std;
int main()
{
string str("now step live...");
string::reverse_iterator it = str.rbegin();
while (it != str.rend())
{
cout << *it;
++it;
}
cout << endl;
return 0;
}

4: cbegin与cend返回到begin或end
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
分别是Return const_iterator to begin 回到const_iterator开始

Return const_iterator to end 返回const_iterator到结束

5:同样有crbegin与crend返回到cbegin或cend
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
Capacity
1:size求string对象的大小
size_type size() const;
返回string的大小

这个还是很好理解的,直接展示代码的自己实现

    size_t size() const
    {
        return _size;
    } 

2:length求string对象的大小
这个函数跟size()其实没什么区别,而且用的很少,他出现的原因就是因为string是早期的c++产物,当时c++还不成熟,就造出了他,到后面也不能删除导致的。

3:max_size求string对象最大可以存贮多少字符
size_type max_size() const;
这个就是返回string中size最大是多大

4:resize 修改string的size大小
void resize (size_type n);
void resize (size_type n, charT c);
这个函数就是修改size的值,意在修改string的大小

在函数也对应了两种特殊情况;第1种便是n的值比原来的size大,还有1种是比原来的小;

那么我们看看原档对于此的解决

那么展示代码的实现:

    void resize(size_t n, char ch = '\0') 
    {
        if (n > _size)
        {

            reserve(n);//修改capacity大小为n后面回介绍

            for (size_t i = _size; i < n; i++)
            {
                _str[i] = ch;
            }
            _str[n] = '\0';
            _size = n;
        }
        else 
        {
            _str[n] = '\0';
            _size = n;
        }
    }

5:capacity求string对象的容器大小
size_type capacity() const;
该函数与size差不多,但这个还是是返回capacity的大小

   size_type capacity() const;
    {
        return _capacity;
    } 

6:reserve调整string对象的capacity大小
void reserve (size_type n = 0);
该函数是在修改capacity的大小,但是它只能放大不可以缩小。主要是因为如果缩小的话,代价太过于大,而且会产生很多不必要的麻烦。所以该函数只支持放大容量不可以缩小。

代码实现也有很多小细节:主要是末尾的'\0';

    void reserve(size_t n = 0)
    {
        if (n > _capacity)
        {
            char* tmp = new char[n + 1];//第n+1个位置存的是'/0'
            strcpy(tmp, _str);
            delete[] _str;
            _str = tmp;
            _capacity = n;
        }
    }

7:clear清空string对象存储内容
void clear();
该函数也是人如其名,进行了清理clear,所以函数的实现还是比较好理解的。这里不再进行多说那么这些进行代码展示

    void clear()
    {
        _str[0] = '\0';
        _size = 0;
    }

8:empty检测string对象是否为空
bool empty() const;
Returns whether the basic_string is empty (i.e. whether its length is 0).

这句话的详细意思就是如果该对象为空就返回1(true)如果对象不为空就返回零(false);

    bool empty() const
    {
        return _size == 0;
    }

9:shrink_to_fit调整capacity的啊小使其与size相等
void shrink_to_fit();
这个函数官方的介绍还有比较少的,但是实际上实现起来还是比较麻烦的。

它的作用主要是修改修改capacity大小,使其正好达到满的效果,也就是第capacity的位置就为第size的值。

其实该函数的实现不单单是调用了reserve

因为如果原本的capacity很大很大,但是我们又删了很多,那么这时候在shrink_to_fit,就会很浪费空间,原码是这样实现的,会先拷贝,后修改,不是单单的reserve

最后展示一下官方举例

Element access: 元素访问
1: operator[](跟数组一样进行下标随机访问)
reference operator[] (size_type pos);
const_reference operator[] (size_type pos) const;
实现起来还是比较简单的这里就不在说了。

    char& operator[] (size_t pos)
    {
        assert(pos < _size);
        return _str[pos];
    }
    const char& operator[] (size_t pos) const
    {
        assert(pos < _size);
        return _str[pos];
    }

2:at(跟operator差不多)
reference at (size_type pos);
const_reference at (size_type pos) const;
at与operator[]效果完全差不多,但是有一点不同的是operator在出错时会掏出他的七匹狼给你直接报告,但是at出错时只是会警告,所以at使用的很少

3:back与front (返回string对象的尾或首字符)
charT& back();const charT& back() const;
charT& front();const charT& front() const;
返回第一个与最后一个

Modifiers: 修饰 符
1:operator+= (实现+=)
string (1)
basic_string& operator+= (const basic_string& str);
c-string (2)
basic_string& operator+= (const charT* s);
character (3)
basic_string& operator+= (charT c);
这个重载运算符那就不需要多的介绍了吧,我们已经很详细了,就是+=

string& operator+=(const char str)
{
append(str);
return
this;
}
string& operator+=(char ch)
{
push_back(ch);
return *this;
}

2:append (附加别的对象)
string (1)
basic_string& append (const basic_string& str);
substring (2)
basic_string& append (const basic_string& str, size_type subpos, size_type sublen);
c-string (3)
basic_string& append (const charT s);
buffer (4)
basic_string& append (const charT
s, size_type n);
fill (5)
basic_string& append (size_type n, charT c);
range (6)
template basic_string& append (InputIterator first, InputIterator last);
initializer list(7)
basic_string& append (initializer_list il);
可以看到C++祖师爷写了很多它的重载,也完美了应对了我们的所有要求。而且这还是C++11如果C++14的话那么就会更多.那么这里就介绍几个我们经常用到的。

函数的作用

向后添加想要对象,俗话说时延长

代码实现 :

string& append(size_t n, char c)
{
if (_size + n > _capacity)
{
reserve(_size + n);
}
size_t begin = _size;
_size += n;
for (size_t i = begin; i < _size; i++)
{
_str[i] = c;
}
return this;
}
void append(const char
str)
{
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(_size + len);
}
strcpy(_str + _size, str);
_size += len;
}
string& append(const string& str)
{
append(str._str);
return *this;
}

3:push_back与pop_back (后添加与后删)
void push_back (charT c);
void pop_back();
向后添加,与后删,这个就没有好多说的。

4:assign (将string对象的元素全部转换到别的对象内)
string (1)
basic_string& assign (const basic_string& str);
substring (2)
basic_string& assign (const basic_string& str, size_type subpos, size_type sublen);
c-string (3)
basic_string& assign (const charT s);
buffer (4)
basic_string& assign (const charT
s, size_type n);
fill (5)
basic_string& assign (size_type n, charT c);
range (6)
template basic_string& assign (InputIterator first, InputIterator last);
initializer list(7)
basic_string& assign (initializer_list il);
move (8)
basic_string& assign (basic_string&& str) noexcept;
Assign content to string
将内容分配给字符串

include

include

using namespace std;
int main()
{
string str("now step live...");
string s;
s.assign(str);
auto it = s.begin();
while (it != s.end())
{
cout << *it;
++it;
}
cout << endl;
return 0;
}

5:insert (根据小标随机在其前面插入元素)
string (1)
basic_string& insert (size_type pos, const basic_string& str);
substring (2)
basic_string& insert (size_type pos, const basic_string& str, size_type subpos, size_type sublen);
c-string (3)
basic_string& insert (size_type pos, const charT s);
buffer (4)
basic_string& insert (size_type pos, const charT
s, size_type n);
fill (5)
basic_string& insert (size_type pos, size_type n, charT c); iterator insert (const_iterator p, size_type n, charT c);
single character (6)
iterator insert (const_iterator p, charT c);
range (7)
template iterator insert (iterator p, InputIterator first, InputIterator last);
initializer list (8)
basic_string& insert (const_iterator p, initializer_list il);
同样c++给了很多重载,insert就是在pos的前面插入

代码实现:

string& insert(size_t pos, char ch)
{
assert(pos < _size);
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : _capacity 2);
}
size_t end = _size + 1;
while (end > pos)
{
_str[end] = _str[end - 1];
--end;
}
_str[pos] = ch;
_size++;
return
this;
}
string& insert(size_t pos, const char str)
{
assert(pos < _size);
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(_size + len);
}
size_t end1 = _size + 1;
size_t end2 = _size + len + 1;
while (end1 > pos)
{
_str[end2 - 1] = _str[end1 - 1];
end2--;
end1--;
}
_str[_size + len] = '\0';
strncpy(_str + pos, str, len);
_size+=len;
return
this;
}

6:erase (根据下标进行删除)
sequence (1)
basic_string& erase (size_type pos = 0, size_type len = npos);
character (2)
iterator erase (const_iterator p);
range (3)
iterator erase (const_iterator first, const_iterator last);
需要注意的是这里的len是删除的个数,而npos是-1;

返回值就是删除后指向的位置(为了使其迭代器不失效)

7:replace (根据下标随机替换n个对应的元素)
就是代替,这个用的不是很多,就不想insert与erase那样全部展示了,就举个简单的例子吧

include

include

using namespace std;
int main()
{
string str("now step live...");
string s1("pqpq2");
str.replace(2, 2, s1);//把str从第二个开始把两个字符,替换为s1,
auto it = str.begin();
while (it != str.end())
{
cout << *it;
++it;
}
cout << endl;
return 0;
}

通常可以与find一同使用,统一替换某个特殊字符转化为想要的结果。

8:c_str (将string转化为char*来打印)
获取 C 字符串等效值

通常可以应用输出流

简单的来说就是将string转化为char*来打印

int main()
{
string b("abcd");
cout << b.c_str();
return 0;
}

代码实现

    const char* c_str() const
    {
        return _str;
    }

9:copy (复制拷贝)
这个就是复制拷贝,很好理解

同样第一个参数就是要拷贝的对象,第二个是要拷贝的个数,第三个参数就是被拷贝的对象第一个拷贝的位置。

举例:
10:find (查找特殊的元素)
string (1)
size_type find (const basic_string& str, size_type pos = 0) const noexcept;
c-string (2)
size_type find (const charT s, size_type pos = 0) const;
buffer (3)
size_type find (const charT
s, size_type pos, size_type n) const;
character (4)
size_type find (charT c, size_type pos = 0) const noexcept;

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

include

include

using namespace std;
void test()
{
string s3("https://legacy.cplusplus.com/reference/string/string/rfind/");
// 协议
// 域名
// 资源名

string sub1, sub2, sub3;
size_t i1 = s3.find(':');
if (i1 != -1)
    sub1 = s3.substr(0, i1);//可以理解为赋值从第0到第i1个
else
    cout << "没有找到i1" << endl;

size_t i2 = s3.find('/', i1 + 3);
if (i2 != -1)
    sub2 = s3.substr(i1 + 3, i2 - (i1 + 3));
else
    cout << "没有找到i2" << endl;

sub3 = s3.substr(i2 + 1);

cout << sub1 << endl;
cout << sub2 << endl;
cout << sub3 << endl;

}
int main()
{
test();
return 0;
}

11:substr (按string对象的指定部分生成子string对象)
asic_string substr (size_type pos = 0, size_type len = npos) const;
该函数就是生成其子字符串

代码实现 :

    string substr(size_t pos, size_t len = npos)
    {
        string s;
        size_t end = pos + len;
        if (len == npos || pos + len >= _size) // 有多少取多少
        {
            len = _size - pos;
            end = _size;
        }
        s.reserve(len);
        for (size_t i = pos; i < end; i++)
        {
            s += _str[i];
        }
        return s;
    }

那么到这里这篇文章就结束了,本篇文章不是详细介绍,而是帮助回忆!!!
看到这了就给自己点个赞把

目录
相关文章
|
5月前
|
存储 安全 C语言
C++ String揭秘:写高效代码的关键
在C++编程中,字符串操作是不可避免的一部分。从简单的字符串拼接到复杂的文本处理,C++的string类为开发者提供了一种更高效、灵活且安全的方式来管理和操作字符串。本文将从基础操作入手,逐步揭开C++ string类的奥秘,帮助你深入理解其内部机制,并学会如何在实际开发中充分发挥其性能和优势。
|
5月前
|
C++
模拟实现c++中的string
模拟实现c++中的string
|
8月前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
356 5
|
8月前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
239 2
|
9月前
|
C++ 容器
|
9月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
75 1
|
9月前
|
安全 C语言 C++
【C++篇】探寻C++ STL之美:从string类的基础到高级操作的全面解析
【C++篇】探寻C++ STL之美:从string类的基础到高级操作的全面解析
113 4
|
9月前
|
C++ 容器
|
9月前
|
C++ 容器
【C++】—— string模拟实现(一)
【C++】—— string模拟实现
|
9月前
|
存储 C++ 容器