3.2 标准库类型string

标准库类型string是可变长的字符序列,如果使用该类型,必须包括string,同时,string是std空间中的名字,因此,使用前需要:

#include <string>
using std::string

一、string的定义和初始化

string的初始化方式如下:

string s1;     //默认初始化,s1为空串
 
string s2 = s1;  //使用来为s2初始化,是赋值初始化
string s2(s1);  //使用来为s2初始化,是直接初始化

string s3 = "value";  //使用字面值"value"来为s2初始化,是赋值初始化
string s3("value");  //使用字面值"value"来为s2初始化,是直接初始化

string s4(n,'c');   //s4初始化为n个c组成的字符串
  • 使用等号的是拷贝初始化,不使用等号的是直接初始化
  • 在使用字符串初始化的时候string会丢弃字符串最后面的换行符

二、string对象的操作

string的读写操作

使用cin和cout进行string读写

string s;
cin >> s;    //读取输入到字符串
cout << s << endl;  //写出字符串到输出
  • 读取字符串会忽略开头的空白(包括空格,换行符,制表符),遇见下一个空白停止。如读取" abc “,最后只读取"abc”
  • 可以多个输入一起读取,输入时中间留空白就可以 cin >> s1 >> s2;
  • 当使用cin >> s 作为判断条件时候,正常读取为真;非法输入或者读取到文件结尾符号为假,使用该条件可以逐个单词读取整个文件
  • 但是直接使用字符串字面值给string赋值的时候可以包含空格和制表符,不能包括换行符,如string a = “HELLO WORD”,则a是会包括中间的空格的

使用getline进行string读取

string s1;
getline(is,s);   //从文件is中读取一整行给s
getline(cin,s);  //从标准输入中读取一整行给s
  • getline读取时候遇见空格和制表符不跳过,只有遇见换行的时候停止读取
  • getline会读取换行,但在给字符串赋值的之后会丢弃换行
  • 使用getline()作为判定条件,当读取到非法数据或者文件末尾的时候为假,使用该条件可以逐行读取整个文件

string的empty和size

string s;
s.empty(); s为空返回true,s为非空返回false
s.size(); 返回s中字符个数

-s.size()函数返回的是string::size_type类型的值,他是一个无符号的值,因此他和int类型的值在一起就相当于无符号和有符号一起混用,这样会导致int转换成unsigned,当int为负数的时候就会出问题。因此我们在写程序的时候必须保证和.size()返回值在一起的值是无符号的。

  • 因此我们在要与string的size()进行交互的时候,应这样安全的定义数字变量
string s = "dfgasdfsa";
decltype(s.size()) n = 0; 
//这样也保持了n与.size()类型一致,不会出现类型转换
if (n < s.size())   

比较string对象

  • 当两个string长度一致,且对应位置的字符均一致的时候,string1==string2
  • 当string1和string2对应位置字符不一致的时候,两个字符串的大小取决于第一个不一致位置对应的字符大小
  • 大写字母小于小写字母,a<b,A<B
  • 当string1和string2对应位置字符均一致,但是长度不同的时候(也就是一个string是另外一个的子集),长的string大

相加操作

两个string对象相加

s3 = s1 + s2;  //相加等效与拼接,s3是s1在前s2在后拼接而成
s1 += s2; //相当于s1 = s1 + s2;

string对象和字符串字面值相加

  • 为了兼容C,字符串字面值并不是string类型,在两者相加过程中实际发生了字符串字面值向string对象的类型转换。
  • string对象可以加字符串字面值,但两个字符串字面值不能直接相加
string s1;
string s2 = s1 + "hell";     //合法
string s3 = "helll" + "asasdf"   //非法
  • 同时,在连续加的时候,加法是从左到右结合的,因此在连续加的时候我们必须保证每一个加号两边至少有一个string对象
string s1;
string s2 = s1 + "sdafasd" + "sdfas"; 
//合法,第一个s1保证了加号左边一直是string对象
stsring s3 = "sdfad" + "sdf" + s1;
//非法,第一个+两边均为字符串字面值

三、string对象中的字符

通过继承C语言中的ctype标准库,可以对字符有一系列的处理,引用该库的方式如下:

#include <cctype>
  • C语言中,标准库名字为name.h,当C++继承后,则改为cname,但两种标准库名字的引用在C++中均合法
  • 在C++中,尽量使用cname,因为cname中的名字都在std空间下,而name.h则不再std空间下

cctype中常用函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ut8Bkcnp-1621249932744)(FF42ABB490B4497EACCA1A5976D35B6E)]

  • 这里需要注意的是,表中说的为真,其返回值其实不是true,而是一个非零数,因此isalnum()和true是永远不相等的
  • 保险起见,使用该类真假函数的时候,加上一个bool()进行以下类型转换,使其从数字变成ture或者false
  • 同时注意toupper©和tolower©只是返回c的对应大写或者小写字母,本身c不改变

使用下标访问字符串中的字符

使用如下标运算符[]可以访问字符串s中指定位置的字符

    string s = "sdfadfas";
    decltype(s.size()) n = 0;  
    for (; n<s.size() && !isspace(s[n]); n++)
        s[n] = toupper(s[n]);
  • 当n和s.size()交互的时候,使用decltype将n定义成和s.size()相同的类型,防止出错
  • 在使用[]访问字符时,必须先用n<s.size()保证没有超出范围,因为超出范围的下标会出发不可知结果,但不会报错
  • 对于&&,只有左面条件为真才会判断右边条件,因此将n<s.size()写在左面保证了先判定下标没越界再使用下标进行!isspace(s[n])判定
  • 禁止使用下标为string添加新的字符串,这在操作时会发生下标越界,可以使用+拼接字符串的形式向已有字符串中添加新的内容

使用for(range for)访问字符串中的字符

C++11提供了类似于python中迭代器的使用方法,称作范围for循环,格式如下

for(auto declaration : expression){
    ...
}
  • 其中expression是可迭代对象,declaration每次返回expression中的一个值
  • 一般用auto推断declaration的类型,根据网上说这样是为了减小代码量
  • 范围for循环不应该改变遍历对象的长度
    该语句在访问string中字符的具体应用:
string s = "dsaf sdafsd";
for (auto a : s){
    a = toupper(a);          //实际上没有改变s
}

for (auto &b : s){
    b = toupper(b);          //s变成了大写
}
  • 这里需要注意auto a :s实际上相当于a = s[n],所以改变a没有 改变s
  • 而auto &a :s 相当于&a = s[n],a是s[n]的引用,所以当s不是常量字符串的时候改变a可以改变s
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值