【C++ 精选】C++ Primer(第五版)第二章练习题

练习 2.1

问题:类型 int、long、long long 和 short 的区别是什么?无符号类型和带符号类型的区别是什么?float 和 double的区别是什么?

类型 大小 取值范围
short 2 字节即 16 位 -2^15 ~ 2^15-1
int 2 字节即 16 位 -2^15 ~ 2^15-1
long 4 字节即 32 位 -2^31 ~ 2^31-1
long long 8 字节即 64 位 -2^63 ~ 2^63-1

带符号类型(signed)能够表示正数、负数和 0 ,而无符号类型(unsigned)只能够表示 0 和正数。

双精度浮点型(double)比单精度浮点型(float)的区别:① double 有效数字比 float 多,double 的内存占8个字节有效数字16位,而 float 的内存占4个字节有效数字8位;② 两者处理速度不同,float 的 CPU 速度比处理 double 快,而 double 的精度高导致消耗内存是 float 的两倍;③小数默认是 double 类型,而使用 float 时需要进行强转或者在小数后加上 f

练习 2.2

问题:计算按揭贷款时,对于利率、本金和付款分别应选择何种数据类型?说明你的理由。
:实际应用中的利率、本金和付款既可能为整数,也可能为普通实数,因此可以选择一种浮点类型来表示。可选的浮点类型 float、double 和 long double,float 精度不足,没有必要使用 long double 的精度并且其 CPU 和内存的代价比较大。终上所述,采用 double 类型比较合适。

练习 2.3

问题

unsigned u = 10, u2 = 42;
std::cout << u2 - u << std::endl;  // 32
std::cout << u - u2 << std::endl;  // 4294967264
 
int i = 10, i2 = 42;
std::cout << i2 - i << std::endl;  // 32
std::cout << i - i2 << std::endl;  // -32
std::cout << i - u << std::endl;   // 0
std::cout << u - i << std::endl;   // 0

练习 2.4

问题:编写程序检查你的估计是否正确,如果不正确,请仔细研读本节直到弄明白问题所在。

std::cout << u - u2 << std::endl;  // 4294967264
// 2^32 - (u-u2) = 4294967296 - 32 = 4294967264

练习 2.5

问题:指出下述字面值的数据类型并说明每一组内几种字面值的区别:

(a) 'a', L'a', "a", L"a"
(b) 10, 10u, 10L, 10uL, 012, 0xC
(c) 3.14, 3.14f, 3.14L
(d) 10, 10u, 10., 10e-2

(a): 字符字面值,宽字符字面值,字符串字面值,宽字符串字面值。
(b): 十进制整型,十进制无符号整型,十进制长整型,十进制无符号长整型,八进制整型,十六进制整型。
(c): 双精度浮点型,单精度浮点型,扩展精度浮点型。
(d): 十进制整型,十进制无符号整型,双精度浮点型,双精度浮点型。

练习 2.6

问题:下面两组定义是否有区别,如果有,请叙述之:

int month = 9, day = 7;
int month = 09, day = 07;

:有区别。第一行定义了两个十进制整型数,第二行定义了两个八进制整型数。但注意,就八进制而言,逢八进一,而不应出现第二行中的 09。

练习 2.7

问题:下述字面值表示何种含义?它们各自的数据类型是什么?

(a) "Who goes with F\145rgus?\012"
(b) 3.14e1L
(c) 1024f
(d) 3.14L

(a) Who goes with Fergus?(换行),string 类型
(b) long double
(c) 无效,1024 是整型,而后缀 f 只能用于浮点字面量
(d) long double

练习 2.8

问题:请利用转义序列编写一段程序,要求先输出 2M,然后转到新一行。修改程序使其先输出 2,然后输出制表符,再输出 M,最后转到新一行。

#include <iostream>
int main()
{
   std::cout << 2 << "\115\012";
   std::cout << 2 << "\t\115\012";
   return 0;
}

练习 2.9

问题:解释下列定义的含义,对于非法的定义,请说明错在何处并将其改正。

(a) std::cin >> int input_value;
(b) int i = { 3.14 };
(c) double salary = wage = 9999.99;
(d) int i = 3.14;

# (a) 应先定义好变量再用于接收标准输入。改正:
int input_value = 0;
std::cin >> input_value;

# (b) 用列表初始化内置类型的变量时,如果存在丢失信息的风险,则编译器将报错。改正:
double i = { 3.14 };

# (c)  此处 wage 是未定义的,应于此前先将其定义好。改正:
double wage;
double salary = wage = 9999.99;

# (d) 虽然不报错,但小数部分将会因隐式类型转换而被截断。建议改正
double i = 3.14;

练习 2.10

