第三章 标准库类型

来源:互联网 发布:淘宝bb8玩具多少钱 编辑:程序博客网 时间:2024/06/03 08:40

知识点:

1、string类

几种初始化string类的方法:

  • string s1;//默认构造函数,s1为空串
  • string s2(s1);//将s2初始化为s1的一个副本
  • string s3("value");//将s3初始化为一个字符串字面值副本
  • string s4(n, 'c');//将s4初始化为字符c的n个副本

string类型的输入操作符:

  • 读取并忽略开头所有的输入操作符;
  • 读取字符直到再次遇到空白字符,读取终止;

2、读入未知数目的string对象:

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

3、用getline读取整行文本:

int main(void){    string line;    while(getline(cin, line))    {        cout << line << endl;    }    return 0;}

4、任何存储string的size操作结果的变量必须为string::size_type 类型。特别重要的是,不要把size的返回值赋给一个int变量。

5、bitset对象:

  • bitset类型对象的区别仅在其长度而不在其类型。在定义bitset时,要明确bitset含有多少位,须在尖括号内给出它的长度值。

bitset<32> bitvec;

给出的长度必须是常量表达式,而且是整型。

  • bitset<n> b;//b有n位,每位都是0

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

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

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

  • 用unsigned值初始化bitset对象

bitset<16> bitvec1(0xffff);

bitset<32> bitvec2(0xffff);

bitset<128> bitvec3(0xffff);

以上三个例子中,0到15位都置为1。由于bitvec1的位数少于unsigned long的位数,因此bitvec1的初始值的高阶位被丢掉。bitvec2和unsigned long长度相等,因此所有位正好了初始值。bitvec3长度大于32,31位以上的高阶位都被值为0。

  • 用string对象初始化bitset对象:

string str("1100");

bitset<32> bitvec4(str);

string str("1111111000000011001101");

bitset<32> bitvec5(str, 5, 4);

bitset<32> bitvec6(str, str.size()-4);

  • string对象和bitset对象之间是反向转化的。


部分习题:

  • 习题3.2

什么是默认构造函数?

【解答】

默认构造函数(default constructor)就是在没有显式提供初始化式时调用的构造函数。它由不带参数的构造函数,或者为所有形参提供默认实参的构造函数定义。如果定义某个类的变量时没有提供初始化式,就会使用默认构造函数。如果用户定义的类中没有显式定义任何构造函数,编译器就会自动为该类生成默认构造函数,称为合成的默认构造函数(synthesized default constructor)

  • 习题3.6

解释string 类型的输入操作符和getline 函数分别如何处理空白字符。

【解答】

string 类型的输入操作符对空白字符的处理:读取并忽略有效字符(非空白字符)之前所有的空白字符,然后读取字符直至再次遇到空白字符,读取终止(该空白字符仍留在输入流中)。

getline 函数对空白字符的处理:不忽略行开头的空白字符,读取字符直至遇到换行符,读取终止并丢弃换行符(换行符从输入流中去掉但并不存储在string对象中)。

  • 习题3.10

编一个程序,从string 对象中去掉标点符号。要求输入到程序的字符串必须含有标点符号,输出结果则是去掉标点符号后的string 对象。

#include <iostream>#include <string>#include <cctype>using namespace std;int main(){    string line;   //要处理的字符串    string result; //处理后的字符串        cout << "请输入您要处理的字符串:" << endl;    getline(cin, line);    for(string::size_type i=0; i<line.size(); ++i)    {char ch = line[i];if(!ispunct(ch))//ch是标点符号{            result += ch;}    }    if(result.size() == line.size())    {cout << "该字符串中没有标点!" << endl;    }    else    {cout << "去掉标点后的字符串为:" << endl             << result << endl;    }        cin.get();    return 0;}
  • 习题3.13

读一组整数到vector 对象,计算并输出每对相邻元素的和。如果读入元素个数为奇数,则提示用户最后一个元素没有求和,并输出其值。然后修改程序:头尾元素两两配对(第一个和最后一个,第二个和倒数第二个,以此类推),计算每对元素的和,并输出。

