一、命名空间的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++内置数据类型的数组和指针而言,程序员应优先使用标准库类类型。