9. string 类和标准模板库

目录

  • 9.1 string 类

    • 9.1.1 string 类的构造函数
    • 9.1.2 string 类输入
      • 9.1.2.1 string 类输入方法
      • 9.1.2.2 string 类输入详解
      • 9.1.2.3 使用 string 类
      • 9.1.2.4 string 类的其他功能
  • 9.2 智能指针模板类
    • 9.2.1 使用智能指针
  • 9.2 模板类 vector
    • 9.2.1 使用 vector 类
    • 9.2.2 可以对 vector 进行的其他操作

9.1 string 类

9.1.1 string 类的构造函数

构造函数 描述
string(const char* s) 将string对象初始化为S指向的NBTS(null-terminated-string)
string(size_type n, char c) 创建一个包含n个元素的string对象,其中每个元素都被初始化为字符c
string(const string & str) 将一个string对象初始化为string对象str (复制构造函数)
string( ) 创建一个默认的sting对象,长度为0 (默认构造函数)
string(const char *s, size_ type n) 将string对象初始化为s指向的NBTS的前n个字符,**即使超过了NBTS结尾 **
template\<class lter\><br>string(lter begin, Iter end) 将string对象初始化为区间[begin, end)内的字符,其中begin和end的行为就像指针,用于指定位置
string(const string & str, size_type pos = 0, size_type n = npos) 将一个sring对象初始化为对象str中从位置pos开始到结尾的字符,或从位置pos 开始的n个字符
string(string && str) noexcept 这是C++11新增的,它将一个 string对象初始化为string对象str,并可能修改str (移动构造函数)
string(initializer_list<char> il) 这是C++11新增的,它将一个string对象初始化为初始化列表il中的字符

9.1.2 string 类输入

9.1.2.1 string 类输入方法

对于 C-style 字符串,有三种输入方式:

char info[100];
cin >> info;               // 默认读取一个单词
cin.getline(info, 100);    // 默认读取一行,并用 \0 代替 \n
cin.get(info, 100)         // 读取一行,不过将 \n 留在

对于string对象,有两种输入方法:

string stuff;
cin >> string;          // 默认读取一个字符
getline(cin, stuff);    // 默认读取一行,但 \n 会被抛弃

两个版本的getline()都有一个可选参数,用来指定终止字符(默认为\n):

cin.getline(info, 100, ‘.‘);
getline(cin, stuff, ‘.‘);

两个版本的getline()有两个值得注意的区别

  • 在功能上,它们之间的主要区别在于,string版本的函数会自动调整对象大小,使之刚好能存储输入的字符串。
  • 在设计方面的一个区别是,读取C-style字符串的函数是istream类的成员方法,而string版本的是独立的函数。

    对于C-style字符串,**cin是调用对象;而对于string对象,cin是一个函数参数**。这一点对于operator>>同样适用。

9.1.2.2 string 类输入详解

string输入函数虽然可以自动调整string对象的大小,但也存在一些限制

  1. string对象存在最大允许长度,由string::npos指定,通常为最大的unsigned int值。
  2. 程序可以使用的内存量也是一个限制因素。

stringgetline()函数从输入中读取字符,并将储存到string对象中,直到发生以下三种情况之一:

  1. 到达文件尾(在命令行中,文件尾可以通过特殊的组合键,如Ctrl+c,实现),eofbit被设置,方法fail()eof()都将返回true
  2. 遇到终止字符,将会从输入流中删除终止字符,但不会存储它。
  3. 读取的字符数达到最大限制(string::npos和程序可以使用的内存量之中较小的一个),将设置输入流的failbit,方法fail()会返回true

stringoperator>>()函数的行为与此类似,只是第二种情况变为不断读取直到遇到空白字符并将其留在输入流(空格、换行符、制表符等使isspace()函数返回true的字符)。

9.1.2.3 使用 string 类

  1. 比较字符串:string类对6个逻辑字符串都进行了重载。在比较时,将ASCII码小的字符视为小的字符。
  2. 确定字符串的长度:size()length()都可以用来确定字符串中的字符数量。
  3. 搜索子字符(串):