【解答】

#include <iostream>#include <vector>using namespace std;typedef vector<int> Vect;typedef vector<int>::iterator Iter;int main(void){Vect ivec;int num;while(cin >> num){ivec.push_back(num);}if(ivec.size() == 0){cout << "没有元素可以处理!" << endl;}int i;Iter iter;for(iter = ivec.begin(), i = 1; iter != ivec.end()-1 && iter != ivec.end(); iter += 2, i += 2){cout << "第" << i << "、"<< (i+1) << "个元素的和为:" << (*iter + *(iter+1)) << endl;}if(ivec.size()%2 == 0){cout << "元素个数为偶数!" << endl;}else{cout << "元素个数为奇数,最后一个元素为:" << ivec.back() << endl;}system("pause");return 0;}
  • 习题3.16

列出三种定义vector 对象的方法,给定10 个元素,每个元素值为42。指出是否还有更好的实现方法,并说明为什么。

【解答】

方法一:

vector<int> ivec(10, 42);
方法二:
vector<int> ivec(10);for (ix = 0; ix < 10; ++ix)ivec[ix] = 42;
方法三:
vector<int> ivec(10);for (vector<int>::iterator iter = ivec.begin();iter != ivec.end(); ++iter)*iter = 42;
方法四:
vector<int> ivec;for (cnt = 1; cnt <= 10; ++cnt)    ivec.push_back(42);

方法五:

vector<int> ivec;vector<int>::iterator iter = ivec.end();for (int i = 0; i != 10; ++i){    ivec.insert(iter, 42);    iter = ivec.end();}

各种方法都可达到目的,也许最后两种方法更好一些。它们使用标准库中定义的容器操作在容器中增添元素,无需在定义vector 对象时指定容器的大小,比较灵活而且不容易出错。

  • 习题3.21

何时使用const 迭代器?又在何时使用const_iterator?解释两者的区别。

【解答】

const 迭代器是迭代器常量,该迭代器本身的值不能修改,即该迭代器在定义时需要初始化,而且初始化之后,不能再指向其他元素。若需要指向固定元素的迭代器,则可以使用const 迭代器。const_iterator 是一种迭代器类型,对这种类型的迭代器解引用会得到一个指向const 对象的引用,即通过这种迭代器访问到的对象是常量。该对象不能修改,因此,const_iterator 类型只能用于读取容器内的元素,不能修改元素的值。若只需遍历容器中的元素而无需修改它们,则可以使用const_iterator。

  • 习题3.22

如果采用下面的方法来计算mid 会产生什么结果?

vector<int>::iterator mid = (vi.begin() + vi.end())/2;

【解答】

将两个迭代器相加的操作是未定义的,因此用这种方法计算mid 会出现编译错误。

  • 习题3.23

解释下面每个bitset 对象包含的位模式:

(a) bitset<64> bitvec(32);

(b) bitset<32> bv(1010101);

(c) string bstr; cin >> bstr; bitset<8> bv(bstr);

【解答】

(a) bitvec 有64 个二进制位,(位编号从0 开始)第5 位置为1,其余位置均为0。

(b) bv 有32 个二进制位,(位编号从0 开始)第0、2、4、5、7、8、11、13、14、16、17、18、19 位置为1,其余位置均为0。因为十进制数1010101 对应的二进制数为000000000000011110110100110110101。

(c) bv 有8 个二进制位,(位编号从0 开始)用读入的字符串的从右至左的8个字符对bv 的0~7 位进行初始化。

  • 习题3.24

考虑这样的序列1,2,3,5,8,13,21,并初始化一个将该序列数字所对应的位置设置为1 的bitset<32>对象。然后换个方法,给定一个空的bitset 对象,编写一小段程序把相应的数位设置为1。

【解答】

方法一:

bitset<32>对象的初始化:

bitset<32> bv(0x20212e)

方法二:

bitset<32> bv;int x = 0, y = 1, z;z = x + y;while (z <= 21){    bv.set(z);    x = y;    y = z;    z = x + y;}

注意,设置为1 的数位的位编号符合斐波那契数列的规律。