C++中的标准库类型

一、命名空间的using声明

单个名字声明:using namespace::name;

整个命名空间声明:using namespace std;

1.std::cin:::的含义是右操作数的名字可以在左操作数的作用域中找到。意思是说所需名字cin是在命名空间std中定义的。

2.每个名字都需要一个using声明:一个using声明一次只能作用于一个命名空间成员,如果希望使用std(或其他的命名空间)中的几个名字,则必须为要用到的每个名字都提供一个using声明。

3.使用标准库类型的类定义

在一种情况下,必须总是使用完全限定的标准库名字:在头文件中。

因为头文件的内容会被预处理器复制到程序中,用#include包含文件时,相当于头文件中的文本将成为我们编写的文件的一部分。如果在头文件中放置using声明,就相当于在包含该头文件的每个程序中都放置了同一using声明,无论该程序是否需要using声明。

**通常,头文件中应该只定义确实必要的东西。    using一般不定义在头文件中,而是源文件内。

二、标准库string类型

string类型支持长度可变的字符串。

string和vector往往将迭代器用作配套类型,用于访问string中的字符,或者vector中的元素。

对于标准库类型,在使用其对象之前,必须包含相关头文件,例如:

#include <string>

using std:string;

1.string对象的定义和初始化

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

string s1;                     默认构造函数,s1为空串

string s2(s1);              将s2初始化为s1的一个副本

string s3("value");       将s3初始化为一个字符串字面值副本

string s4(n,'c');            讲s4初始化为字符‘c’的n个副本

注意:因为历史原因以及为了与C语言兼容,字符串字面值与标准库string类型不是同一种类型。这一点很容易引起混乱,需要注意。

2.string对象的读写

eg:cin>>s(string型);  从标准输入读取string,并将读入的串存储在s中,string类型的输入操作符:

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

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

注意:不读入空格

    1.读入未知数目的string对象

string的输入操作符会返回所读的数据流。  可以通过循环从标准输入读取一组string对象。

    2.用getline读取整行文本

这个函数接受两个参数:一个输入流对象和一个string对象。  eg:getline(cin,line)

getline函数从输入流的下一行读取,并保存读取的内容到string中,但不包括换行符

区别:输入操作符忽略开头的换行符,但是getline并不忽略开头的换行符。即使遇到的第一个字符就是换行符,getline也将停止读入并返回,此时string参数将被置为空string。

getline将istream参数作为返回值,和输入操作符一样也把它用作循环的判断条件。

3.string对象的操作

常用的:

s.empty()   如果为空串,true,否则false

s.size()      返回s中字符的个数

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

s1+s2        连接成新字符串,返回新生成的字符串

s1=s2        把s1中的内容替换为s2的副本

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

!=,<,<=,>,>=    保持这些操作符惯有的含义

    1.size和empty操作

了解string对象是否为空有两种方法:s.size()==0是否为真        s.empty()是否为真

    2.string::size_type类型

从逻辑上讲,size()成员函数似乎应该返回整型数值,或者无符号整数,但事实上返回的却是string::size_type类型的值。我们不知道sting::size_type的具体类型,但可以知道它是unsigned类型,表明size_type存储的string长度是int所能存储的两倍。

string类类型和其他库类型都定义了一些配套类型,可以使库类型的使用与机器无关,size_type就是这些配套类型中的一种,它定义为与unsigned型具有相同的含义,而且可以保证足够大能够存储任意string对象的长度。为了使用由string类型定义的size_type类型,程序员必须加上作用域操作符来说明所使用的size_type类型是由string类定义的。

注意:任何存储string的size操作结果的变量必须为string::size_type类型,特别地,不要把size的返回值赋给一个int变量。保存一个string对象size的最安全的方法就是使用标准库类型string::size_type。

    3.从string对象获取字符

通过下标操作符来访问string对象中的单个字符,下标操作符需要取一个size_type类型的值,来标明要访问字符的位置。string对象的下标从0开始

eg:string str("some string");

        for(string::size_type ix=0;ix!=str.size();++ix)

        cout<<str[ix]<<endl;

例如:str[x*y]=someval;    任何可产生整型值的的表达式都可用作下标操作符的索引,但是,索引的实际数据类型却是unsigned类型string::size_type

