71.C++标准库类型string

发布时间 2023-03-22 23:03:50作者: CodeMagicianT

  标准库类型string表示可变长的字符序列,使用string类型必须首先包含 string头文件。作为标准库的一部分,string定义在命名空间std中。接下来的示例都假定已包含了下述代码:

itinclude <string> 
using std::string; 

1.定义和初始化string对象

  如何初始化类的对象是由类本身决定的。 一个类可以定义很多种初始化对象的方式,只不过这些方式之间必须有所区别:或者是初始值的数量不同,或者是初始值的类型不同。

初始化string对象的方式

指令 解释
string s1 默认初始化,s1是一个空串
string s2(s1) s2 是 s1 的副本
string s2=s1 等价于 s2(s1),s2 是 s1 的副本
string s3(“value”) s3 是字面值"value"的副本,除了字面值最后的那个空字符除外
string s3=“value” 等价于 s3(“value”),s3 是字面值"value"的副本
string s4(n, ‘c’) 把 s4 初始化为由连续 n 个字符 c 组成的
string s5(cp, n) s5 是 cp 指向的数组中前 n 个字符的拷贝。此数组至少应包含 n 个字符
string s5(s1, pos1) s5是string s1从下标 pos1 开始的字符的拷贝。若pos1>s1.size(),构造函数的行为未定义
string s5(s1, pos1, len1) s5 是string s1从下标 pos1 开始进行 len1 个字符的拷贝。若pos1>s1.size(),构造函数的行为未定义。不管len1的值是多少,构造函数至多拷贝s1.size()-pos1个字符。
s.substr(pos, n) 返回一个string,包含 s 中从pos开始的 n 个字符的拷贝。pos 的默认值为0,。n 的默认值为s.szie()-pos,即拷贝从pos开始的所有字符。

2. string 对象上的操作

2.1读写string对象

可以使用IO操作符读写string对象:

//注意:要想编译下面的代码还需要适当的#include语句和using声明
int main()
{
    string s;//空字符串
    cin >> s;//将string对象读入s,遇到空白停止
    cout << s << endl; //输出s
    return 0; 
}

  这段程序首先定义一个名为s的空string,然后将标准输入的内容读取到s中。在执行读取操作时,string对象会自动忽略开头的空白(即空格符、换行符、制表符等)并从第一个真正的字符开始读起, 直到遇见下一处空白为止。
  如上所述,如果程序的输入是“ Hello World! " (注意开头和结尾处的空格),则输出将是“Hello",输出结果中没有任何空格。和内置类型的输入输出操作一样,string对象的此类操作也是返回运算符左侧的运算对象作为其结果。因此,多个输入或者多个输出可以连写在一起:

string s1, s2; 
cin >> s1 >> s2; //把笫一个输入读到s1中, 笫二个输入读到s2中
cout << s1 << s2 << endl; //输出两个string对象

  假设给上面这段程序输入与之前一样的内容“ Hello World! ", 输出将是"HelloWorld!"。

2.2读取未知数量的string对象

int main()
{
    string word; 
    while (cin >> word)//反复读取,直至到达文件末尾
        cout << word<< endl;//逐个输出单词, 每个单词后面紧跟一个换行 
    return 0; 
}

  如果流有效,也就是说没遇到文件结束标记或非法输入, 那么执行while语句内部的操作。

2.3使用getline读取一整行

  有时我们希望能在最终得到的字符串中保留输入时的空白符,这时应该用getline函数代替原来的>>运算符。 getline函数的参数是一个输入流和一个string对象, 函数从给定的输入流中读入内容, 直到遇到换行符为止(注意换行符也被读进来了),然后把所读的内容存入到那个string对象中去(注意不存换行符)。getline只要一遇到换行符就结束读取操作并返回结果, 哪怕输入的一开始就是换行符也是如此。 如果输入真的一开始就是换行符, 那么所得的结果是个空string。
  和输入运算符一样, getline也会返回它的流参数。 因此既然输入运算符能作为判断的条件(参见C++Primer1.4.3节, 第13页), 我们也能用getline的结果作为条件。 例如, 可以通过改写之前的程序让它一次性输入整行, 而不再是每行输出 个词了:

