练习

1.(*1)将下面的for循环重写为采用while循环的等价形式:

for(i = 0; i < max_length; i++)
    if(input_line[i] == '?') quest_count++;

重写这个片段,用一个指针作为被控制变量,其检测采用 *p == '?'的形式。

2.(*1)为下面各个表达式加上全部括号:

a = b + c * d << 2 & 8
a & 077 != 3
a == b || a == c && c < 5
c = x != 0
0 <= i < 7
f(1, 2) + 3
a = -1 ++ b -- - 5
a = b == c++
a = b = c = 0
a[4][2] *= *b ? c : *d * 2
a - b, c = d

3.(*2)读入一系列由空白分隔的(名字,值)对,其中每个名字是由空白分隔开的一个单词,值是一个整数或者一个浮点值。计算并打印出对应于每个名字的所有值之和与平均值,以及所有名字的和与平均值。提示:6.1.8节。

4.(*1)写出一个表格,其中列出各种可能的0和1组合作为运算对象,进行按位逻辑运算所得到(6.2.4节)的值。

5.(*1.5)找出5种不同的其意义无定义的C++结构(C.2节)。(*1.5)找出5种不同的其意义由实现确定的C++结构(C.2节)。

6.(*1)找出10个不可移植的C++代码的例子。

7.(*2)写出5个表达式,对它们的求值顺序没有定义。执行它们,看看某一个或(最好)多个实现对它们怎么做。

8.(*1.5)如果你在你的系统上除0会发生什么事情?在上溢和下溢时又会怎么样?

9.(*1)给下面各表达式加上全部括号:

*p++
*--p
++a--
(int*)p->m
*p.m
*a[i]

10.(*2)写出下面函数:strlen(),它返回C风格字符串的长度;strcpy(),它将一个C风格字符串复制到另一个;strcmp(),它比较两个C风格的字符串。考虑参数类型和返回值类型应该是什么。而后将你的函数与在<cstring>(<string.h>)里以及在20.1.4节描述的标准库版本做一个比较。

11.(*1)看看你的编译器对下面这些错误有何反应:

void f(int a, int b)
{
    if(a = 3) // ...
    if(a & 077 == 0) // ...
    a := b + 1;
}

设计一些更简单的错误,并看看编译器如何反应。

12.(*2)修改6.6[3]的程序,使之同时计算出中间值。

13.(*2)写一个函数cat(),它取两个C风格字符串为参数,返回一个字符串,该字符串是两个参数串的拼接。利用new为这个结果取得存储。

14.(*2)写一个函数rev(),它取一个C风格字符串p为参数,并反转其中的字符。也就是说,在rev(p)之后p的最后一个字符将变成第一个,如此等等。

15.(*1.5)下面例子做些什么?

// Duff设施,有帮助的注释被有意删去了
void send(int* to, int* from, int count)
{
    int n = (count + 7) / 8;
    switch(count % 8) {
    case 0:  do { *to++ = *from++;
    case 7:       *to++ = *from++;
    case 6:       *to++ = *from++;
    case 5:       *to++ = *from++;
    case 4:       *to++ = *from++;
    case 3:       *to++ = *from++;
    case 2:       *to++ = *from++;
    case 1:       *to++ = *from++;
        } while (--n > 0);
    }  
}

为什么会有人想写这样的东西?

16.(*2)写一个函数atoi(const char*),它以一个包含数字的C风格字符串为参数,返回与之对应的int值。例如,atoi("123")应是123。修改atoi(),使之除了能处理简单的十进制之外,还能处理C++的八进制和十六进制记法形式。修改atoi()以处理C++的字符常量记法。

17.(*2)写一个函数itoa(int i, char b[]),它在b中建立起i的字符串表示并返回b。

18.(*2)键入计算器的例子并使之能够工作。不要“节约时间”去使用已有的正文文件。你将会从发现并改正各种“小而蠢的错误”中学到许多东西。

19.(*2)修改计算器程序,使之能够在报告错误时给出相应的行号。

20.(*3)设法使用户可以在计算器中定义函数。提示:将一个函数定义为运算的一个序列,就像用户键入它们那样。这种序列可以存储为字符串,或者存储为单词的表。当函数被调用时,就读取并执行这些运算。如果你希望用户定义函数能够使用参数,那么你就必须为此去发明一种记法形式。

21.(*1.5)改造桌面计算器,让它使用一种symbol结构,而不是使用静态变量number_value和string_value。

22.(*2.5)写一个程序,使它能剥掉C++程序里的所有注释。即,从cin读入,删除所有的// 和/* */注释,而后将其写到cout。不要费力去把输出的布局弄得比较好看(那可以成为另外一个更困难的练习题),也不要去顾虑错误的程序。请留意位于注释、字符串和字符常量中的//、/*和*/。

23.(*2)去找一些程序,取得一些有关在实际中使用的缩进编排、命名和注释的认识。

🔚