当前位置: 首页 > news >正文

C++ —— STL容器——string类

1. 前言

本篇博客将会介绍 string 中的一些常用的函数,在使用 string 中的函数时,需要加上头文件 string

2. string 中的常见成员函数

2.1 初始化函数

string 类中的常用的初始化函数有以下几种:

1. string()                             作用:用空字符串初始化string类对象

2. string(const char* s)        作用:以s为指向的以空结尾的字符串初始化string类对象

3. string(size_t n, char c)     作用:用n个字符c初始化string类对象

4. string(const string&s)       作用:拷贝构造函数,用一个string类对象去初始化另一个新传建的对象

下面就来使用这些函数:

string str1;                  // 对应函数1
string str2("hello world");   // 对应函数2
string str3(10, '$');         // 对应函数3
string str4(str3);            // 对应函数4cout << "str1 = " << str1 << endl;
cout << "str2 = " << str2 << endl;
cout << "str3 = " << str3 << endl;
cout << "str4 = " << str4 << endl;

运行结果:



接下来介绍 string 类中一个十分重要的成员变量 —— npos,npos 是 string 类中的一个静态成员变量 —— static const size_t npos = -1。它表示的是整型的最大值,因为它是 size_t 类型的。

2.2 operator = 函数

operator = 函数的原型为:

string& operator= (const string& str) —— 作用用对象 str 中的数据替换调用该函数的对象中的数据

string& operator= (const char* s) —— 作用:用字符串 s 替换掉调用该函数的对象中的数据

下面就来使用这两个函数:

string str1("hello cplusplus");
string str2 = str1;
string str3 = "hello world";cout << "str2 = " << str2 << endl;
cout << "str3 = " << str3 << endl;

运行结果:



2.3 size 和 length 函数

既然是字符串,就免不了要求字符串的长度,那么在 string 中是否存在着能求取字符串长度的函数呢?当然有,而且还有两个。

size 函数和 length 函数的函数原型分别为:

size_t size() const;  作用:返回字符串有效字符长度

size_t length() const;  作用:返回字符串有效字符长度

这两个函数的计算结果均不包括字符 '\0' ,下面就来使用这两个函数:

string str1("hello world");
cout << "size = " << str1.size() << endl;
cout << "length = " << str1.length() << endl;

运行结果:



既然这两个函数都可以求取字符串的长度大小,那么在实际的使用过程中使用哪个函数呢?其实都可以,根据容器的不同去使用更好的,当然也可以直接使用通用的 —— size 函数。在后续的其它STL容器的学习中,求容器的数据个数一般使用 size 函数

2.4 operator[ ] 函数

在 string 类用多种可以访问对象中的数据的方法,其中一种就是通过重载下标引用操作符(即 [ ] )来访问,不仅可以访问数据,还可以修改数据。该函数的函数原型为:

char& operator[ ] (size_t pos)

const char& operator[ ] (size_t pos) const

一个普通函数,一个是 const 函数,普通对象调用普通的重载函数,const修饰对象调用const的重载函数。

下面就来使用这个函数:

string str("hello world");
// 访问
for (size_t i = 0; i < str.size(); i++)
{cout << str[i] << " ";
}
cout << endl;
// 修改
for (size_t i = 0; i < str.size(); i++)
{str[i] += 1;cout << str[i] << " ";
}
cout << endl;

运行结果:



在数组中若越界访问了,编译器可能会报错也可能不会报错;但是在sting类中的[ ],若访问字符串数组时,下标越界了,则会报错。这是因为在 string 类中下标引用操作符被重载了,重载的函数中加上了关于下标大小的断言操作。下面以具体的例子来理解这二者的区别:



2.5 迭代器相关的函数