小心:标准库不要求检查索引值,所用索引的下标越界是没有定义的,这样往往会导致严重的运行错误。(所以,还是用string::size_type类型比较保险,因为是unsigned的。)

    4.string对象中字符的处理

对string对象中的单个字符进行处理,定义了各种字符操作函数(P77),这些函数都在cctype头文件中定义。

建议:采用C标准库头文件的C++版本。

cctype与ctype.h文件的内容是一样的,只是采用了更适合C++程序的形式。特别地,cname头文件中定义的名字都定义在命名空间std内,而.h版本中的名字却不是这样。

三、标准库vector类型

1.称之为“容器”,是因为它可以包含其他对象。一个容器中的所有对象必须是同一类型的。

#include <vector>

using std::vector;

2.声明某种类型的对象,需要将类型放在类模板名称后面的尖括号中来指定类型:

vector<int> ivec;

vector<Sales_item> Sales_vec;

vector不是一种数据类型,而只是一个类模板,可用来定义任意多种数据类型。vector<int>是数据类型。

3.vector对象的定义和初始化

几种构造函数:

vector<T> v1;

vector<T> v2(v1);        注意类型保持一致

vector<T> v3(n,i);

vector<T> v4(n);

关键概念:vector对象动态增长。

vector对象(以及其他标准库容器对象)的重要属性就在于可以在运行时高效地添加元素。

4.vector对象的操作

几种最重要的:

v.empty()

v.size()

v.push_back(t)

v[n]

v1=v2

v1==v2

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

1.vector对象的size

empty和size操作类似于string类型的相关操作。成员函数size返回相应vector类定义的size_type的值。

vector<int>::size_type        必须加上类型

2.向vector添加元素:可以通过push_back()将一个新的元素添加到vector对象的后面。

3.vector的下标操作

for(vector<int>::size_type ix=0;ix!=ivec.size();++ix)

ivec[ix]=0;

下标操作类似于string类型

关键概念:C++程序员习惯于优先选用!=而不是<来编写循环判断条件。

重点:下标操作不添加元素

下标只能用于获取已存在的元素,如果添加元素,用push_back()。

小心:必须是已存在的元素才能用下标操作符进行索引。通过下标操作进行赋值时,不会添加任何元素。

仅能提取确实已存在的元素,试图获取不存在的元素必然产生运行时错误。 例如“缓冲区溢出”。

这个警告适用于任何使用下标操作的时候,如string类型的下标操作,以及内置数组的下标操作等。

四、迭代器

迭代器是一种检查容器内元素并遍历元素的数据类型。

标准库为每一种标准容器(包括vector)定义了一种迭代器类型。迭代器类型提供了比下标操作更通用化的方法:所有的标准库容器都定义了相应的迭代器类型,而只有少数的容器支持下标操作。因为迭代器对所有的容器都适用,现代C++程序更倾向于使用迭代器而不是下标操作访问元素,即使对支持下标操作的vector类型也是这样。

    1.容器的iterator类型

每种容器类型都定义了自己的迭代器类型,如vector:

vector<int>::iterator iter;

定义了一个名为iter的变量,它的数据类型是由vector<int>定义的iterator类型。 每个标准库容器类型都定义了一个名为iterator的成员。

    2.迭代器和迭代器类型

iterator:一般意义上指的是迭代器的概念,而具体而言时指的则是由容器定义的具体的iterator类型,如vector<int>。

    3.begin和end操作

每种容器都定义了一对命名为begin和end的函数,用于返回迭代器

如果容器中有元素的话,由begin返回的迭代器指向第一个元素;由end操作返回的迭代器指向vector的“末端元素的下一个”,并不指向vector中任何实际的元素,相反,只是起一个哨兵的作用,表明我们已经处理完vector中所有元素。通常称为超出末端迭代器(off-the-end iterator),表明它指向了一个不存在的元素。

如果vector为空,begin和end返回的迭代器相同。

    4.vector迭代器的自增和解引用运算

迭代器类型定义了一些操作来获取迭代器所指向的元素,并允许程序员将迭代器从一个元素移动到另一个元素。

