自学内容网 自学内容网

C++ -string -常见用法1

博客主页:【夜泉_ly
本文专栏:【C++
欢迎点赞👍收藏⭐关注❤️

在这里插入图片描述

💡前言

在这篇文章中,我将简单探讨 C++string 的基本用法。写这篇文章的主要目的是帮助我巩固所学的知识,同时也便于未来的复习和参考。

如果你想大致的了解string的基本用法,也可以留下来看看。

对于那些希望深入学习更多细节的读者,可以去看看这个网站:cplusplus.com,以获取更全面的参考资料。

1.构造函数

1.1函数原型

在 C++98 中,string 类提供了七种构造函数,具体的函数原型如下:

string();
string (const string& str);
string (const string& str, size_t pos, size_t len = npos);
string (const char* s);
string (const char* s, size_t n);
string (size_t n, char c);
template <class InputIterator> string  (InputIterator first, InputIterator last);

注:
函数原型中的缺省参数npos是一个为静态成员变量,类型为size_t,值为-1(整型的最大值),通常用于表示无效位置。

1.2用法速览

在众多构造函数中,以下四个是最常用的:

string s1; // 创建一个空的 string 对象
string s2("Hello World"); // 用 C 字符串初始化 string 对象
string s3(6, '6'); // 用 6 个字符 '6' 填充 string 对象
string s4(s2); // 使用 s2 拷贝构造一个新的 string 对象

此外,还有一些不太常用的构造函数:

string s5(s2, 6, 5); // 从 s2 的第 7 个字符(下标为6)开始,拷贝 5 个字符
string s6("Hello World", 5); // 用"Hello World"的前 5 个字符初始化 string 对象

至于其他构造方式,我暂时还不熟悉。

1.3详解

() -重点⭐

string s1;

调用的是默认构造函数,创造出一个空的string类对象,其字符串为空,即""
VS上的调试图:

在调试中可以看到,空的string类对象具有以下特征:

  • 初始字符串长度size0
  • 初始容量capacity15(实际为16,但最后一个用来放\0

尽管空的 string 类对象可以被打印出来,但不会显示任何内容:

cout << "s1:" << s1 << endl;
cout << "s1:" << s1 << 'a' << endl;

在这里插入图片描述

( s) -重点⭐

string s2("Hello World");

以C类型的字符串构造string类对象。

C类型的字符串就是以\0为结束标志的字符串。

VS上的调试图:
在这里插入图片描述
显然,这种构造方式有一个限制,即它无法将'\0'填入string类对象,例如:

string s2("Hello \0World"); // 此时 '\0' 之后的字符不会被存储

在这里插入图片描述

( n, c) -重点⭐

string s3(6, '6'); 

nc字符填充string类对象。
在这里插入图片描述
与用C类型的字符串构造不同,这种构造方式可以将'\0'填入string类对象:

string s3(10,'\0'); // 创建一个长度为 10 的字符串,全部填充 '\0'

在这里插入图片描述

( str) -重点⭐

string s2("Hello World");
string s4(s2);

调用的是拷贝构造函数。
在这里插入图片描述
会拷贝原string类对象的所有内容,而不是简单地拷贝 C 类型的字符串:

string s3(10,'\0'); // 创建一个长度为 10 的字符串,全部填充 '\0'
string s4(s3); // 拷贝构造,复制 s3 的内容

在这里插入图片描述

( str, pos, len)

string s2("Hello World");
string s5(s2, 6, 5);

strpos位置(指下标)开始,拷贝len个字符。
在这里插入图片描述

string (const string& str, size_t pos, size_t len = npos);

在其函数原型中,len给了一个缺省参数npos

static const size_t npos = -1;

可以看见,npos为一个静态常变量,值为-1,又因为其类型为size_t,因此,npos实际值为整型的最大值。
当传参时,不传len或传的len过大,会默认从strpos位置拷贝至结尾。

string s2("Hello World");
string s5_1(s2, 6); // 默认拷贝至字符串结束
string s5_2(s2, 6, 100); // 尝试拷贝超过实际长度,将从第 6 个字符拷贝至结束

在这里插入图片描述

( s, n)

拷贝字符串s的前n个字符。感觉比较废。

2.容量函数

2.1函数原型

size: 返回当前字符串的长度

size_t size() const;

length: 返回当前字符串的长度(与 size() 等效)

size_t length() const;

max_size: 返回字符串可以容纳的最大字符数

size_t max_size() const;

resize: 改变字符串的长度

void resize (size_t n);
void resize (size_t n, char c);

capacity: 返回当前字符串的容量

size_t capacity() const;

reserve: 预留空间

void reserve (size_t n = 0);

clear: 清空字符串

void clear();

empty: 判断字符串是否为空

bool empty() const;

shrink_to_fit: 收缩容量

void shrink_to_fit();

2.2用法速览

常用的:

string s; // 创建一个空字符串
//size:
cout << s.size() << endl; // 输出字符串的长度

//reserve:
s.reserve(100); // 预留 100 个字符的空间
cout << s.capacity() << endl; // 输出当前字符串的容量

//resize:
//1:
s.resize(5); // 调整字符串的长度为 5
cout << s.size() << endl; // 输出调整后的长度
//2:
s.resize(10,'6'); // 调整字符串的长度为 10,填充字符 '6'
cout << s << endl; // 输出字符串内容

//clear:
s.clear(); // 清空字符串内容
cout << s << endl; // 输出空字符串

不常用的:

//length:
cout << s.length() << endl; // 输出字符串的长度(与 size() 等效)

//max_size:
cout << s.max_size() << endl; // 输出字符串可以容纳的最大字符数

//capacity:
cout << s.capacity() << endl; // 输出当前字符串的容量

//empty:
cout << (s.empty() ? "String is empty" : "String is not empty") << endl; // 判断字符串是否为空

//shrink_to_fit:
s.shrink_to_fit(); // 收缩字符串的容量,释放多余的内存
cout << s.capacity() << endl; // 输出收缩后的字符串容量

2.3详解

size() -重点⭐

重点,但用法很简单。
可以返回字符串的有效字符长度。
注,并非C语言类型的字符串的长度:

string s(10,'0'); // 创建一个包含 10 个 '0' 的字符串
cout << s.size() << endl; // 输出结果将是 10

Output:

10

注意事项:

  • string类对象的size并不一定等于其容量capacity
  • 由于不知道编码方式,返回值可能不等于实际编码后的字符数量。

std::sizestd::length的用法完全一致(一般用size),文档中将它们称作同义词synonym

reserve() -重点⭐

注意区分reserve和reverse!!!

可以改变string类对象的容量capacity不会改变有效数据个数size!!!

扩容与缩容:

可简单测试一下:

string s;
size_t cap = s.capacity();
cout << "Init:" << cap << endl;
for (int i = 0; i < 200; i++)
{
s += ' ';
if(cap != s.capacity())
{
cap = s.capacity();
cout << "capacity change : " << cap << endl;
}
}

在这里插入图片描述

不同环境的自动扩容机制不同,VS大概是1.5倍,linux大概是2倍。

reserve手动扩容,如果提前知道要多少空间,这样做可减少自动扩容带来的消耗:

string s;
s.reserve(100);

在这里插入图片描述
VS上,一般会稍微大于你给的值,因为它有一套自己的对齐规则。
这样的实现并没有问题:

在这里插入图片描述


如果字符串有内容,一般不会缩容:

string s("1");
s.reserve(100);
s.reserve(0);
cout << s.capacity() << endl;

在这里插入图片描述
如果为空字符串(初始为空/被clear清空),可能会缩容:

string s;
s.reserve(100);
s.reserve(0);
cout << s.capacity() << endl;

string s2("Hello World!!!!!!!!!!!!!!!!");
s2.clear();
s2.reserve(0);
cout << s2.capacity() << endl;

在这里插入图片描述
reserve也有缺省参数:

void reserve (size_t n = 0);

因此: s . r e s e r v e ( ) ; s.reserve(); s.reserve(); 等价于 s . r e s e r v e ( 0 ) ; s.reserve(0); s.reserve(0);

如果有编译器,任何情况它都不缩/缩,这种实现也是对的,因为这是一个不具有约束力的请求:

在这里插入图片描述

resize() -重点⭐

可以改变string类对象的有效数据个数size,增容时可能改变容量capacity大小。
该函数提供了两个重载版本:

void resize (size_t n);
void resize (size_t n, char c);

用法:

  1. string s;
    s.resize(3,'6'); // 将字符串大小调整为 3,并用字符 '6' 填充
    

    在这里插入图片描述

    当使用void resize (size_t n, char c);增加size时,多余的部分用字符c填充。

  2. s.resize(6); // 调整大小为 6,多余部分将用 '\0' 填充
    

    在这里插入图片描述
    当使用void resize (size_t n);增加size时,多余部分默认用'\0'填充:
    在这里插入图片描述
    所以std::resize的两个重载函数应该可以合成为一个:void resize (size_t n, char c = '\0');,没这样做的原因好像是函数重载比缺省参数早出现。

  3. s.resize(0);
    

    直接变成空串,但不改变capacity
    这点感觉和std::clear完全相似。

在这里插入图片描述


希望本篇文章对你有所帮助!并激发你进一步探索编程的兴趣!
本人仅是个C语言初学者,如果你有任何疑问或建议,欢迎随时留言讨论!让我们一起学习,共同进步!


原文地址:https://blog.csdn.net/2401_86587256/article/details/142896377

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!