标准库类型string表示可变长的字符序列,使用string类型必须首先包含string头文件。作为标准库中的一部分,string定义在命名空间std中。

C++标准一方面对库的类型所提供的操作做了详细的规定,另一方面也对库的实现者做出一些性能上的需求。因此,标准库类型对于一般应用场合来说有足够的效率。

定义和初始化string对象:下面是常见的一些方式:

string s1;

string s2=s1;//s2是s1的副本

string s3=“hiya”;s3是字符串字面值的副本

string s4(10,‘c’);s4的内容是:10个c

string s1 默认初始化
string s2(s1) s2是s1的副本
string s3(“value”) s3是value的副本
string s4(n,'c') 连续n个c字符

直接初始化和拷贝初始化:

C++有几种不同的初始化方式,通过string我们可以清楚地看到在这些初始化方式之间到底有什么区别和联系。

如果使用等号(=)初始化一个变量,实际上执行的就是拷贝初始化,与之相反如果不使用等号(=)就是直接初始化。

string对象上的操作:

一个类除了要规定初始化其对象的方式外,还要定义对象上所能执行的操作。其中,类即能定义通过函数名调用的操作,就像sales_item类的isbn函数那样,也能定义<<,++等各种运算符在该类对象上的新含义。

string的操作:

 

os<<s 将s写到os当中,返回os
is>>s 从is中读取字符串赋给s,返回is
s.empty() s为空返回true
s.size() 返回s中字符的个数
s[n] 返回s中第n个字符的引用,位置n从0记起。
s1+s2
           
返回s1和s2连接后的结果

读写string对象:

可以使用输入输出io操作符读写string对象;

读取未知数量的string对象:

1
2
3
4
while(cin>>word)
{
    cout<<word<<endl;
}

每次读入一整行,直至文件末尾。由于line中不包含换行符所以我们手动的添加上换行符。endl结束当前行并刷新显示缓冲区。

触发的getline函数返回的那个换行符实际上被丢弃了,得到的身体日那个、对象中并不包含该换行符。

string的empty和size操作:

 

1
2
3
4
5
6
7
while(getline(cin,line))
{
    if(!line.empty())
        {
           cout<<line<<endl;
        }
}

if语句的条件部分使用了逻辑非运算符!,它返回与其运算对象相反的结果。此例中如果str不为空则返回真。

1
2
3
4
5
6
7
8
string line;
while(getline(cin.line))
{
    if(line.size()>80)
        {
            cout<<line<<endl;
        }
}

每次读取一整行,输出其中超过80个字符的行。

string::size_type类型:

尽管我们不知道string::size_type类型的细节,但有一点是肯定的,它是一个无符号类型的值而且能够存放下任何string类型对象的大小。所有用于存放string类的size函数返回值的变量,都应该是string::size_type类型的。

在C++11中,允许编译器通过auto或者decltype来推断变量类型。

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

由于size函数返回的是一个无符号整型数,因此在表达式中混用了有符号,无符号将可能产生意料之外的结果哦。

如果一个表达式中已经有了size()函数,就不要在使用int

了,这样可以避免混用int和unsigned可能带来的问题。

比较string对象:

(==)和(!=)分别检验两个string对象相等或不相等,string对象相等意味着他们的长度相同而且字符也全部相同。

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

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

为string对象赋值:

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

两个string值相加:

把左右两侧的string对象串接起来

处理string对象中的字符:

在cctype头文件中定义了一组便准库来处理这部分工作。

 

isalnum Check if character(字母) is alphanumeric(字母或者数字) (function)

 

isalpha Check if character is alphabetic(字母) (function)

 

iscntrl Check if character is a control character(控制字符) (function)

 

isdigit Check if character is decimal (数字)digit (function)

 

isgraph Check if character has graphical (不是空格但可打印时为真)representation (function)

 

islower Check if character is lowercase(小写字母) letter (function)

 

isprint Check if character is printable(可打印的) (function)

 

ispunct Check if character is a punctuation (标点符号)character (function)

 

isspace Check if character is a white-space(空白) (function)

 

isupper Check if character is uppercase(大写) letter (function)

 

isxdigit Check if character is hexadecimal(16进制数字) digit (function)

 

And secondly, two functions to convert between letter cases:

tolower Convert uppercase letter to lowercase (function)(大写换成小写)

 

 

toupper Convert uppercase letter to uppercase (function)(小写换成大写)

翻译,如下:

 

 

C++标准中除了定义C++语言特有的功能之外,也兼容了C语言的标准库。C语言的头文件形如:name.h,C++则将这些文件命名为Cname。也就是去掉了.h后缀,而在文件名name之前添加了首字母c,这里的c表示这是一个属于c语言标准库的头文件。

 一般来说,C++程序因该使用名为cname的头文件而不使用name.h的形式,标准库中的名字总能在命名空间std中找到。如果使用.h形式的头文件,程序员就不得不时刻牢记哪些是从C语言那里继承过来的,哪些优势C++语言所独有的。

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

 

1
2
3
4
5
string str("some string");
for(auto c:str)
{
    std::cout<<c<<std::endl;
}

for循环把变量c和str联系起来,其中我们定义循环变量的方式与定义任意一个普通变量是一样的。此例中,使用auto关键字让编译器来决定变量c的类型。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<iostream>
#include<cctype>
#include<cstring>
using namespace std;
int main()
{
    string name="wang shuai";
    for(auto &c:name)
    {
        c=toupper(c);
    }
    cout<<name<<endl;
 }

只处理一部分字符?

如果要处理string对象中的每一个字符,使用范围for语句是个好主意。然而我们有时只是需要访问其中一个字符,或者访问多个字符遇到某个条件就要停下来。例如:同样是将字符改写为大写形式,不过新的要求不再是对整个字符串都这样做,而仅仅是把string对象中的第一个字母或者第一个单词大写化。

想访问string对象中的单个字符有两个方式:(1)使用下标(2)使用迭代器

下标运算符【】接受的输入类型是string ::size_type类型的值,返回值是该字符在该位置上的引用。

使用下标进行迭代。