标准库 string 类型

string 类型支持长度可变的字符串,标准库 string 类型的满足对对字符串的一般应用。

与其他的标准库类型一样,用户程序要使用 string 类型对象,必须包含相关头文件。如果提供了合适的 using 声明,那么编写出来的程序将会变得简短些:

#include <string>
using std::string;

string 对象的定义和初始化

初始化string对象的几种方式:

string s1;

默认构造函数 s1 为空串

string s2(s1);

将 s2 初始化为 s1 的一个副本

string s3("value");

将 s3 初始化为一个字符串字面值副本

string s4(n, 'c');

将 s4 初始化为字符 'c' 的 n 个副本

若采用字符串字面值初始化,则该字面值中除了最后那个空字符外其他所有的字符都被拷贝到新创建的string对象中去。

直接初始化和拷贝初始化

如果使用等号(=)初始化一个变量,实际上执行的是拷贝初始化,编译器把等号右侧的初始值拷贝到新创建的对象中去,与之相反,如果不使用等号,则执行的是直接初始化。

当初始值只有一个时,使用直接初始化或拷贝初始化都行,但是如果初始化要用到多个值时一般只能采用直接初始化的方式:

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

对于上面s7的例子,如果非要采用拷贝初始化,则需要显示的创建一个临时对象:

string s8 = string (10,’c’);         //拷贝初始化

string对象上的操作

os<<s

将s写入到输出流os中,返回os

is>>s

从is中读取字符串赋给s,字符串以分隔,返回is

getline(is,s)

从is中读取一行赋给s,返回is

s.empty()

如果 s 为空串,则返回 true,否则返回 false。

s.size()

返回 s 中字符的个数

s[n]

返回 s 中位置为 n 的字符,位置从 0 开始计数

s1 + s2

把 s1 和 s2 连接成一个新字符串, 返回新生成的字符串

s1 = s2

把 s1 内容替换为 s2 的副本

s1 == s2

比较 v1 与 v2 的内容,相等则返回 true,否则返回 false

!=, <, <=, >, and >=

保持这些操作符惯有的含义

string 对象的读写

用 iostream 和 string 标准库,使用标准输入输出操作符来读写 string 对象:

int main()
{
string s; // empty string
cin >> s; // read whitespace-separated string into s
cout << s << endl; // write s to the output
return 0;
}

string 类型的输入操作符:

读取并忽略开头所有的空白字符(如空格,换行符,制表符)。

读取字符直至再次遇到空白字符,读取终止。

可以把多个读操作或多个写操作放在一起:

string s1, s2;
cin >> s1 >> s2; // read first input into s1, second into s2
cout << s1 << s2 << endl; // write both strings

读入未知数目的 string 对象

int main()
{
string word;
// read until end-of-file, writing each word to a new line
while (cin >> word)118
cout << word << endl;
return 0;
}

使用 getline 读取整行文本

getline接受两个参数:一个输入流对象和一个 string 对象。getline 函数从输入流的下一行读取,并保存读取的内容到不包括换行符。和输入操作符不一样的是,getline 并不忽略行开头的换行符。只要 getline 遇到换行符,即便它是输入的第一个字符,getline 也将停止读入并返回。如果第一个字符就是换行符,则 string 参数将被置为空 string。getline 函数将 istream 参数作为返回值,和输入操作符一样也把它用作判断条件。

每次输出一行文本:

int main()
{
string line;
// read line at time until end-of-file
while (getline(cin, line))
cout << line << endl;
return 0;
}

string 的 size 和 empty 操作

string 对象的长度指的是 string 对象中字符的个数,可以通过 size 操作获取。

了解 string 对象是否空是有用的。一种方法是将 size 与 0 进行比较:

if (st.size() == 0)
// ok: empty

用 string 的成员函数 empty() 可以更直接地回答这个问

题:

if (st.empty())
// ok: empty

empty() 成员函数将返回 bool,如果 string 对象为空则返回 true 否则返回 false。

string::size_type 类型

size 操作返回的是 string::size_type 类型的值。

虽然不知道 string::size_type 的确切类型,但可以知道它是 unsigned 型。

由于size函数返回的是一个无符号整型,因此,如果在表达式中混用了带符号数和无符号数将带来意想不到的结果:

s.size()<n     

若n是负值,则上面的表达式判断结果几乎肯定是true,因为负数n会自动转换成一个比较大的无符号值。

string 关系操作

string 对象比较操作是区分大小写的,在多数计算机上,大写的字母位于小写之前:任何一个大写之母都小于任意的小写字母。

== 操作符比较两个 string 对象,如果它们相等,则返回 true。两个 string 对象相等是指它们的长度相同,且含有相同的字符。标准库还定义了 != 操作符来测试两个 string 对象是否不等。

关系操作符 <,<=,>,>= 分别用于测试一个 string 对象是否小于、小于或等于、大于、大于或等于另一个 string 对象。

关系操作符比较两个 string 对象时采用了和字典排序相同的策略:

如果两个 string 对象长度不同, 且短的 string 对象与长的 string 对象的前面部分相匹配,则短的 string 对象小于长的 string 对象。

如果 string 对象的字符不同,则比较第一个不匹配的字符。

string 对象的赋值

对 string 对象来说,可以把一个 string 对象赋值给另一个 string 对象:

// st1 is an empty string, st2 is a copy of the literal
string st1, st2 = "The expense of spirit";
st1 = st2; // replace st1 by a copy of st2

赋值操作后,st1 就包含了 st2 串所有字符的一个副本。

大多数 string 库类型的赋值等操作的实现都会遇到一些效率上的问题,但值得注意的是, 从概念上讲, 赋值操作确实需要做一些工作。 它必须先把 st1 占

用的相关内存释放掉,然后再分配给 st2 足够存放 st2 副本的内存空间,最后

把 st2 中的所有字符复制到新分配的内存空间。

两个 string 对象相加

string 对象的加法被定义为连接(concatenation)。也就是说,两个(或多个)string 对象可以通过使用加操作符 + 或者复合赋值操作符 += 连接起来。给定两个 string 对象:

string s1("hello, ");
string s2("world\n");
string s3 = s1 + s2; // s3 is hello, world\n
s1 += s2; // equivalent to s1 = s1 + s2

string和字符串字面值的连接

可以通过

将 string 对象和字符串字面值混合连接:

string s1("hello");
string s2("world");
string s3 = s1 + ", " + s2 + "\n";

当进行 string 对象和字符串字面值混合连接操作时,+ 操作符的左右操作数必须至少有一个是 string 类型的:

string s1 = "hello";
string s5 = s1 + ", " + "world"; // ok: each + has string operand
string s6 = "hello" + ", " + s2; // error: can't add string literals

处理string对象中的字符

string 对象中字符的处理

这些函数都在 cctype 头文件中定义:

isalnum(c)

如果 c 是字母或数字,则为 True。

isalpha(c)

如果 c 是字母,则为 true。

iscntrl(c)

如果 c 是控制字符,则为 true

isdigit(c)

如果 c 是数字,则为 true。

isgraph(c)

如果 c 不是空格,但可打印,则为 true。

islower(c)

如果 c 是小写字母,则为 true。

isprint(c)

如果 c 是可打印的字符,则为 true。

ispunct(c)

如果 c 是标点符号,则 true。

isspace(c)

如果 c 是空白字符,则为 true。

isupper(c)

如果 c 是大写字母,则 true。

isxdigit(c)

如果是 c 十六进制数,则为 true。

tolower(c)

如果 c 大写字母,返回其小写字母形式,否则直接返回 c。

toupper(c)

如果 c 是小写字母,则返回其大写字母形式,否则直接返回 c。

使用基于范围for语句处理每个字符

范围for是C++11中新提供的,这种语句能够遍历给定序列中的每个元素并对序列中的每个值执行某种操作,其语法形式为:

for (declaration:expression)
       statement

其中,expression部分是一个对象,用于表示一个序列,declaration部分负责定义一个变量,该变量被用于访问序列中的基础元素,每次迭代declaration部分的变量会被初始化为expression部分的下一个元素值。

使用范围for语句把string对象中的字符每行一个输出出来:

string str(“some string”);
for (auto c:str)
       cout<<c<<endl;

使用范围for语句改变字符串中的字符

若想要改变string对象中字符的值,必须把循环变量定义成引用类型,使用这个引用就可以改变它绑定的字符。

把string对象转换成大写:

string s(“Hello World!!!”);
for(auto &c :s)
       c=toupper(c);
cout<<s<<endl;

从 string 对象获取字符

string 类型通过下标操作符([ ])来访问 string 对象中的单个字符。下标操作符需要取一个 size_type 类型的值,来标明要访问字符的位置。这个下标中的值通常被称为“下标”或“索引”(index):

string 对象的下标从 0 开始。如果 s 是一个 string 对象且 s 不空,则 s[0] 就是字符串的第一个字符, s[1] 就表示第二个字符(如果有的话),而 s[s.size() - 1] 则表示 s 的最后一个字符。

引用下标时如果超出下标作用范围就会引起溢出错误。

下标操作可用作左值

string 对象的下标操作返回值也是左值。因此,下标操作可以放于赋值操作符的左边或右边。通过下面循环把 str 对象的每一个字符置为 ‘*’:

for (string::size_type ix = 0; ix != str.size(); ++ix)
str[ix] = '*';

计算下标值

任何可产生整型值的表达式可用作下标操作符的索引。例如,假设 someval 和 someotherval 是两个整形对象,可以这样写:

str[someotherval * someval] = someval;

虽然任何整型数值都可作为索引,但索引的实际数据类型却是类型 unsigned 类型 string::size_type。

标准库不要求检查索引值,所用索引的下标越界是没有定义的,这样往往会导致严重的运行时错误。

posted @ 2018-04-27 17:30  刘-皇叔  阅读(238)  评论(0编辑  收藏  举报