访问迭代器所指向的元素:解引用操作符(*操作符):*iter=0;    解引用操作符返回迭代器当前所指向的元素

迭代器使用自增操作符向前移动迭代器指向容器中下一个元素。

注意:由于end操作返回的迭代器不指向任何元素,因此不能对它进行解引用或自增操作。

    5.迭代器的其他操作

可以用==或!=来比较两个迭代器,检验是否指向同一个元素。

    6.const_iterator

每种容器类型还定义了一种名为const_iterator的类型,该类型只能用于读取容器内元素,但不能改变其值。

当对const_iterator类型解引用时,返回的是一个const值。

const_iterator对象可以用于const vector或非const vector,因为不能改写元素值。

注意:不要把const_iterator对象与const的iterator对象混淆起来。声明一个const迭代器时,必须初始化迭代器,一旦被初始化后,就不能改变它的值。

使用const_iterator类型时,可以得到一个迭代器,它自身的值可以改变,但不能用来改变其所指向的元素的值。

区别:

vector<int>::const_iterator:不能改变迭代器所指向的元素值,可以改变迭代器本身的值。

const vector<int>::iterator:不能改变迭代器的值(指向),可以改变其指向的元素值。

    7.迭代器的算术操作

iter+n或iter-n:对迭代器对象加上或减去一个整型值。这样将会产生一个新的迭代器,其位置在iter所指元素之前(加)或之后(减)n个元素的位置。加或减之后的结果必须指向iter所指vector中的某个元素,或者是vector末端的后一个元素。加上或减去的值的类型应该是vector的size_type或difference_type类型。

iter1-iter2:用来计算两个迭代器对象的距离,该距离是名为difference_type的signed类型的值。difference_type类型类似于size_type类型,也是由vector定义的。difference_type是signed类型,因为减法运算可能产生负数,该类型可以保证足够大以存储任何两个迭代器对象间的距离。iter1与iter2两者必须都指向同一vector中的元素,或者指向vector末端之后的下一个元素。

可以用迭代器算术操作来移动迭代器直接指向某个元素,这种直接计算迭代器的方法,与逐个自增效果等价,但是效率要高得多。

小心:任何改变vector长度的操作都会使已存在的迭代器失效。

五、标准库bitset类型

提供了一种抽象方法来操作位的集合。

相关头文件:

#include <bitset>

using std::bitset;

1.bit对象的定义和初始化

类似于vector,bitset类是一种类模板;而与vector不一样的是bitset类型对象的区别仅在其长度而不在其类型。在定义bitset时,要明确bitset含有多少位,须在尖括号内给出长度值:

bitset<32> bitvec;

长度值必须是常量表达式。

2.构造函数

bitsset<n> b;                     b有n为,每位都为0

bitsset<n> b(u);                b是unsigned long型u的一个副本

bitsset<n> b(s);                b是string对象s中含有的位串的副本

bitsset<n> b(s,pos,n);     b是s中从位置pos开始的n个位的副本

    1.当用unsigned long值作为bitset对象的初始值是,该值将转化为二进制的位模式,而bitset对象中的位集作为这种位模式的副本。

如果bitset类型长度大于unsigned long值的二进制维数,则其余的高阶位将置为0;如果小于,则只使用其低阶位,超过的高阶位部分将被丢弃。

    2.用string对象初始化bitset对象时,string对象直接表示为位模式,从string对象读入位集的顺序是从右向左(具体例子见P89)。

3.bitset对象上的操作

具体P90

特别地:

1.b.count()和b.size():前者是b中置为1的二进制个数;后者是b中二进制位的总个数。

count操作的返回类型是标准库中命名为size_t的类型。size_t类型定义在cstddef头文件中,它是一个与机器相关的unsigned类型。size返回的类型也是size_t。

2.获取bitset对象的值

to_ulong操作返回一个unsigned long值,该值与bitset对象的位模式存储值相同。但是,仅当bitset类型的长度小于或等于unsigned long的长度时,才可以使用to_ulong操作。


数组和指针提供了类似于vector和string标准库类型的低级抽象类型,相对于C++内置数据类型的数组和指针而言,程序员应优先使用标准库类类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值