问题:下列变量的初值分别是什么?

std::string global_str;
int global_int;
int main()
{
    int local_int;
    std::string local_str;
}

:global_str 和 global_int 均为定义在函数体外的变量 (全局变量),故将被默认初始化为空字符串和 0。
local_int 作为函数体内的内置类型 (int) 变量 (局部变量),将不被初始化 (uninitialized),初值未定义。
local_str 作为函数体内的 std::string 类变量 (局部变量),其初值由该类决定,为空字符串。

练习 2.11

问题:指出下面的语句是声明还是定义:

(a) extern int ix = 1024;
(b) int iy;
(c) extern int iz;

(a) 定义,虽然使用了 extern 关键字,但还是对变量 ix 进行初始化了,以至于抵消了 extern 的作用。
(b) 定义,未对变量 iy 初始化而已。
(c) 声明,使用了 extern 关键字且未对变量 iz 初始化。

练习 2.12

问题:请指出下面的名字中哪些是非法的?

(a) int double = 3.14;
(b) int _;
(c) int catch-22;
(d) int 1_or_2 = 1;
(e) double Double = 3.14;

(a) 非法,变量名 double 使用了 C++ 关键字。
(b) 合法,但注意定义在函数体外的标识符不能以下划线开头。
(c) 非法,使用非法符号 (-) 构成标识符。
(d) 非法,标识符必须以字母或下划线开头。
(e) 合法,但注意变量名一般以小写字母开头,用户自定义类名才通常以大写字母开头。

练习 2.13

问题:下面程序中 j 的值是多少?

int i = 42;
int main()
{
    int i = 100;
    int j = i;  // int j = ::i
}

:局部变量 j = 100,因为新建的局部变量 i (100) 覆盖了原先的全局变量 i (42)。除非使用作用域操作符 :: 将局部变量 j 的创建和初始化语句改为 int j = ::i; 有 j = 42。

练习 2.14

问题:下面的程序合法吗?如果合法,它将输出什么?

int i = 100, sum = 0;
for (int i = 0; i != 10; ++i)
    sum += i;
std::cout << i << " " << sum << std::endl;

:该程序合法,因为 for 循环中的临时局部变量 i 将在内层作用域内暂时覆盖外层作用域的变量 i,从而实现正常的循环计数,并在 for 循环结束后被释放。结果将分别输出 100 45,其中 45 是整数 1-9 之和。

练习 2.15

问题:下面的哪个定义是不合法的?为什么?

(a) int ival = 1.01;
(b) int &rval1 = 1.01;
(c) int &rval2 = ival;
(d) int &rval3;

(a) 合法,但浮点数 1.01 的小数部分会被截断 (隐式类型转换 double → int)。
(b) 非法,引用类型的初始值必须是一个对象。
(c) 合法,rval2 作为 int 型对象 ival 的引用,成为变量 ival 的别名。
(d) 非法,不能定义引用的引用,应当有初始化。

练习 2.16

问题:考察下面的所有赋值然后回答:哪些赋值是不合法的?为什么?哪些赋值是合法的?它们执行了哪些操作?

int i = 0, &r1 = i;     
double d = 0, &r2 = d;
 
(a) r2 = 3.14159;
(b) r2 = r1;
(c) i = r2;
(d) r1 = d;

(a) 合法,等价于 d = 3.14159。
(b) 合法,等价于 d = 0.0,增加小数部分 (隐式类型转换 int → double)。
(c) 合法,等价于 i = 0,小数部分被截断 (隐式类型转换 double → int)。
(d) 合法,等价于 i = 0,小数部分被截断 (隐式类型转换 double → int)。

练习 2.17

问题:执行下面的代码段将输出什么结果?

int i, &ri = i;
i = 5; ri = 10;
std::cout << i << " " << ri << std::endl;

:该代码段将输出 10 10

练习 2.18

问题:编写代码分别改变指针的值以及指针所指对象的值。

#include<iostream>
 
int main()
{
    int *ptr = nullptr;
    std::cout << ptr << " " << std::endl;  // 地址值
 
    int x = 6;
    ptr = &x;  // int 指针 ptr 保存 int 变量 x 的内存地址 (ptr 指向 x)
    std::cout << ptr << " " << *ptr << " " << x << std::endl;  // 地址值、解引用值、变量 x
 
    *ptr = 9;  // ptr 解引用, 改变 ptr 所指地址中保存的值 (改变 x 的值)
    std::cout << ptr << " " << *ptr << " " << x << std::endl;  // 地址值、解引用值、变量 x
 
    system("pause");
    return 0;
}

#控制台输出:
#0
#0x61fe34 6 6
#0x61fe34 9 9

练习 2.19

