string类介绍
string类是由头文件string支持的,string库实际上是基于一个模板类的typedef:
template<class charT, class traits = char _traits<charT>,
class Allocator = allocator<charT> >
basic_string {...};
模板basic_string有4个具体化,每个具体化都有一个typedef名称:
typedef basic_string<char> string;
typedef basic_string<wchar_t> wstring;
typedef basic_string<char16_t> u16string; //C++11
typedef basic_string<char32_t> u32string; //C++11
这让您能够使用基于类型wchar_t、char16_t、char32_t和char的字符串。甚至可以开发某种类似字符的类,并对它使用basic_string类模板(只要他满足某些要求)。traits类描述关于选定字符类型的特定情况,如如何对值进行比较。对于char、wchar、char16_t和char32_t类型,有预定义的char_traits模板具体化,他们都是traits的默认值。Allocator是一个管理内存分配的的类。对于各种字符类型,都有预定义的allocator模板具体化,他们都是默认的。他们使用new和delete。
string类的构造函数
构造函数 | 描述 |
---|---|
string(const char* s) | 将string对象初始化为s指向的NBTS |
string(size_type n,char c) | 创建一个包含n个元素的string对象,每个元素都被初始化为字符c |
string(const string & str) | 将一个string对象初始化为string对象str(复制构造函数) |
string() | 创建一个默认的string对象,长度为0(默认构造函数) |
string(const char* s,size_type n) | 将string对象初始化为s指向的NBTS的前n个字符,即使超过了NBTS结尾 |
template< class Iter > string(Iter begin,Iter end) | 将string对象初始化为区间[begin,end)内的字符,其中begin和end的行为就像指针,用于指定位置,范围包含begin,但不包含end |
string(const string & str,size_type pos,size_type n= pose) | 将一个string对象初始化为对象str中从位置pos开始到结尾的字符,或从位置pos开始的n个字符 |
string(string && str)noexcept | c++11新增的,他将一个string对象初始化为string对象str,并可能修改str(移动构造函数) |
string(initializer_list< char > il) | c++11新增,他将一个string对象初始化为初始化列表il中的字符 |
上表中一些名词解释:
size_type是一个依赖于实现的整形,是在头文件string中定义的。string将string::npos定义为字符串的最大长度,通常为unsigned int的最大值。表格中的NBTS(null-terminated string)表示以空字符结束的字符串—传统c字符串。下面的例子程序展示了各个构造函数的用法:
// str1.cpp -- introducing the string class
#include <iostream>
#include <string>
// using string constructors
int main()
{
using namespace std;
string one("Lottery Winner!"); // ctor #1
cout << one << endl; // overloaded <<
string two(20, '$'); // ctor #2
cout << two << endl;
string three(one); // ctor #3
cout << three << endl;
one += " Oops!"; // overloaded +=
cout << one << endl;
two = "Sorry! That was ";
three[0] = 'P';
string four; // ctor #4
four = two + three; // overloaded +, =
cout << four << endl;
char alls[] = "All's well that ends well";
string five(alls,20); // ctor #5
cout << five << "!\n";
string six(alls+6, alls + 10); // ctor #6
cout << six << ", ";
string seven(&five[6], &five[10]); // ctor #6 again
cout << seven << "...\n";
string eight(four, 7, 16); // ctor #7
cout << eight << " in motion!" << endl;
// std::cin.get();
string nine = { 'w','e','l','l' };
cout << nine << endl; //ctor #9
return 0;
}
输出如下:
Lottery Winner!
$$$$$$$$$$$$$$$$$$$$
Lottery Winner!
Lottery Winner! Oops!
Sorry! That was Pottery Winner!
All's well that ends!
well, well...
That was Pottery in motion!
well
string类输入
对于c风格字符串,有三种方式:
char info[100];
cin >> info; //read a word
cin.getline(info,100); //read a line,discard \n
cin.get(info,100); //read a line,leave \n in queue
对于string对象,有两种方式:
string stuff;
cin >> stuff; //read a word
getline(cin,stuff); //read a line,discard \n
两个版本的getline都有一个可选参数,用于指定使用哪个字符来确定输入的边界:
cin.getline(info,100,':'); //read up to :,discard :
getline(stuff,':'); //read up to :,discard :
在功能上的区别在于string版本的getline()将自动调整目标string对象的大小,使之刚好能够存储输入的字符。
在设计上的区别是读取c风格字符串的函数是istream类的方法,而string版本是独立的函数。这就是对于c风格字符串输入,cin是调用对象;而对于string对象输入,cin是一个函数参数的原因。
string版本的getline()函数从输入中读取字符,并将其存储到目标string中,直到发生下列三种情况之一:
- 到达文件尾,在这种情况下,输入流的eofbit将被设置,这意味着方法fail()和eof()都将返回true;
- 遇到分界字符(默认为\n),在这种情况下,将把分界字符从输入流中删除,但不存储它。
- 读取的字符数达到最大允许值(string::npos和可供分配的内存字节数中较小的一个),在这种情况下,将设置输入流的failbit,这意味着方法fail()将返回ture。
string版本的operator>>()函数的行为与此类似,只是它不断读取,直到遇到空白字符并将它留在输入队列中,而不是不断读取,直到遇到分界字符并将其丢弃。空白字符指的是空格,换行符和制表符。更普遍地说,是是任何将其作为参数来调用isspace()时返回true的函数。
string的其他方法
string 库提供了很多其他的工具,包括完成下述功能的函数:删除字符串的部分或全部内容、用一个字符串的部分或全部内容替换另一个字符串的部分或全部内容、将数据插人到字符串中或删除字符串中的数据、将一个字符串的部分或全部内容与另一个字符串的部分或全部内容进行比较、从字符串中提取子字符串、将一个字符串中的内容复制到另一个字符串中、交换两个字符串的内容。这些函数中的大多数都被重载,以便能够同时处理C风格字符串和 string对象。了解更多。
首先来看自动调整大小的功能。每当程序将一个字母附加到字符串末尾时将发生什么呢?不能仅仅将已有的字符串加大,因为相邻的内存可能被占用了。因此,可能需要分配一个新的内存块,并将原来的内容复制到新的内存单元中。如果执行大量这样的操作,效率将非常低,因此很多C++实现分配一个比实际字符串大的内存块,为字符串提供了增大空间。然而,如果字符串不断增大,超过了内存块的大小,程序将分配一个大小为原来两倍的新内存块,以提供足够的增大空间,避免不断地分配新的内存块。方法 capacity()返回当前分配给字符串的内存块的大小。而reserve()方法让您能够请求内存块的最小长度。下列程序演示了capacity()和reverse()的细节:
// str2.cpp -- capacity() and reserve()
#include <iostream>
#include <string>
int main()
{
using namespace std;
string empty;
string small = "bit";
string larger = "Elephants are a girl's best friend";
cout << "Sizes:\n";
cout << "\tempty: " << empty.size() << endl;
cout << "\tsmall: " << small.size() << endl;
cout << "\tlarger: " << larger.size() << endl;
cout << "Capacities:\n";
cout << "\tempty: " << empty.capacity() << endl;
cout << "\tsmall: " << small.capacity() << endl;
cout << "\tlarger: " << larger.capacity() << endl;
empty.reserve(50);
cout << "Capacity after empty.reserve(50): "
<< empty.capacity() << endl;
// cin.get();
return 0;
}
输出如下:
Sizes:
empty: 0
small: 3
larger: 34
Capacities:
empty: 15
small: 15
larger: 47
Capacity after empty.reserve(50): 63