使用恰当的using 声明重做 1.4.1节和2.6.2节的练习。
编写一段程序从标准输入中一次读入一行,然后修改该程序使其一次读入一个词。
请说明string类的输入运算符和getline函数分别是如何处理空白字符的。
- 类似 is >> s 的读取,string对象会忽略开头的空白并从第一个真正的字符开始,直到遇见下一空白为止。
- 类似 getline(is, s) 的读取,string对象会从输入流中读取字符,直到遇见换行符为止。
编写一段程序读取两个字符串,比较其是否相等并输出结果。如果不相等,输出比较大的那个字符串。改写上述程序,比较输入的两个字符串是否等长,如果不等长,输出长度较大的那个字符串。
编写一段程序从标准输入中读入多个字符串并将他们连接起来,输出连接成的大字符串。然后修改上述程序,用空格把输入的多个字符串分割开来。
编写一段程序,使用范围for语句将字符串内所有字符用X代替。
就上一题完成的程序而言,如果将循环控制的变量设置为char将发生什么?先估计一下结果,然后实际编程进行验证。
如果设置为char,那么原来的字符串不会发生改变。
分别用while循环和传统for循环重写第一题的程序,你觉得哪种形式更好呢?为什么?
范围for语句更好,不直接操作索引,更简洁。
下面的程序有何作用?它合法吗?如果不合法?为什么?
string s;
cout << s[0] << endl;
不合法。使用下标访问空字符串是非法的行为。
编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分。
下面的范围for语句合法吗?如果合法,c的类型是什么?
const string s = "Keep out!";
for(auto &c : s){ /* ... */ }
要根据for循环中的代码来看是否合法,c是string 对象中字符的引用,s是常量。因此如果for循环中的代码重新给c赋值就会非法,如果不改变c的值,那么合法。
下列vector对象的定义有不正确的吗?如果有,请指出来。对于正确的,描述其执行结果;对于不正确的,说明其错误的原因。
vector<vector<int>> ivec; // 在C++11当中合法
vector<string> svec = ivec; // 不合法,类型不一样
vector<string> svec(10, "null"); // 合法
下列的vector对象各包含多少个元素?这些元素的值分别是多少?
vector<int> v1; // size:0, no values.
vector<int> v2(10); // size:10, value:0
vector<int> v3(10, 42); // size:10, value:42
vector<int> v4{ 10 }; // size:1, value:10
vector<int> v5{ 10, 42 }; // size:2, value:10, 42
vector<string> v6{ 10 }; // size:10, value:""
vector<string> v7{ 10, "hi" }; // size:10, value:"hi"
编写一段程序,用cin读入一组整数并把它们存入一个vector对象。
改写上题程序,不过这次读入的是字符串。
编写一段程序,把练习3.13中vector对象的容量和具体内容输出出来
从cin读入一组词并把它们存入一个vector对象,然后设法把所有词都改为大写形式。输出改变后的结果,每个词占一行。
下面的程序合法吗?如果不合法,你准备如何修改?
vector<int> ivec;
ivec[0] = 42;
不合法。应改为:
ivec.push_back(42);
如果想定义一个含有10个元素的vector对象,所有元素的值都是42,请例举三种不同的实现方法,哪种方式更好呢?
如下三种:
vector<int> ivec1(10, 42);
vector<int> ivec2{ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
vector<int> ivec3;
for (int i = 0; i < 10; ++i)
ivec3.push_back(42);
第一种方式最好。
读入一组整数并把他们存入一个vector对象,将每对相邻整数的和输出出来。改写你的程序,这次要求先输出第一个和最后一个元素的和,接着输入第二个和倒数第二个元素的和,以此类推。
请使用迭代器重做3.3.3节的第一个练习。
修改之前那个输出text第一段的程序,首先把text的第一段全部改成大写形式,然后输出它。
编写一段程序,创建一个含有10个整数的vector对象,然后使用迭代器将所有元素的值都变成原来的两倍。输出vector对象的内容,检验程序是否正确。
请使用迭代器重做3.3.3节的最后一个练习。
3.3.3节划分分数段的程序是使用下标运算符实现的,请利用迭代器改写该程序实现完全相同的功能。
在100页的二分搜索程序中,为什么用的是 mid = beg + (end - beg) / 2, 而非 mid = (beg + end) / 2 ; ?
因为迭代器支持的运算只有 -
,而没有 +
。end - beg
意思是相距若干个元素,将之除以2然后与beg相加,表示将beg移动到一半的位置。
假设txt_size 是一个无参函数,它的返回值是int。请回答下列哪个定义是非法的,为什么?
unsigned buf_size = 1024;
(a) int ia[buf_size];
(b) int ia[4 * 7 - 14];
(c) int ia[txt_size()];
(d) char st[11] = "fundamental";
- (a) 非法。纬度必须是一个常量表达式。
- (b) 合法。
- (c) 非法。txt_size() 的值必须要到运行时才能得到。
- (d) 非法。数组的大小应该是12。
下列数组中元素的值是什么?
string sa[10];
int ia[10];
int main() {
string sa2[10];
int ia2[10];
}
数组的元素会被默认初始化。sa 的元素值全部为空字符串,ia 的元素值全部为0。sa2 的元素值全部为空字符串,ia2 的元素值全部未定义。
相比于vector 来说,数组有哪些缺点,请例举一些。
- 数组的大小是确定的。
- 不能随意增加元素
- 不允许拷贝和赋值
指出下面代码中的索引错误。
constexpr size_t array_size = 10;
int ia[array_size];
for (size_t ix = 1; ix <= array_size; ++ix)
ia[ix] = ix;
当 ix 增长到 10 的时候,ia[ix] 的下标越界。
编写一段程序,定义一个含有10个int的数组,令每个元素的值就是其下标值。
将上一题刚刚创建的数组拷贝给另一数组。利用vector重写程序,实现类似的功能。
对于104页的程序来说,如果不初始化scores将会发生什么?
数组中所有元素的值将会未定义。
假定p1 和 p2 都指向同一个数组中的元素,则下面程序的功能是什么?什么情况下该程序是非法的?
p1 += p2 - p1;
将 p1 移动到 p2 的位置。任何情况下都合法。
编写一段程序,利用指针将数组中的元素置为0。
编写一段程序,比较两个数组是否相等。再写一段程序,比较两个vector对象是否相等。
下面的程序是何含义,程序的输出结果是什么?
const char ca[] = { 'h', 'e', 'l', 'l', 'o' };
const char *cp = ca;
while (*cp) {
cout << *cp << endl;
++cp;
}
会将ca 字符数组中的元素打印出来。但是因为没有空字符的存在,程序不会退出循环。
在本节中我们提到,将两个指针相加不但是非法的,而且也没有什么意义。请问为什么两个指针相加没有意义?
将两个指针相减可以表示两个指针(在同一数组中)相距的距离,将指针加上一个整数也可以表示移动这个指针到某一位置。但是两个指针相加并没有逻辑上的意义,因此两个指针不能相加。
编写一段程序,比较两个string对象。再编写一段程序,比较两个C风格字符串的内容。
编写一段程序,定义两个字符数组并用字符串字面值初始化它们;接着再定义一个字符数组存放前面两个数组连接后的结果。使用strcpy和strcat把前两个数组的内容拷贝到第三个数组当中。
编写一段程序,用整型数组初始化一个vector对象。
编写一段程序,将含有整数元素的vector对象拷贝给一个整型数组。
编写3个不同版本的程序,令其均能输出ia的元素。版本1使用范围for语句管理迭代过程;版本2和版本3都使用普通for语句,其中版本2要求使用下标运算符,版本3要求使用指针。此外,在所有3个版本的程序中都要直接写出数据类型,而不能使用类型别名、auto关键字和decltype关键字。
改写上一个练习中的程序,使用类型别名来代替循环控制变量的类型。
再一次改写程序,这次使用auto关键字。