int main() 
{
    string line; 
    //每次读入一整行, 直至到达文件末尾
    while (getline (cin, line)) 
        cout << line << endl; 
    return 0; 
}

  因为line中不包含换行符, 所以我们手动地加上换行操作符。和往常一样, 使用endl结束当前行并刷新显示缓冲区。

2.4string的empty和size操作

  empty函数根据string对象是否为空返回一个对应的布尔值。

//每次读入一整行,遇到空行直接跳过
while (getline(cin, line)) 
    if (!line. empty()) 
        cout << line << endl; 

  size函数返回string对象的长度(即string对象中字符的个数),可以使用size函数只输出长度超过80个字符的行:

String line; 
//每次读入一整行,输出其中超过80个字符的行
while (getline(cin, line)) 
    if (line.size() > 80) 
        cout << line << endl; 

2.5string::size_type类型

  对于size函数来说,返回一个int或者如前面C++Primer2.1.1节(第31页)所述的那样返回一个unsigned似乎都是合情合理的。但其实size函数返回的是一个string: :size_type类型的值,下面就对这种新的类型稍作解释。string类及其他大多数标准库类型都定义了几种配套的类型。这些配套类型体现了标准库类型与机器无关的特性,类型size_type即是其中的一种。在具体使用的时候,通过作用域操作符来表明名字size_type是在类string中定义的。

  它是一个无符号类型的值(参见C++Primer2.1.1节,第30页)而且能足够存放下任何string对象的大小。所有用于存放string类的size函数返回值的变量,都应该是string::size_type类型的。

在C++11新标准中,允许编译器通过auto或者decltype(参见2.5.2节,第61页)来推断变量的类型:

auto len = line.size();//len的类型是string::size_type 

  由于size函数返回的是一个无符号整型数,因此切记,如果在表达式中混用了带符号数和无符号数将可能产生意想不到的结果(参见C++Primer2.1.2节,第33负)。例如,假设n是一个具有负值的int,则表达式s.size()<n的判断结果几乎肯定是true。这是因为负值n会自动地转换成一个比较大的无符号值。

2.6比较string对象

  string类定义了几种用于比较字符串的运算符。这些比较运算符逐—比较string对象中的字符,并且对大小写敏感,也就是说,在比较时同一个字母的大写形式和小写形式是不同的。

●1.如果两个string对象的长度不同,而且较短string对象的每个字符都与较长string对象对应位置上的字符相同,就说较短string对象小于较长string 对象。

●2.如果两个string对象在某些对应的位置上不一致,则string对象比较的结果其实是string对象中第一对相异字符比较的结果。

compare 函数

标准库 String 类型还提供了 compare 函数,与 C 中的 strcmp 函数很相似。

形式:s.compare(args);

函数()内的参数 解释
s2 比较 s 和 s2
pos1, n1 ,s2 将 s 中从 pos1 开始的 n1 个字符与 s2进行比较
pos1, n1, s2, pos2, n2 将 s 中从 pos1 开始的 n1 个字符与 s2 中从 pos2开始的 n2 个字符进行比较
cp 比较 s 与 cp 指向的以空字符结尾的字符数组
pos1, n1, cp 将 s 中从 pos1 开始的 n1 个字符与 cp 指向的以空字符结尾的字符数组进行比较
pos1, n1, cp, n2 将 s 中从 pos1 开始的 n1 个字符与指针 cp 指向的地址开始的 n2 个字符进行比较

2.7为对象赋值

  一般来说,在设计标准库类型时都力求在易用性上向内置类型乔齐,因此大多数库类型都支持赋值操作。对于string类而言,允许把个对象:

string st1(1O, 'c'), st2;//st1的内容是cccccccccc;st2是一个空字符串
st1 = st2; 

2.8两个对象相加

  两个string对象相加得到一个新的string对象,其内容是把左侧的运算对象与右侧的运算对象串接而成。也就是说,对string对象使用加法运算符(+)的结果是一个新的string对象,它所包含的字符由两部分组成:前半部分是加号左侧string对象所含的字符、后半部分是加号右侧string对象所含的字符。另外,复合赋值运算符(+=) (参见C++Primer1.4.1节,第10页)负责把右侧string对象的内容追加到左侧string对象的后面:

string s1 = "hello, ", s2 = "world\n";
strings3 = s1 + s2;//s3的内容是hello,world\n
s1 += s2;//等价于s1= s1 + s2 

2.9字面值和string对象相加

  因为标准库允许把字符字面值和字符串字面值 (参见2.1.3节,第36页)转换成string对象,所以在需要string对象的地方就可以使用这两种字面值来替代。利用这点将之前的程序改写为如下形式:

string s1 = "hello", s2 = "world";//在s1和s2中都没有标点符号 
string s3 = s1 + ", " + s2 +'\n'; 

  当把string对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符(+)的两侧的运算对象至少有一个是string:

string s4 = s1 + ", ";//正确:把一个string对象和一个字面值相加
string s5 = "hello" + ", ";//错误: 两个运算对象都不是string 
//正确:每个加法运算符都有一个运算对象是string
string s6 = s1 + ", " + "world"; 
string s7 = "hello" +", "+ s2;//错误:不能把宇面值直接相加

  s6的初始化形式之前没有出现过,但其实它的工作机理和连续输入连续输出(参见C++Primer1.2节, 第6页)是一样的, 可以用如下的形式分组:

string s6 = (s1 + ", ") + "world"; 

  其中子表达式s1 + “ ,"的结果是一个string对象, 它同时作为第二个加法运算符的左侧运算对象,因此上述语句和下面的两个语句是等价的:

string tmp = s1 + ", ";//正确:加法运算符有一个运算对象是
string s6 = tmp + "world";//正确:加法运算符有一个运算对象是string

因为某些历史原因,也为了与 C 兼容,所以 C++语言中的字符串字面值并不是标准库类型string的对象。 切记, 字符串字面值与string是不同的类型。

2.9string 对象上的操作

指令 解释
os<< s 将 s 写到输出流os当中,返回os (cout<< s)
is>> s 从 is 中读取字符串赋值给 s,字符串以空白分隔,返回 is 例如(cin>> s)
getline(is, s) 从 is 中读取一行赋给 s,返回 is 例如getline(cin, s)
s.empty() s 为空返回 true,否则返回 false
s.size() 返回 s 中字符的个数
s[n] 返回 s 中第 n 个字符的引用,位置 n 从 0 计起
s1+s2 返回 s1 和 s2 连接后的结果
s1=s2 用 s2 的副本代替 s1 中原来的字符
s1==s2 如果 s1 和 s2 中所含的字符完全一样,则他们相等;
s1!=s2 (接上)string 对象的相等性判断对字母大小写敏感
<, <=, >, >= 利用字符在字典中的顺序进行比较,大小写敏感

ps :cin 输入遇到空格停止,有时希望在最终得到的字符串中保留空格,这时应该用 getline 函数代替。getline 从输入流中读取内容,知道遇到换行符为止(注意换行符也被读进来了),然后把所读内容存入 string 对象中(注意不存换行符)。
ps2:对于 size 函数来说,返回的是一个 string::size_type 类型的值。这是一个无符号类型的值,而且能足够存放下任何 string 对象的大小。因此在c++11新标准中,最好通过auto来推断类型变量,比如:

auto len = line.size();  // len的类型是 string::size_type

  由于size函数返回的是一个无符号整形数,因此切记,如果在表达式中混用了带符号数和无符号数可能产生意想不到的效果。例如,假设 n 是一个具有负值的 int,则表达式 s.size()<n 的判断结果几乎肯定是 true。这是因为负值 n 会自动地转换成一个比较大的无符号值。

ps3:字面值和 string 对象相加,当把 string 对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加号(+)的两侧的运算对象至少有一个是 string。因为某些历史原因,也为了与C兼容,所以C++语言中的字符串字面值并不是标准库类型 string 对象。切记,字符串字面值与 string 是不同的类型。

2.10处理 string 对象中的字符