除了上述的方法可以访问和修改容器中的数据之外,还有一种方法就是使用迭代器。迭代器是什么?迭代器的名字是:iterator,它是容器中的一个类型,在使用它的时候要指明容器类域;也可以将它想象成像指针一样的类型对象。使用迭代器时,需要获取区间范围,这种区间都是左闭右开(右区间 - 左区间 就是当前字符串的长度)的,以便知道迭代器从哪里开始迭代,从哪里结束迭代。这就需要用到迭代器相关函数了。此外迭代器可以分成很多种类,不同种类的迭代器的获取迭代区间的函数有所不同。迭代器可以分为正向迭代器和反向迭代器,而这两种迭代器又可以分为普通迭代器和 const 迭代器。

接下来就来一一介绍和使用这几种迭代器:

1. 正向迭代器 —— 普通迭代器

获取迭代区间的函数:begin 函数和 end 函数,这两个函数的原型分别为:

begin —— iterator begin()   const_iterator begin() const

end —— iterator end()   const_iterator end() const

普通迭代器使用的都是未被 const 修饰的函数,那么这两个函数的作用分别是什么呢?

begin —— 作用:返回指向字符串的第一个字符迭代器

end —— 作用:返回指向容器末尾(最后一个元素之后,即‘\0')的迭代器

普通的迭代器不仅可以访问容器中的数据,还可以修改容器中的数据。下面就来使用该迭代器:

string str("hello cplusplus");
string::iterator it1 = str.begin(); 	//指明类域
// 访问
while (it1 != str.end())
{cout << *it1 << " ";// 向后迭代it1++;
}
cout << endl;
// 修改
it1 = str.begin();
while (it1 != str.end())
{// 修改 —— 让每个字符都加1(*it1)++;cout << *it1 << " ";// 向后迭代it1++;
}
cout << endl;

运行结果:



2. 正向迭代器 —— const 迭代器

由于 begin 函数和 end 函数均有 const 修饰的函数的原型,所以在获取迭代器的区间范围时,也可以使用 begin 和 end 函数。但是在 C++11 中,为了区分这是在使用 const 迭代器,引入两个新的函数 cbegin 和 cend 函数,它们两个函数的原型分别为:

cbegin —— const_iterator cbegin()   const noexcept

cend —— const_iterator cend()   const noexcept

不必考虑这里的 nonexcept 是什么意思,有什么作用。cbegin 和 cend 函数的作用与 begin 和 end 函数的作用一致。需要注意的是 const 迭代器并不是直接在 iterator 的 前面加上 const ,如:const iterator ,而是 const_iteratorconst iterator 中 const 修饰的是迭代器本身,表示迭代器本身不能修改,也就说明迭代器不能迭代,这在实践中根本没法使用;const_iterator 表示迭代器指向的数据的内容不能被修改,可以做到迭代的功能。const 迭代器只能访问容器中的数据,不可以修改容器中的数据。下面就来使用该迭代器:

// 使用 begin 和 end 函数
string str1("hello cplusplus");
string::const_iterator it1 = str1.begin();
while (it1 != str1.end())
{cout << *it1 << " ";it1++;
}
cout << endl;// 使用 rbegin 和 rend 函数
string str2("hello cplusplus");
string::const_iterator it2 = str2.cbegin();
while (it2 != str2.cend())
{cout << *it2 << " ";it2++;
}
cout << endl;

3. 反向迭代器 —— 普通迭代器

反向迭代器顾名思义就是反着遍历字符串,获取迭代器区间的函数为 rbegin 和 rend ,这里与 begin 和 end 函数名的前面多了一个 r ,这个 r 表示的反向 reverse 的首字母,且反向迭代器的名字就是 reverse_iterator 。rbegin 和 rend 函数原型分别为:

rbegin —— reverse_iterator rbegin()   const_reverse_iterator rbegin() const

rend —— reverse_iterator rend()      const_reverse_iterator rend() const 

这两个函数的作用分别是:

rbegin —— 作用:返回指向字符串最后一个字符的迭代器

rend ——  作用:返回指向字符串的首字符的前一个字符的迭代器

并且迭代时的++,是从 rbegin 开始,从后往前++,直到等于 rend ,这也是为什么该迭代器被称为反向迭代器。下面就来使用该迭代器:

string str("24680");
string::reverse_iterator it1 = str.rbegin();
while (it1 != str.rend())
{cout << *it1 << " ";it1++;
}
cout << endl;string::reverse_iterator it2 = str.rbegin();
while (it2 != str.rend())
{(*it2)++;cout << *it2 << " ";it2++;
}

运行结果:



4. 反向迭代器 —— const 迭代器

与正向迭代器中的 const 迭代器一致,反向迭代器中的 const 迭代器并不是简单的在reverse_iterator 前面加上 const ,而是 const_reverse_iterator。基于 rbegin 和 rend 函数都有 const 修饰的函数原型,所以在获取迭代器的迭代区间的时候可以使用这两个函数。但是在 C++11 中,为了区分这是在使用 const 迭代器,引入两个新的函数 crbegin 和 crend 函数,它们两个函数的原型分别为:

crbegin —— const_reverse_iterator crbegin() const noexcept

cend —— const_reverse_iterator crend() const noexcept

crbegin 和 crend 函数的作用与 rbegin 和 rend 函数的作用一致。下面就来使用该迭代器:

string str("13579");
// 使用 rbegin 和 rend
string::const_reverse_iterator it1 = str.rbegin();
while (it1 != str.rend())
{cout << *it1 << " ";it1++;
}
cout << endl;// 使用 rbegin 和 rend
string::const_reverse_iterator it2 = str.crbegin();
while (it2 != str.crend())
{cout << *it2 << " ";it2++;
}
cout << endl;

运行结果:



5. 总结:

了解了迭代器之后,我们就可以直到另外一种可以访问和修改对象中的数据的方法。在实际的使用过程中,正向迭代器使用的更多。若想要逆置字符串中的数据,可以使用算法库(algorithm)中的 reverse 函数。

2.6 push_back 函数和 pop_back 函数

push_back 和 pop_back 的函数原型分别为:

push_back —— void push_back(char c)

pop_back —— void pop_back()

基于前面的数据结构的学习可以知道,这两个函数的作用分别为尾插字符和尾删字符。下面就来使用这两个函数:

string str1("hello world");
cout << "插入前: ";
for (size_t i = 0; i < str1.size(); i++)
{cout << str1[i] << " ";
}
cout << endl;str1.push_back('$');
cout << "插入后: ";
for (size_t i = 0; i < str1.size(); i++)
{cout << str1[i] << " ";
}
cout << endl;string str2("hello cplusplus");
cout << "删除前: ";
for (size_t i = 0; i < str2.size(); i++)
{cout << str2[i] << " ";
}
cout << endl;str2.pop_back();
cout << "删除后: ";
for (size_t i = 0; i < str2.size(); i++)
{cout << str2[i] << " ";
}
cout << endl;

运行结果:



 

2.7 capacity 函数

前面有提到 string 类的底层实际上是一个存储字符类型的顺序表,由此也可以知道它的结构是:指向数组的指针,存储当前有效数据个数,当前数组的内存空间的大小。在前面介绍了 size 函数可以获取当前字符串的长度,那么 string 类中有没有函数可以获取当前字符串的容量大小呢?当然存在,那就是接下来要介绍的 capacity 函数。该函数的原型和作用分别为:

capacity —— size_t capacity() const —— 作用:返回当前字符串的空间大小,单位是字节

这里求得的结果并不包含 '\0' ,与 size 函数一致。需要注意的是内存的大小不一定与当前字符串的长度相等,可能相等,可能较大。当相等的时候,就会扩容,但是具体的扩容机制 C++ 标准并没有规定,根据编译器的不同而不同,根据操作系统的不同而不同。下面就来看看在 Vs 编译器下的扩容机制:

string str("gon");
cout << "old caapcity: " << str.capacity() << endl;
size_t old = str.capacity();// 不断的往 str 中插入100个数据
for (size_t i = 0; i < 100; i++)
{str.push_back('*');// 判断是否需要扩容// 当 old 的大小与当前字符串的capacity的大小不等时// 就会触发扩容机制if (str.capacity() != old){cout << "new capacity: " << str.capacity() << endl;}old = str.capacity();
}

运行结果:



有运行结果可以知道,除了第一次的扩容不是1.5倍扩容之外,后续的扩容都是1.5倍扩容。另外可以知道,在 Linux 中,后续的扩容是2倍扩容

2.8 empty 函数和 clear 函数

这两个函数就较为简单了,这两个函数的函数原型分别是:

empty —— bool empty() const

clear —— void clear()

empty 和 clear 函数的作用分别为:

empty —— 检查当前的字符串是否是空串,若是则返回 true ,若不是则返回 false

clear —— 清楚当前字符串中的所有字符,即将 size 变为 0 ,但是不改变 capacity 的大小

下面就来使用这两个函数:

empty 函数:

string str1;
string str2("");
string str3(" ");
string str4("hello");cout << str1.empty() << endl;
cout << str2.empty() << endl;
cout << str3.empty() << endl;
cout << str4.empty() << endl;

运行结果:



clear 函数:

string str("hello world");
cout << "size: " << str.size() << endl;
cout << "capacity: " << str.capacity() << endl;
cout << endl;// 调用 clear 函数
str.clear();
cout << "size: " << str.size() << endl;
cout << "capacity: " << str.capacity() << endl;

运行结果:



2.9 shrink_to_fit 函数

shrink_to_fit 函数是 C++11 出现的,该函数的作用是缩容不改变 size改变capacity的大小,将capacity的大小减少到合适的大小,但是该过程的结果是不确定的,根据平台的不同而不同,可能缩容成功,也可能缩容失败,即便缩容成功了,其结果 capacity 仍然大于 size。该函数的函数原型为:

shrink_to_fit —— void shrink_to_fit()

下面来使用该函数:

// 缩容失败
string str;
size_t old = str.capacity();
cout << "******缩容失败******" << endl;
// 不断的往 str 中插入100个数据
for (size_t i = 0; i < 100; i++)
{str.push_back('*');
}
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;
cout << endl;str.shrink_to_fit();
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;
cout << endl;// 缩容成功
cout << "******缩容成功******" << endl;
//尾删 50 个字符
for (size_t i = 0; i < 50; i++)
{str.pop_back();
}
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;
cout << endl;str.shrink_to_fit();
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;

运行结果:



shrink_to_fit 函数的底层缩容原理是异地缩容,先开一块新的较小的内存空间,将原空间的数据拷贝到新的空间,然后释放旧空间。在实际的编程中很少执行缩容操作,因为缩容的代价是很大的,需要重新开辟空间,是以时间换空间的做法。

2.10 reserve 函数 和 resize 函数

reserve 函数的函数原型为:

reverse —— void reserve(size_t n = 0)

该函数的作用是扩容,为字符串预留空间,将字符串的 capacity 的大小改变到 n 但是根据 n 的大小的不同会产生不同的结果

当 size < n < capacity 时,那么 reserve 可能会让当前容器的 capacity 缩小至 n 或 更大 亦或者是不变。下面来使用该函数

string str("hello world");
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;
cout << endl;
str.reserve(13);
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;

运行结果:



当 size > capacity 时,那么 reserve 就会让当前容器的capacity 增长至 n 或者更大。下面来使用该函数:

string str("hello world");
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;
cout << endl;
str.reserve(20);
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;

运行结果:



在之前了解 capacity 函数时,有频繁的扩容,但是使用 reserve 函数,先确定需要开多大的内存空间,提前开辟好,这样可以避免扩容,提高效率。如下代码所示:

string str("hello world");
cout << "old caapcity: " << str.capacity() << endl;
size_t old = str.capacity();
str.reserve(100);for (size_t i = 0; i < 100; i++)
{str.push_back('*');if (str.capacity() != old){cout << "new capacity: " << str.capacity() << endl;}old = str.capacity();
}

运行结果:



resize 函数的函数原型为:

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

该函数的作用是将字符串的长度 size 改变至 n有时也会改变 capacity 的大小。与 reserve 函数一致,改变的结果与 n 的大小有关。

当 n < size 的大小时,那么 resize 会保留前 n 个字符,删除 n 之后的字符,但是不影响 capacity 的大小。下面开始使用该函数:

string str("hello world");
cout << str << endl;
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;
cout << endl;
// n < size
str.resize(7);
cout << str << endl;
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;

运行结果:



当 size < n < capacity 时那么当前字符串的长度会增长至 n 。若没有明确传参,则多出来的长度用 '\0' 来填充。下面开始使用该函数:

string str("hello world");
cout << str << endl;
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;
cout << endl;
str.resize(14);
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;

运行结果:



调用 resize 后,字符串 str 为:



由编译的结果可以看出多出来的长度全由' \0' 填充。

当 size < n < capacity 时,且明确传参字符 c ,则多出来的长度全由字符 c 来填充。下面开始使用该函数:

string str("hello world");
cout << str << endl;
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;
cout << endl;
str.resize(14, '@');
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;
cout << str << endl;

运行结果:



当 n > capacity 的大小时,那么当前字符串的长度会增加至 n,capacity 的大小也会增加若没有明确传参,则多出来的长度用 '\0' 来填充。下面开始使用该函数:

string str("hello world");
cout << str << endl;
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;
cout << endl;
str.resize(20);
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;
cout << str << endl;

运行结果:



调用 resize 后,字符串 str 为:



当 n > capacity 时,且明确传参字符 c ,则多出来的长度全由字符 c 来填充。下面开始使用该函数:

string str("hello world");
cout << str << endl;
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;
cout << endl;
str.resize(20, '@');
cout << "size = " << str.size() << endl;
cout << "capacity = " << str.capacity() << endl;
cout << str << endl;

运行结果:



2.11 append 函数和 operator += 函数

append 函数的函数原型和作用分别为:

string& append (const string& str) —— 作用:在字符串的尾部追加 str

string& append (const char* s) —— 作用:在字符串的尾部追加 s 

string& append (size_t n, char c) —— 作用:在字符串的尾部追加 n 个字符 c

下面就来使用这些函数:

string str("hello world ");
cout << str << endl;
str.append(str);          // 原型1
cout << str << endl;
str.append("and space");  // 原型2
cout << str << endl;    
str.append(10, '@');      // 原型3
cout << str << endl;

运行结果:



operator += 函数的函数原型和作用分别为:

string& operator+= (const string& str) —— 作用:在字符串的末尾加上 str

string& operator+= (const char* s) —— 作用:在字符串的末尾加上字符串 s

string& operator+= (char c) —— 作用:在字符串的末尾加上字符 c

下面就来使用这些函数:

string str("hello world ");
cout << str << endl;
str += str;            // 原型1
cout << str << endl;
str += " and space";   // 原型2
cout << str << endl;
str += '@';            // 原型3
cout << str << endl;

运行结果:



相较于append 函数,operator+= 函数使用的最多.

2.12 insert 函数,erase 函数和 replace 函数

在 string 类中并没有提供头插和头删以及其它除了尾插和尾删的插入操作,这是因为 string 类提供了一个更好的函数 —— insert 函数。insert 函数的函数原型和作用分别为:

string& insert (size_t pos, const char* s) —— 作用:在 pos 位置前插入字符串 s

string& insert (size_t pos, size_t n, char c) —— 作用:在 pos 位置前插入 n 个字符 c

下面开始使用这些函数:

string str("hello world");
cout << str << endl;
str.insert(6, "space and ");
cout << str << endl;
str.insert(6, 10, '*');
cout << str << endl;

运行结果:



insert函数要谨慎使用,因为insert的底层涉及数据的挪动,效率低下.

erase 函数的函数原型为:

erase —— string& erase (size_t pos = 0, size_t len = npos)

该函数的作用为:删除字符串中从字符位置pos开始len个字符的部分,若 len 的大小大于从 pos 位置开始到 '\0' 结束之后的字符串的长度,那么有多少删除多少。下面开始使用该函数:

string str1("hello world");
cout << "删除前: " << str1 << endl;
str1.erase();
cout << "删除后: " << str1 << endl;
cout << endl;string str2("cplusplus");
cout << "删除前: " << str2 << endl;
str2.erase(4);
cout << "删除后: " << str2 << endl;
cout << endl;string str3("watergraphiclaly");
cout << "删除前: " << str3 << endl;
str3.erase(4, 5);
cout << "删除后: " << str3 << endl;
cout << endl;

运行结果:



erase要谨慎使用,因为erase的底层涉及数据的挪动,效率低下

replace 函数的函数原型为:

replace —— string& replace (size_t pos,  size_t len,  const char* s)

该函数的作用为:从pos位置开始,将长度为len的字符串替换成字符串s。下面开始使用该函数:

string str1("hello world");
cout << str1 << endl;
str1.replace(6, 3, "$");
cout << str1 << endl;
cout << endl;string str2("hello world");
cout << str2 << endl;
str2.replace(6, 3, "abcdef");
cout << str2 << endl;

运行结果:



replace函数要谨慎使用,因为replace的底层涉及数据的挪动,效率低下

这以上三个函数都并不常用,也不好用。

2.13 c_str 函数和 substr 函数

c_str 函数的函数原型和作用为:

c_str —— const char* c_str() const —— 作用:返回string指向底层数组的指针

获取了 string 指向底层数组的指针后,可以通过该指针打印该指针指向的数组中的数据。下面开始使用该函数以及其运行结果:



substr 函数的函数原型和作用分别为:

string substr (size_t pos = 0, size_t len = npos) const —— 作用:在str中从pos位置开始,截取len个字符,然后将其返回

下面开始使用该函数:

// 获取空格之后部分的字符串
string str("hello world");
cout << str << endl;
cout << "size = " << str.size() << endl;
cout << endl;
string ret = str.substr(6, str.size() - 6);
cout << ret << endl;
cout << "size = " << ret.size() << endl;

运行结果:



当 len 不传参数时,默认 len 的大小为 npos

2.14 find 函数和 rfind 函数

find 函数的函数原型为:

find —— size_t find (char c, size_t pos = 0) const

该函数的作用为:从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置;如果没有找到字符串c,则函数返回string::npos。下面开始使用函数:

// 将字符串中的空格字符替换成"%%"
string str("water geographically @ g . mail");
cout << str << endl;
// 默认从下标为 0 的位置开始找
size_t pos = str.find(' ');
while (pos != string::npos)
{str.replace(pos, 1, "%%");// 继续往后找,不需要再从下标为 0 的位置开始找了// 从下标为 pos + 2 的位置开始找pos = str.find(' ', pos + 2);
}cout << str << endl;

运行结果:



rfind 函数的函数原型为:

rfind —— size_t rfind(char c, size_t pos = npos) const

该函数的作用为:从字符串 str 的 pos 位置开始,向后找字符 c ,如果没有找到字符 c,函数返回string::npos。该函数的使用与 find 一致,这里就不多赘述。

3. string 中的常见非成员函数

3.1 relational operators 函数

relational operators 函数是一系列的字符串比较函数,它们的作用均为字符串的比较。这些函数的函数原型为:

小于运算符 —— bool operator<(const string& str1, const string& str2)

小于等于运算符 —— bool operator<=(const string& str1, const string& str2)

大于运算符 —— bool operator>(const string& str1, const string& str2)

大于等于运算符 —— bool operator>=(const string& str1, const string& str2)

等于运算符 —— bool operator==(const string& str1, const string& str2)

不等于运算符 —— bool operator!=(const string& str1, const string& str2)

这些函数的比较方式与 strcmp 函数类似,比较的是 ascii 码,而不是长度若结果为真则返回大于0的数字,若结果为假,则返回小于 0 的数字

3.2 流提取运算符和流插入运算符

string 类并不是内置类型,而是自定义类型,那为什么仍然可以使用流插入运算符和流提取运算符呢?这是因为在 string 类中重载了这两个操作符。那么这两个重载函数的函数原型为:

流提取运算符 —— ostream& operator<< (ostream& os, const string& str)

流插入运算符 —— istream& operator>> (istream& is, string& str)

3.3 getline 函数

在 C++ 中,可以使用 cin 往 string 类对象中输入数据,但有些字符串当中是存在空格的,而当读取到空格字符时,cin 会停止读取。那若想要输入带空格的字符串,应该怎么办呢?唉!这就不都得不提 getline 函数了。该函数的原型为:

istream& getline(istream& is, string& str, char delim)

istream& getline(istream& is, string& str)

getline 函数的作用为:从is中提取字符并将其存储到str中,直到找到分隔字符delim在用户未自定义分隔字符delim时,默认分割字符为’\n’,若用户自定义分隔字符delim时,则分隔字符delim使用的就是用户自定义的;与cin不同的是,cin遇到’\0‘或’\n’时就停止读取,getline遇到分隔符delim才停止读取。下面就来使用该函数:

// 求一个字符长串中最后一个单词的长度
string str;
getline(cin, str);
size_t pos = str.rfind(' ');
if (pos != string::npos)
{cout << str.size() - pos - 1 << endl;
}
else
{cout << str.size() << endl;
}

运行结果:



4. 范围 for

除了以上提到的两种可以访问和修改对象中的数据的方法之外,还有一种方法是 —— 范围 for 。在了解范围 for 之前先来了解 auto 关键字。

4.1 auto 关键字

auto 可以自动推导数据的类型,如下图所示:



对于引用类型,若想要 auto 推导出的数据类型为引用类型,需要在 auto 的后面加上 &

对于指针,若想要 auto 推导出的数据类型为指针,可以在 auto 的后面加上解引用操作符( * ),也可以不加

4.2 范围 for

了解了 auto 关键字后,接下来介绍范围 for。范围 for 为:

for( : )
{}

for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,范围 for 的特点是:自动迭代,自动取数据,自动判断结束。下面就来使用范围 for :



但是上面的范围 for 只能访问容器中的数据,不能修改容器中的数据。若要想修改容器中的数据,可以使用引用,如下图所示:



这里的类型不一定要写成auto,也可以写成确定的类型。但是确定的类型应该与容器中的数据类型相等。范围for支持所有的容器,因为范围for的底层就是迭代器

5. 结言

以上介绍的函数中有些是十分重要的,如:一系列的初始化函数, size 函数, empty 函数, clear 函数, reserve 函数, resize 函数, operator[ ] 函数, c_str 函数, find 函数, 流插入和流提取函数, getline 函数, relational operators 函数。 

相关文章:

  • ps中通过拷贝的图层和通过剪切的图层
  • java多线程与JUC
  • ck-editor5的研究 (4):初步使用 CKEditor5 的插件功能
  • Cesium快速入门到精通系列教程三
  • 高速串行接口
  • Spring Boot 4.0实战:构建高并发电商系统
  • ArkTS基础
  • spining-lidar的电机和激光雷达体(lidar-imu)之间的标定
  • VMware-VMRC-12.0.1-18113358安装包下载安装与使用(附下载)
  • 数学分析——一致性(均匀性)和收敛
  • 高速串行通信解惑说明
  • ReLU的变体
  • 【项目记录】登录认证(下)
  • vscode 代理模式(agent mode),简单尝试一下。
  • Day42 Python打卡训练营
  • powershell7.5@.net环境@pwsh7.5在部分windows10系统下的运行问题
  • 机器人学基础——正运动学(理论推导及c++实现)
  • 智能指针unique
  • Launcher3体系化之路
  • day16 leetcode-hot100-30(链表9)
  • 南川网站建设/2023疫情最新情况
  • 手机网站制作免费/游戏推广员好做吗
  • 女人做绿叶网站相亲拉人/seo舆情优化
  • 地产网站建设方案/长春网站seo
  • 南阳做网站收费/百度一下你就知道了百度一下
  • 阿里云虚拟主机怎么建立网站/企业网络营销业务