方法原型 描述
size_type find(const basic_string &str, size_type pos = 0) const noexcept; 从字符串的pos位置开始,查找子字符串str。如果查到,返回子字符串首次时其首字符的索引;否则,返回string::npos
size_type find(const CharT *s, size_type pos = 0) const; 从字符串的pos位置开始,查找子字符串s(以\n为结尾)。如果查到,返回子字符串首次时其首字符的索引;否则,返回string::npos
size_type find(const CharT* s, size_type pos, size_type count) const; 从字符串的pos位置开始,查找子字符串s的前n个字符组成的子字符串。如果查到,返回子字符串首次时其首字符的索引;否则,返回string::npos
size_type find(CharT ch, size_type pos = 0 ) const noexcept; 从字符串的pos位置开始,查找子字符ch。如果查到,返回子字符首次时的索引;否则,返回string::npos

注意noexcept是在C++11之后才有的。

string库还提供了相关的方法,它们的重载方式与find()相同。

  1. refind()查找源字符串中目标字符串最后一次出现的位置。
  2. find_first_of()查找源字符串中目标字符串中任何一个字符首次出现的位置。
  3. find_last_of()查找源字符串中目标字符串中任何一个字符最后一次出现的位置。
  4. find_first_not_of()查找源字符串中首次出现不属于目标字符串的任意字符的位置。
  5. find_last_not_of()查找源字符串中最后一次出现不属于目标字符串的任意字符的位置。

另外,string对象还重载了operator=operator+operator+=等运算符。

9.1.2.4 string 类的其他功能

  • 删除一个字符串的部分或全部内容;
  • 将一个字符串的部分或全部内容替换为另一个字符串的部分或全部内容;
  • 将一个字符串的部分或全部内容插入到另一个字符串中;
  • 将一个字符串的部分或全部内容与另一个字符串的部分或全部内容进行比较;
  • 从一个字符串中提取子字符串;
  • 交换两个字符串的部分或全部内容。

自动调节大小的功能:

改变字符串内容一般都会涉及到字符串长度的改变,这时不能简单地将已有的字符串加大,因为旁边的内存可能已经被占用了。因此通常的做法是为string重新分配一块地址,并释放原来的地址。

如果一个string对象中储存的字符串的长度会频繁地变化,会造成很多不必要的开销。这时,可以用额外的内存占用来换取这些开销的减少——使用reserve()方法改变string类的大小(但是不能低于默认的最小大小,也不能低于size()length())。

string str1 = "aloha0123456789";    // 5个字符
string str2 = "aloha01234567890";   // 16个字符
string str3 = "Please remember, Still water runs deep, my brother.中文";    // “中文”被视为六个字符,其实只有53个
cout << "size(): capacity()\n";
cout << str1.size() << ": " << str1.capacity() << endl;
cout << str2.size() << ": " << str2.capacity() << endl;
cout << str3.size() << ": " << str3.capacity() << endl;
str2.reserve(10);
cout << "after reserve(10):\n";
cout << str2 << ": " << str2.capacity() << endl;
str2.reserve(15);
cout << "after reserve(15):\n";
cout << str2 << ": " << str2.capacity() << endl;
str2.reserve(70);
cout << "after reserve(70):\n";
cout << str2 << ": " << str2.capacity() << endl;
size(): capacity()
15: 15
16: 16
57: 57
after reserve(10):
aloha01234567890: 16
after reserve(15):
aloha01234567890: 16
after reserve(70):
aloha01234567890: 70

9.2 智能指针模板类

在异常处理中,可能还没释放动态分配的内存程序就抛出异常。这样会造成内存泄漏。

要解决这个问题,可以使用C++中的智能指针代替普通指针。与普通指针相比,智能指针是一个类,在栈解退过程中会自动调用其构造函数,并在构造函数中释放指针所指的内存。

C++中提供了三个智能指针模板:auto_ptrunique_ptrshared_ptrauto_ptr是C++98提供的解决方案,C++11中以将其摒弃(但是一般会向后兼容)。另外,还有一个特殊的智能指针weak_ptr,需要配合shared_ptr使用。

9.2.1 使用智能指针

要使用智能指针,必须要包含头文件memory。使用语法:

auto_ptr<Data_Type> ap(new Data_type);
unique_ptr<Data_Type> up(new Data_type);
shared_ptr<Data_Type> sp(new Data_type);
auto_ptr<string> ps1(new string("Still water runs deep."));
cout << *ps1 << endl;
auto_ptr<string> ps2 = ps1;
cout << *ps2 << endl;

