String 类和 STL (Standard Template Library)
一. string 类
很多应用程序都需要处理字符串。C语言在string.h(在++中为cstring)中提供了一系列的字符串函数,很多早期的C++实现为处理字符串提供了自己的类。
string类是由头文件string支持的(以头文件string.h和cstring支持对C风格字符串进行操纵的C库字符串函数,但不支持string类)。要使用类,关键在于知道它的公有接口,而string类包含大量的方法,其中包括了若干构造函数,用于将字符串赋给变量、合并字符串、比较字符串和访问各个元素的重载运算符以及用于在字符串中查找字符和子字符串的工具等。以string类包含的内容很多。
1. 构造字符串
先来看string的构造函数。毕竟,对于类而言,最重要的内容之一是,有哪些方法可用于创建其对象。程序清单1使用了string的7个构造函数(用ctor标识,这是传统C++中构造函数的缩写)。表1简要地描述了这些构造函数,它首先按顺序简要描述了程序清单1使用的7个构造函数,然后列出了C++11新增的两个构造函数。使用构造函数时都进行了简化,即隐藏了这样一个事实:string实际上是模板具体化basic_string<char>的一个typedef,同时省略了与内存管理相关的参数。 size_type是一个依赖于实现的整型,是在头文件string中定义的。string类将string::npos定义为字符串的最大长度,通常为unsigned int的最大值。以表格中使用缩写NBTS(null终止string)来表示以空字符结束的字符串一一传统的C字符串。
表1 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 = npos)
将一个string对象初始化为对象str中从位置pos开始到结尾的字符,或从位置pos开始的n个字符
string(string && str) noexcept
这是C++11新增的,它将一个string对象初始化为string对象str,并可能修改str(移动构造函数)
string(initializer_list<char> il)
这是C++11新增的,它将一个string对象初始化为初始化列表il中的字符
程序清单1 :
#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 "; //will Clean up the original string in object two
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";
cout << "Now four is :" << four << endl;
string eight(four, 7, 16); // ctor #7
cout << eight << " in motion!" << endl;
system("pause");
return 0;
}
程序清单1 的输出:
Lottery Winner!
$$$$$$$$$$$$$$$$$$$$
Lottery Winner!
Lottery Winner! Oops!
Sorry! That was Pottery Winner!
All's well that ends!
well, well...
Now four is :Sorry! That was Pottery Winner!
That was Pottery in motion!
Press any key to continue . . .
2. string类输入
有哪些输入方式可用呢? 对于C风格的字符串, 有3种方式:
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(cin,stuff, ':'); // read up to :, discard :
对于string版本的getline() 能够自动调整目标string 对象的大小, 使之刚好能存储输入的字符:
char fname[10];
string lname;
cin >> fname; // could be a problem if input size > 9 characters
cin >> lname; // can read a very, very long word
cin.getline(fname, 10); // may truncate input
getline(cin, fname); // no truncation
自动调整大小的功能让 string版本的getline() 不需要指定要读取多少个字符的参数
string 版本的 getline() 从输入流中读取字符, 并将其放入目标string 中, 直到发生下面几种情况:
- 到达文件尾的输入流的eofbit将被设置,这意味着方法fail()和eof()都将返回true;
- 遇到分界字符(默认为\n) 在这种情况下, 将把分界字符从输入流中删除,但不存储它;
- 读取的字符数达到最大允许值(string::npos和可供分配的内存字节数中较小的一个) 在这种情况下,将设置输入流的failbit,这意味着方法fail()将返回true。
eofbit fail()等与 流状态 相关, 将在 ~ C++输入输出和文件 -> 三. 使用cin进行输入 -> 2. 流状态 ~ 中讲解
3. 使用字符串
字符串比较
string 类对全部6个关系运算符都进行了重载, 如果机器排列序列为ASCII码, 那么数字字符 < 大写字符 < 小写字符;
对于每个关系运算符, 都以三种方式被重载, 以便将string对象和 另一个string对象,C风格字符串 进行比较 :#include <iostream>
#include <exception>
int main()
{
using namespace std;
string snake1("cobra");
string snake2("coaal");
char snake3[20] = "cobra";
if (snake1 < snake2) // operator<(const string &, const string &)
{
cout << "snake1 < snake 2" << endl;
}
if (snake1 == snake3) // operator==(const string &, const char *)
{
cout << "snake1 == snake3" << endl;
} if (snake3 != snake2) // operator!=(const char *, const string &)
{
cout << "snake3 != snake2" << endl;
}
system("pause");
return 0;
}
size() 和 length() 都返回字符串的字符数
length()成员来自较早版本的string类, 而size()则是为STL兼容性而添加的字符串查找
string::npos是字符串可存储的最大字符数, 通常是无符号int或long的最大取值;表2 重载的find()方法方 法 原 型
描 述
size_type find(const string & str,
size_type pos = 0)const从字符串的pos位置开始,查找子字符串str。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回string :: npos
size_type find(const char * s,
size_type pos = 0)const从字符串的pos位置开始,查找子字符串s。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回string :: npos
size_type find(const char * s,
size_type pos, size_type n)从字符串的pos位置开始,查找s的前n个字符组成的子字符串。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回string :: npos
size_type find(char ch,
size_type pos = 0)const从字符串的pos位置开始,查找字符ch。如果找到,则返回该字符首次出现的位置;否则,返回string :: npos
string 库还提供了相关的方法: rfind()、find_first_of()、find_last_of()、find_first_not_of()和find_last_not_of(),它们的重载函数特征标都与find()方法相同。rfind()方法查找子字符串或字符最后一次出现的位置;find_first_of()方法在字符串中查找参数中任何一个字符首次出现的位置。例如,下面的语句返回 r 在“cobra”中的位置(即索引3),因为这是“hark”中各个字母在“cobra”首次出现的位置:
int where = snake1.find_first_of("hark");
find_last_of()方法的功能与此相同,只是它查找的是最后一次出现的位置。因此,下面的语句返回a在“cobra”中的位置:
int where = snake1.find_last_of("hark");
find_first_not_of()方法在字符串中查找第一个不包含在参数中的字符,因此下面的语句返回c在“cobra”中的位置,因为“hark”中没有c:
int where = snake1.find_first_not_of("hark");
4. 其他string类方法
很多, 就萝莉一些, 再挑几个讲. 其他的用到的时候就知道了
a) =,assign() //赋以新值
b) swap() //交换两个字符串的内容
c) +=,append(),push_back() //在尾部添加字符
d) insert() //插入字符
e) erase() //删除字符
f) clear() //删除全部字符
g) replace() //替换字符
h) + //串联字符串
i) ==,!=,<,<=,>,>=,compare() //比较字符串
j) size(),length() //返回字符数量
k) max_size() //返回字符的可能最大个数
l) empty() //判断字符串是否为空
m) capacity() //返回重新分配之前的字符容量
n) reserve() //保留一定量内存以容纳一定数量的字符
o) [], at() //存取单一字符 at()索引无效时,会抛出out_of_range异常
p) >>,getline() //从stream读取某值
q) << //将谋值写入stream
r) copy() //将某值赋值为一个C_string
s) c_str() //将内容以C_string返回 不可修改
t) data() //将内容以字符序列指针形式返回 可修改
u) substr() //返回某个子字符串
v)查找函数
w)begin() end() //提供类似STL的迭代器支持
x) rbegin() rend() //逆向迭代器
y) get_allocator() //返回配置器
compare 返回值意义(吾用区间表示法表示):[小于,0,大于] , 0:相等
string s("abcd");
s.compare("abcd"); //返回0
s.compare("dcba"); //返回一个小于0的值
s.compare("ab"); //返回大于0的值
s.compare(s); //相等
//参数1:下标 2:字符个数 3:比较的对象 4:下标 5:字符个数
s.compare(0,2,s,2,2); //用"ab"和"cd"进行比较 小于零
//参数1:下标 2:字符个数 3:比较的对象 4:字符个数
s.compare(1,2,"bcx",2); //用"bc"和"bc"比较。
assign 重新分配
s.assign(str); //字面意思
//参数1:目标 2:下标 3:字符数
s.assign(str,1,3);//如果str是"iamangel" 就是把"ama"赋给字符串
s.assign(str,2,string::npos);//把字符串str从索引值2开始到结尾赋给s
s.assign("gaint"); //字面意思
s.assign("nico",5);//把’n’ ‘I’ ‘c’ ‘o’ ‘’赋给字符串
s.assign(5,'x');//把五个x赋给字符串
append 附加
s.append(str);
s.append(str,1,3);//不解释了 同前面的函数参数assign的解释
s.append(str,2,string::npos)//
s.append("my name is jiayp");
s.append("nico",5);
s.append(5,'x');
s.push_back('a');//这个函数只能增加单个字符
insert 插入
s.insert(0,"my name");
s.insert(1, "m");
s.insert(1,str);
replace erase 替换和擦除
s.replace(1,2,"nternationalizatio");//从索引1开始的2个替换成后面的C_string或string对象
s.erase(13);//从索引13开始往后全删除
s.erase(7,5);//从索引7开始往后删5个
substr 返回子字符串(新的string)
s.substr();//返回s的全部内容
s.substr(11);//从索引11往后的子串
s.substr(5,6);//从索引5开始6个字符
copy 复制并替换目标中原有的字符
char str1[20] = "Hello";
char str2[20] {0};
string sl = "World";
//参数1:目标对象 2:要copy的字符数 3:从sl的下标?开始
sl.copy(str1, 5, 2);//
cout << str1 << endl;
方法capacity()返回当前分配给字符串的内存块的大小,而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;
return 0;
}
如果您有string对象,但需要C风格字符串,该如何办呢?
string filename;
filename.c_str(); //返回c风格字符串
5. 字符串种类
本节将string类看作是基于char类型的。事实上,正如前面指出的,string库实际上是基于一个模板类的:
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类描述关于选定字符类型的特定情况,如如何对值进行比较。对于wchar_t、char16_t、char32_t和char类型,有预定义的char_traits模板具体化,它们都是traits的默认值。Allocator是一个管理内存分配的类。对于各种字符类型,都有预定义的allocator模板具体化,它们都是默认的。它们使用new和delete。
String 类和 STL (Standard Template Library)的更多相关文章
- [c++] STL = Standard Template Library
How many people give up, because of YOU. Continue... 先实践,最后需要总结. 1. 数据流中的数据按照一定的格式<T>提取 ------ ...
- C++ Standard Template Library STL(undone)
目录 . C++标准模版库(Standard Template Library STL) . C++ STL容器 . C++ STL 顺序性容器 . C++ STL 关联式容器 . C++ STL 容 ...
- C++ Standard Template Library (STL) 高级容器
更多 STL 数据结构请阅读 NOIp 数据结构专题总结(STL structure 章节) std::map Definition: template < class Key, // map: ...
- <Standard Template Library>标准模板库专项复习总结(一)
看了看博客园的申请时间也一年多了...想想自己一年多以来一直处于各种划水状态,现在又要面临ACM的冲击... 还是要抓紧时间赶紧复习一下了- -毕竟校园新生赛还是有奖金的.. 1.栈 先进后出(LIF ...
- <Standard Template Library>标准模板库专项复习总结(二)
4.队列 先进先出(FIFO)表 头文件:#include<queue> 变量的定义:queue<TYPE>queueName 成员函数: bool empty() 空队列返回 ...
- string类------新标准c++程序设计
定义: string类是STL中basic_string模板实例化得到的模板类.其定义如下: typedef basic_string<char>string; 构造函数: string类 ...
- C++标准模板库Stand Template Library(STL)简介与STL string类
参考<21天学通C++>第15和16章节,在对宏和模板学习之后,开启对C++实现的标准模板类STL进行简介,同时介绍简单的string类.虽然前面对于vector.deque.list等进 ...
- STL 的string类怎么啦?
前言 上个周末在和我的同学爬香山闲聊时,同学说到STL中的string类曾经让他备受折磨,几年前他开发一个系统前对string类还比较清楚,然后随着程序的复杂度的加深,到了后期,他几乎对strin ...
- STL库中string类内存布局的探究
在STL中有着一个类就是string类,他的内存布局和存储机制究竟是怎么样的呢? 这就是建立好的string 可以看出,图中用黄色框框标注的部分就是主要区域 我们用来给string对象进行初始化的字符 ...
- STL:string类中size()与length()的区别
结论是:两者没有任何区别 解释: C++Reference中对于两者的解释: 两者的具体解释都一模一样: 理解: length是因为C语言的习惯而保留下来的,string类最初只有length,引进S ...
随机推荐
- SQL函数union,union all整理
SQL集合函数--并集union,union all 本次整理从4个方面展示union函数,union all函数的风采: 1.集合函数使用规则 2.集合函数作用 3.数据准备及函数效果展示 首先1. ...
- 关于tiptop gp5.2采购模块,价格变更的随笔
采购价格变更要看具体环节,你可以把他当作是三张表,采购价格表.收货价格表.入库价格表,这些还好处理,如果已抛砖到财务端生成账款再要求改价格就更复杂,会产生更多张表了,改起来也就更复杂. 用apmt91 ...
- Arduino入门教程
Arduino入门教程 Arduino是一款简单易学的开源电子原型平台,包含硬件(各种型号的Arduino板)和软件(Arduino IDE).它通过各种各样的传感器来感知环境,再通过控制 ...
- nittest单元测试框架—加载测试用例的3种方法以及测试报告存储管理
项目结构 测试用例 import unittest class LoginTestCase(unittest.TestCase): def test_login_success(self): self ...
- docker入门加实战—部署Java和前端项目
docker入门加实战-部署Java和前端项目 部署之前,先删除nginx,和自己创建的dd两个容器: docker rm -f nginx dd 部署Java项目 作为演示,我们的Java项目比较简 ...
- Mac OS安装Python的pip
最近牛牛的同学在学习python,但当他使用numpy时出现了报错(。•́︿•̀。) 原因为他的python没有numpy这个库(这个故事很典).然鹅雪上加霜的是,他的电脑是Mac,没有Windows ...
- 如何为你的WSL2更换最新的6.5.7kernel
1.如果你像我一样,喜欢折腾你的 WSL2 ,这里是安装内核 6.X 的方法. 2.这是一个坏主意,可能会导致系统不稳定.数据损坏和其他问题.也可能会没事的,但不要怪我. Arch linux的wsl ...
- 如何避免JavaScript中的内存泄漏?
前言 过去,我们浏览静态网站时无须过多关注内存管理,因为加载新页面时,之前的页面信息会从内存中删除. 然而,随着单页Web应用(SPA)的兴起,应用程序消耗的内存越来越多,这不仅会降低浏览器性能,甚至 ...
- QT中级(1)QTableView自定义委托(一)实现QSpinBox、QDoubleSpinBox委托
1 写在前面的话 我们在之前写的<QT(7)-初识委托>文章末尾提到,"使用一个类继承QStyledItemDelegate实现常用的控件委托,在使用时可以直接调用接口,灵活实现 ...
- tcpdump必知必会
tcpdump原理 & 在tcp协议栈的位置 tcpdump用法 基于协议.主机.端口过滤 使用and or逻辑运算符做复杂的过滤操作 tcpdump flags 1. tcpdump原理 l ...