《C++ Primer》读书笔记第三章-1-标准库类型string

笔记会持续更新,有错误的地方欢迎指正,谢谢!

前言:这一章我们主要介绍两种十分常用的标准库类型:string表示可变长字符串,vector表示可变长的容器。还会介绍迭代器,它是string和vector的配套类型,用于访问string中的字符或vector中的元素。

在开始介绍标准库类型之前,先简单学习一下命名空间的using声明:

  1. 我们用到的库函数基本都属于命名空间std,using namespace std;//这样就可以访问std中所有的名字,但是很多用不到,程序开销会变大。

  2. 头文件不应包含using声明
    因为头文件的内容在编译时会被拷贝到所有引用它的文件中去,如果头文件中有某个using声明,那么每个使用了该头文件的文件就都会有这个声明,很有可能产生一些名字冲突。

using声明的总结:每个using声明引入命名空间的一个成员,头文件中的代码一般不应使用using声明。

string定义

string表示可变长的字符序列,使用string必须包含下述代码:

#include <string> //要使用string类型,必须要包含string头文件。
using std::string; //string作为标准库的一部分,它定义在命名空间std中。

定义和初始化string对象

string s1; //s1默认初始化,是一个空字符串
string s2 = s1; 等价于 string s2(s1);//s2是s1的副本
string s3 = "hello"; 等价于 string s3("hello");//字符串字面值赋值
string s4(3, 'c'); //s4 = “ccc”;
对s1有个小问题,s1和”“相等吗?相等!

直接初始化和拷贝初始化

-拷贝初始化:使用等号初始化一个变量,编译器把等号右边的值拷贝到左边新建的对象中;
-直接初始化:不使用等号。
例子:
string s6 = "world"; //拷贝初始化
string s7("heihei");//直接初始化
当初始值只有一个时,两种初始方法都行,但初始值有多个(如下),则最好使用直接初始化。
string s8(3, 'c');//直接初始化

string对象上的操作

读写string

可使用IO操作读写string对象

int main()
{
    string s;
    cin >> s;//读取操作,从标准输入的内容读取到s中。
    cout << s << endl;//输出s
    return 0;
 }

在执行读取操作时,string对象会自动忽略开头的空白(空格,换行,制表)并从第一个真正的字符开始读起,直到遇见下一处空白为止。 例子:如果输入” Bill Chen “,输出一定是”Bill”。 string对象也支持连续输入输出:
例子:

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

这段程序如果输入” Bill Chen “,输出是”BillChen” 。
只有这样的一种输入方式肯定不够,因为它只能读取数量确定的一个一个的单词,太复杂啦!救世主在下方!

读取未知数量的string

代码如下:

int main()
{
    string word;
    while(cin >> word)
    {
        cout << word << endl;
    }
    return 0;
}

使用getline读取一整行

有时候,我们还希望能在最终得到的字符串中保留输入的空白符,这时可用getline函数代替>>运算符。

int main()
{
    string line;
    while(getline(cin, line))//从输入流中读入内容直到读入换行符,保留空白符,但换行符不存入string对象中。
    {
        cout << line << endl;//一次输出一整行后再换行,再循环。
    }
    return 0;
}

strng的size函数和empty函数

empty()返回的是布尔类型;
size()返回string对象中字符的个数。

string::size_type类型

size()返回一个string::size_type类型的数,该类型是无符号类型,当表达式中存在有符号类型和无符号类型时,所有的操作数都转换为无符号类型。例子:假设n是一个负整型数,s.size()<n; 的判断结果一定为true,因为n自动转换为了比较大的无符号数。但int n=s.size();s.size()<80; 都是对的,因为未出现负数。

比较string对象

直接贴代码,读者就知道了啊。

string s0 = "Hello";
string s1 = "Hello";
string s2 = "Hello Bill";
string s3 = "Hi";
string s4 = "hi";
//大小结果:s0=s1<s2<s3<s4

**总结:**1.前面相同的话,长度长的则大;2.两个string对象在对应位置上不同,则比较第一对相异的两个字符;3.依照大小写敏感的字典顺序(大写 排在 小写 前)。

为string对象赋值

string类 允许把一个对象的值赋给另一个对象。
例子:

string str = "Hello";
string str1 = str; 

两个string对象相加

string s1 = "Hello", s2 = " Bill";
s1 += s2; //s1 = s1 + s2,s1的内容变为Hello Bill

字面值和string对象相加

准则:字符字面值和字符串字面值都可转化为string对象,相加时加号两侧的运算对象至少有一个是string型:
原因:由于历史原因,也为了和C兼容,所以C++中的 字符串字面值 和 标准库类型string的对象 并不是同类型!

string s1 = "hello", s2 = "bill";
string s3 = s1 + ", " + s2; //正确
string s4 = "hello" + "bill"; //错误:两个运算对象都不是string
string s5 = s1 + ", " + "bill"; //正确:第一个加号的结果就是string
string s6 = "hello" + ", " + s2; //错误

处理string对象中的字符

题型: 比如检查一个string对象是否包含空白,或者把大写改为小写,或者查看某个特定字符是否出现等。
解答:如何获取字符本身并改变之?用cctype头文件中的标准库函数。
补充:C++标准库不仅自定义了C++特有的功能外,还兼容了C语言的标准库。所以,在C语言中的头文件name.h,C++将它命名为cname。这里的c表示这是一个属于C语言标准库的头文件。

使用 范围for语句 遍历处理每个字符

范围for语句:c是由str中的字符一个个地拷贝过去的,处理c即可。

简单的例子:每行输出str中的单个字符

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

这里用auto来决定c的类型,这里c是char,每次迭代,str的下一个字符被拷贝给c。

复杂点的例子:统计一个string对象中标点符号的个数

string s("Hello World!!!??");
int punct_cnt = 0;
for(auto c : s)
{
    if(ispunct(c))
    {
        ++punct_cnt ;
    }
}

punct_cnt 为5,不用解释啦。另外,[ ]符号中的数是什么类型的呢?s.size()返回值的类型?punct_cnt原本应该是什么类型呢?都是string的size_type,即无符号数。无符号数可默认转为有符号数;有符号数转无符号数看正负。

使用 范围for语句 遍历改变字符

如果我想把一个string对象中的小写字母都改成大写呢?
先看看下面的代码对不对?

string s("hello");
for(auto c : s)
{
    c = toupper(c);//若c是小写则输出大写,否则原样输出。tolower则相反。
}
cout << s << endl;

SORRY!是错的,因为c是由s中的字符拷贝过去的,跟s没啥关系。 其实只需要改一个地方就好:

string s("hello");
for(auto &c : s)
{
    c = toupper(c);
}
cout << s << endl;

以上是我们在处理string中所有字符的情况,只处理一部分字符呢?

只处理一部分字符呢?

当然是选择用 下标运算符[ ] 咯!
例子:我们只想把字符串中第一个字符改为大写,其他不变:

string s("some thing");
if(!s.empty()) //别忘了这个条件,提升代码的鲁棒性!
{
    s[0] = toupper(s[0]);
}

使用下标执行迭代

例子:把s的第一个单词变成大写,其他不变:

string s("some thing");
for(int i=0;i<s.size()&&s[i]!='';++i)
s[i]=toupper(s[i]);

使用下标执行随机访问

例子:编写一个程序把0-15之间的十进制数转换成对应的十六进制数:

const string str= "0123456789ABCDEF";
string result;
int n;
while(cin >> n)//有效输入则进入循环,将标准输入赋给n。
{
    if(n < 16)
    {
        result+= str[n]; //根据n获取到字符数组元素呗!
    }
    cout << result<< endl;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值