为避免重复释放同一块内存,auto_ptr采用ownership的方法(可能定义了一个标志所有者的bool变量):当将一个auto_ptr的值传递(赋值运算符或复制构造函数)给另一个auto_ptr时,将转交所有权,前者将不再引用此对象。

这样虽然确实保证了对象所在内存不会被重复释放,但是可能会出于各种意外而使用原来的auto_ptr,这显然是一个风险。

使用shared_ptr可以避免这种风险。shared_ptr类中有一个counter,每次调用析构函数时将counter减 1 ,并确保只有当counter为 1(初始值)时,其析构函数才会释放内存。

如果使用unique_ptr,程序不会等到运行时才报错,在编译时编译器就会报错。这是因为unique_ptr禁止使用一个可能会长期存在的左值进行初始化。但是神奇的是,unique_ptr允许使用一个临时的右值进行初始化,并且能正确地运行(unique_ptr使用了移动构造函数和右值引用):

auto_ptr<string> ps1(new string("Still water runs deep."));
unique_ptr<string> ps2;
ps2 = ps1;                    // error
unique_ptr<string> ps3;
ps3 = unique_ptr<string>(new string("aloha!"));

另外,如果要使用new[],就一定要使用unique_ptr,因为只有uinque_ptr有使用new[]delete[]的版本。使用示例:

unique_ptr<string[]> pad(new string[5]);

9.2 模板类 vector

在头文件vector中定义了vector类。可以像使用数组一样使用vector(虽然vector的用法要更多)。

要创建vector,可以使用通常的<type>语法来指定要存储的数据的类型,并通过构造函数指定数据的数量。

#include <vector>
// ...
vector<int> arri(5);

9.2.1 使用 vector 类

因此可以用索引语法访问vector对象中的数据。

可对vector进行的操作:

  1. 所有容器都有的方法:

    • size():返回容器中的元素个数。
    • swap():交换两个容器的内容。
    • begin():返回指向容器中的一个元素的迭代器。
    • end():返回指向一个超出容器尾的迭代器。
  2. vector及其他部分容器具有的方法:
    • push_back():在容器结尾添加元素。
    • erase():删除指定“[)”区间的元素。
    • insert():在指定位置前插入一组数据。第一个参数为迭代器,指定插入位置。插入的数据可以用两个迭代器确定,也可以使用新增的初始化列表语法。

STL通过为每种容器都定义一个迭代器,给所有的容器都提供了统一的接口。

可以像下面这样使用迭代器(其实STL为下面的操作提供了更简便的方法):

vector<int> nums(5);
nums  = {1, 2, 3, 4, 5};
vector<int>::iterator pd = nums.begin();
for(pd; pd != nums.end(); ++pd)
    cout << *pd << ‘\t‘;

9.2.2 可以对 vector 进行的其他操作

  1. foreach(),前两个迭代器参数指定要进行操作的区间,第三个函数指针参数指定要进行的操作。

    vector<Review>::iterator pr;
    for (pr = books.begin(); pr != books.end(); pr++)
    	ShowReview(*pr);
    
    // 等价于以下代码
    for_each(books.begin(), books.end(), ShowReview);
    
  2. Random_shuffle(),接受两个指定区间的迭代器参数,并随机排列该区间中的元素。这个函数要求容器支持随机访问。
  3. sort():该函数也要求容器支持随机访问。该函数有两个版本:
    • 接受两个指定区间的迭代器,使用定义在容器内的<运算符对容器内的元素进行排序。
    • 接受两个指定区间的迭代器,并接受一个指定操作的函数指针。
      bool WorseThan(const Review & r1, const Review & r2)
      {
          if(r1.title < r2.title)
              return true;
          else if(r1.title == r2.title && r1.rating < r2.rating)
          	return true;
          else
              return false;
      }
      sort(books.begin(), books.end(), WorseThan);
      

原文地址:https://www.cnblogs.com/alohana/p/12571711.html

时间: 2024-10-09 10:15:36

9. string 类和标准模板库的相关文章

C++ Primer Plus 第六版 第16章 string类和标准模板库

1.string实际上是模板具体化basic_string<char> 的一个typedef,有默认参数,所以省略了初始化参数 2.size_type是一个依赖于实现的整形 string将string::npos定义为字符串的最大长度 3.string类的构造函数P656 4.对于c-风格字符串,3种输入方法:cin>>   cin.getline(),cin.get 对于string   ,2种输入方法:cin>>,getline(cin,string对象) 5.st

