string

string是长度不定的字符串。为了使用string类型,需要:

#include <string>
using std::string;

当然,有的编译器可能直接把上述内容直接包含到<iostream>等,参见 can std::string be used without #include

定义和初始化string

下面是最常见的初始化string的方法:

string s1; // 默认初始化;s1是个空串
string s2(s1); // s2 是 s1 的拷贝
string s2 = s1; // 等价于 s2(s1)。
string s3("value"); // 字符串字面常量的拷贝
string s3 = "value"; // 等价于 s3("value")
string s4(n, 'c'); // 用n个字符'c'的拷贝初始化

初始化的直接或拷贝形式

当我们使用=初始化变量时,是在要求编译器去拷贝初始化(copy initialize);当忽略=时,就是直接初始化(direct initialization)。

当我们只有一个初始化器时,使用初始化的拷贝或直接初始化是无所谓的。当我们要从多个值初始化变量,比如上面的s4,我们必须使用直接初始化。

string s5 = "hiya"; // 拷贝初始化
string s6("hiya"); // 直接初始化
string s7(10, 'c'); // 直接初始化

注意string s8 = string(10, 'c')这样的拷贝初始化,显式地创建了一个临时对象。

string的操作

下面是string对象的最常见的操作:

os << s // 写s到流os;返回os
is >> s // 从is读空白符分隔的字符串到s;返回is
getline(is, s) // 从is读取一行输入到s;返回is
s.empty()
s.size()
s[n] // 返回n位置字符的引用
s1 + s2
s1 = s2
s1 == s2
s1 != s2
< <= > >=

读取不确定数目的strings:

string word;
while(cin >> word)
    cout << word << endl;

使用getline读取整行:

while(getlien(cin, line))
   cout << line << endl;

string::size_type类型

我们可能很自然的想:size返回的是int或者unsigned。当实际上,它返回的是string::size_type类型。

string和很多库类型定义了很多伴随类型(companion type)。这使得它能够依赖机器的使用。size_type就是一个伴随 类型。虽然我们不知道其具体类型,但我们知道它是一个无符号类型,足以容纳任何大小的字符串。

显然,写代码时敲出string::size_type很麻烦,我们可以使用auto或者decltype

strings和字面字符串的相加

要注意的是,使用+来连接它们时,至少一个得是string类型

string s4 = s1 + ","; // ok
string s5 = "hello" + ","; // error
string s6 = "hello" + "," + s2; // error

因为历史原因,和为了和C语言兼容,字符串字面常量不是标准库里的strings。

处理字符

关于处理字符的函数,比如判断是不是字母,是不是大写等,都在cctype头文件里。

函数 解释
isalpha 是不是大写
isdigit 是不是数字
... ...

使用C++版本的C库。建议使用c开头的版本,而不是.h版本。

范围for

C++ 11引入了新的range for语句。语法是:

for (declartion : expression)
   statement

比如下面的遍历字符串的语句,

string str("hello world");
for (auto c : str)
  cout << c << endl;

下面是统计字符串里面的标点符号数:

string s("hello world!!!");
decltype(s.size()) punct_cnt = 0;
for (auto c : s)
   if (ispunct(c))
      ++punct_cnt;

在range for里面修改字符串

如果要在range for里面修改字符串,必须把循环变量定义成引用类型

下面是把字符串里面的字符都变成大写的:

for (auto &c : s)
  c = toupper(c);

如果不使用引用,对原串没有影响。

下标操作符

下标操作符[]接受的是一个string::size_type类型的参数。如果传递一个signed的值,会先变成unsinged。

需要手动检查下标的合法边界