知识点:
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 的数位的位编号符合斐波那契数列的规律。