问题:说明 指针和引用的主要区别。
:指针和引用都能提供对其他对象的间接访问,且在定义时均需满足类型匹配原则。两者的区别:

  • 引用本身不是一个对象即引用没有实际地址而是另一个对象的别名,故不能定义引用的引用;而指针本身就是一个对象即指针有实际地址,故可以定义指向指针的指针,也可以定义指针的引用。
  • 引用在新建时必须绑定一个对象实现初始化,且引用一旦被定义就无法再绑定到其他对象;而指针及其保存的地址间则无此限制,指针无须在定义时赋初值,且在其生命周期内,可以通过赋值使之重新指向其他对象。

练习 2.20

问题:请叙述下面这段代码的作用。

int i = 42;
int *p1 = &i;     // 等号右侧, & 为取地址符
*p1 = *p1 * *p1;  // 等号右侧, * 为解引用符

int i = 42;    // 定义 int 型变量 i,并将 i 的值初始化为 42
int *p1 = &i;     // 定义 int 型指针变量 p1,令指针 p1 指向对象 i
*p1 = *p1 * *p1;  // 对指针变量 p1 解引用 从而为变量 i 赋予新值 1764

练习 2.21

问题:请解释下述定义。在这些定义中有非法的吗?如果有,为什么?

int i = 0;
 
(a) double *dp = &i;
(b) int *ip = i;
(c) int *p = &i;

(a) 非法。创建 double 型指针变量 dp,并令其指向 int 型对象 i,导致类型不一致。
(b) 非法。把 int 变量 i 直接赋给指针 ip 是错误的操作,即便 i 的值恰为 0 也不行。
(c) 合法。创建 int 型指针变量 p,并令其指向 int 型对象 i ,即 p 保存变量 i 的内存地址。

练习 2.22

问题:假设 p 是一个 int 型指针,请说明下述代码的含义。

if (p) // ...
if (*p) // ...

:Line 1:判断 p 是否为空指针。
Line 2:判断 p 所指对象的值 (整数) 是否为 0。

练习 2.23

问题:给定指针 p,你能知道它是否指向了一个合法的对象吗?如果能,叙述判断的思路;如果不能,也请说明原因。
:不能,因为首先要确定指针 p 是否合法,才能判断 p 所指向的对象是否合法。

练习 2.24

问题:在下面这段代码中为什么 p 合法而 lp 非法?

int i = 42;
void *p = &i;
long *lp = &i;

:因为指针变量 lp 的类型为 long,与指向对象 i 的类型 int 不一致。注意,在 C++ 中,继承自 C 的 void * 才可以指向任何类型的对象,而其他指针类型必须要与所指对象严格匹配。

练习 2.25

问题:说明下列变量的类型和值。

(a) int* ip, i, &r = i;
(b) int i, *ip = 0;
(c) int* ip, ip2;

(a) ip 是指向 int 对象的指针;i 是 int 型变量;r 是对变量 i 的 int 型引用
(b) i 是 int 型变量;ip 是 int 型的空指针
(c) ip 是指向 int 对象的指针;ip2 是 int 型变量

练习 2.39

问题:编译下面的程序观察其运行结果,注意,如果忘记写类定义体后面的分号会发生什么情况?记录下相关的信息,以后可能会有用。

struct Foo { /* 此处为空  */ } // 注意:没有分号
int main()
{
    return 0;
}

:在 struct Foo ... } 处提示应输入“ ; ” 。

练习 2.40

问题:根据自己的理解写出 Sales_data 类,最好与书中的例子有所区别。

struct Sales_data {
    std::string book_name;       // 书名
    std::string book_index;      // 书编号
    unsigned sales_volume = 0;   // 销售总量
    double unit_price = 0.0;     // 书单价
    double unit_cost = 0.0;      // 单书成本
    double total_revenue = 0.0;  // 总营收
    double net_profit = 0.0;     // 净利润
    // ...
};

练习 2.41

问题:使用你自己的 Sale_data 类重写1.5.1节(第20页)、1.5.2节(第21页)和1.6节(第22页)的练习。眼下先把 Sales_data 类的定义和 main 函数放在一个文件里。

#include<iostream>
#include<string>
 
struct Sale_data
{
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};
 
int main()
{
    Sale_data book;
    double price;
    std::cin >> book.bookNo >> book.units_sold >> price;
    book.revenue = book.units_sold * price;
    std::cout << book.bookNo << " " << book.units_sold << " " << book.revenue << " " << price;
    
    system("pause");
    return 0;
}

练习 2.42

问题:根据你自己的理解重写一个 Sales_data.h 头文件,并以此为基础重做 2.6.2节(第67页)的练习。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354

推荐阅读更多精彩内容