指令 解释
isalnum() 字母或数字为真
isalpha() 字母为真
iscntrl() 控制字符为真
isdigit() 数字为真
isgraph() 不是空格但可以打印为真
islower() 小写字母为真
isprint() 可打印字符为真(即空格或具有可视形式 )
ispunct() 标点符号为真(即c不是控制字符、数字、字母、可打印空白中的一种)
isspace() 空白为真(即空格、横向制表符、纵向制表符、回车符、换行符、进纸符中的一种)
issupper() 大写字母为真
isxdigit() 十六进制数字为真
tolower() 如果是大写字母,输出对应的小写字母;否则原样输出
toupper() 如果是小写字母,输出对应的大写字母;否则原样输出

ps:当处理每个字符的时候,可以使用基于范围的for 语句,其语法形式是:

for(declaration: expression)
	statement;

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

例子:

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

2.11改变 string 的其他方法

指令 解释
s.insert(pos, args) 在pos 之前插入args指定的字符。pos可以是一个下标或一个迭代器。接受下标的版本返回一个指向s 的引用,接受迭代器的版本返回指向第一个插入字符的迭代器
s.erase(pos, len) 删除从位置 pos 开始的 len 个字符。如果 len 被省略,则删除从 pos 开始直至末尾的所有字符。返回一个指向 s 的引用
s.assign(args) 将 s 中的字符替换为 args 制定的字符。返回一个指向 s 的引用
s.append(args) 将 args 追加到 s 。返回一个指向 s 的引用
s.replace(range, args) 删除 s 中范围 range 内的字符,替换为 args 指定的字符。range是一个下标和一个长度,或者是一对指向 s 的迭代器。返回一个指向 s 的引用。

2.12string 搜索操作

指令 解释
s.find(args) 查找 s 中 args 第一次出现的位置
s.rfind(args) 查找 s 中 args 最后一次出现的位置
s.find_first_of(args) 在 s 中查找 args 中任何一个字符第一次出现的位置
s.find_last_of(args) 在 s 中查找 args 中任何一个字符最后一次出现的位置
s.find_first_not_of(args) 在 s 中查找第一个不在 args 中的字符
s.find_last_not_of(args) 在 s 中查找最后一个不在 args 中的字符
上表中 ( ) 内的参数 解释
c, pos 从 s 中位置 pos 开始查找字符 c。pos 默认 0
s2, pos 从 s 中位置 pos 开始查找字符串 s2。pos 默认 0
cp, pos 从 s 中位置 pos 开始查找指针 cp 指向的以空字符结尾的 C 风格字符串。pos 默认 0
cp, pos ,n 从 s 中位置 pos 开始查找指针 cp 指向的数组的前 n 个字符。pos 和 n 无默认值

ps:每个搜索操作都返回一个 string::size_type 值,表示匹配发生位置的下标。如果搜索失败,则返回一个名为 string::npos 的 static 成员。由于 npos 是一个 unsigned 类型,此初始值意味着 npos 等于任何 string 最大的可能大小。

2.13数值转换

指令 解释
to_string(val) 一组重载函数,返回数值 val 的 string 表示。val 可以是任何算数类型。
stoi(s, p, b) 返回 s 的起始子串(表示整数内容)的数值,返回类型为 int。
stol(s, p, b) 返回类型为 long
stoul(s, p, b) 返回类型为 unsigned long
stoll(s, p, b) 返回类型为 long long
stoull(s, p, b) 返回类型为 unsigned long long
stof(s, p) 返回 s 的起始子串(表示浮点数内容)的数值,返回值类型为 float
stod(s, p) 返回类型为 double
stold(s, p) 返回类型为 long double

ps:p: 是 size_t 指针,用来保存 s 中第一个非数值字符的下标,p 默认为 0 ,即,函数不保存下标。

b: 是转换所用的基数,默认值为10。

2.14迭代器

成员 返回值
begin 返回指向字符串第一个元素的指针
end 返回指向字符串最后元素下一个位置的指针
rbegin 返回字符串最后一个元素的指针
rend 返回字符串第一个元素前一个位置的指针
cbegin 同begin,只读
cend 同end,只读
crbegin 同rbegin,只读
crend 同rend,只读

ps: 反向迭代器执行++操作,也是在反着遍历,比如rbegin指向字符串最后一个字符,rbegin++,此时就指向倒数第二个字符。

版权声明:本文为CSDN博主「wanttifa」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wanttifa/article/details/81333458