C++ primer plus读书笔记——第16章 string类和标准模板库

第16章 string类和标准模板库 1. string容易被忽略的构造函数: string(size_type n, char c)长度为n,每个字母都为c string(const string & str, size_type pos = 0, size_type n = pos)初始化为str中从pos开始到结尾的字符,或从pos开始的n个字符 string(const char *s, size_type n)初始化为s指向的前n个字符,即使超过了s的结尾: string(Iter b

《C++ Primer Plus》第16章 string类和标准模板库 学习笔记

C++提供了一组功能强大的库,这些库提供了很多常见编程问题的解决方案以及简化其他问题的工具string类为将字符串作为对象来处理提供了一种方便的方法.string类提供了自动内存管理动能以及众多处理字符串的方法和函数.例如,这些方法和函数让您能够合并字符串.将一个字符串插入到另一个字符串中.反转字符串.在字符串中搜索字符或姊姊富川以及执行输入和输出操作.诸如auto_ptr以及C++11新增的shared_ptr和unique_ptr等智能指针模板使得管理由new分配的内存更容易.如果使用这些智

C++——string类和标准模板库

一.string类 1.构造函数 string实际上是basic_string<char>的一个typedef,同时省略了与内存管理相关的参数.size_type是一个依赖于实现的整型,是在string中定义的.string类将string::npos定义为字符串的最大长度,通常为unsigned int的最大值.另外,使用缩写NBTS(null-terminated string)来表示以空字符结束的字符串——传统的C字符串.下面的表格中列出了string的构造函数: 构造函数 描述 str

C++标准模板库Stand Template Library(STL)简介与STL string类

参考<21天学通C++>第15和16章节,在对宏和模板学习之后,开启对C++实现的标准模板类STL进行简介,同时介绍简单的string类.虽然前面对于vector.deque.list等进行过学习和总结,但并没有一个宏观上的把握,现在通过上一篇和这一篇博文,将对C++模板以及基于C++模板的STL关联起来,形成一个总体的把握,对于掌握C++中模板(template)这一强有力的工具会十分有帮助.本文的主要内容有: (1) STL容器: (2) STL迭代器: (3) STL算法: (4) ST

C++标准模板库集合类与映射类总结

一.STL集合类 标准模板库向程序员提供了一些容器类,以便在应用程序中频繁而快速的搜索.std::set和std::multiset用于存储一组经过排序的元素,其查找元素的复杂度为对数,而unordered集合的插入和查找时间是固定的. 容器set和multiset快速查找键,键是存储在一维容器中的值,multiset可存储重复的键值,而set不行.STL容器是泛型模板类,可用于存储字符串.整型.结构或对象. 为了实现快速搜索,STL set和multiset内部结构类似二叉树,将元素插入到se

C++ Primer(第五版)学习笔记_5_标准模板库string(2)

C++ Primer(第五版)学习笔记_5_标准模板库string(2) 10.搜索string对象的元素或子串 采用find()方法可查找字符串中的第一个字符元素(char, 用单引号界定)或者子串(用双引号界定):如果查到,则返回下标值(从0开始计数),如果查不到,则返回一个很大的数string:npos(即:4294967295). #include <iostream> #include <stdio.h> #include <string> using nam

C++ Primer(第五版)学习笔记_4_标准模板库string(1)

C++ Primer(第五版)学习笔记_4_标准模板库string(1) 1.创建string对象 创建一个空字符串,其长度为0 #include <iostream> #include <string> using namespace std; int main(int argc, char* argv[]) { string s; cout << s.length() << endl; return 0; } 运行结果: 0 2.给string对象赋值

标准模板库

-------------------siwuxie095 在长期的编码中,聪明的程序员们发现:有一些代码经常碰到, 而且需求特别稳定,于是,各大公司在出售自己的 IDE 环境时, 就会把这些模板代码打包,一起销售 慢慢地,这些大公司之间就达成了某种共识,觉得应该把这些 涉及模板的通用代码进一步的统一和规范,于是,大家慢慢形 成了一套 C++ 的标准模板,就是现在所看到的标准模板库 标准模板库 标准模板库,即 Standard Template Lib,简称为 STL 标准模板库所涉及的内容非常