C++ Primer 第五版 课后章节练习答案 第一、二章

编译软件为 vs2015。

第一章

练习1.9:

编写程序,使用 while 循环将 50 到100 的整数相加。

#include "stdafx.h"
#include<iostream>


int main()
{
	int sum = 0, val = 50;
	while (val <= 100) {
		sum += val;
		val++;
	}
	std::cout << " sum of 50 to 100 is " << sum << std::endl;
    return 0;
}

练习1.10:

除了++运算符将运算对象的值增加 1 之外,还有一个递减运算符(--)实现将值减少 1 。编写程序,使用递减运算符在循环中按照递减顺序打印出 10 到 0 之间的整数。

#include "stdafx.h"
#include<iostream>

int main() 
{
	int i = 10;
	while (i >= 0) {
		std::cout << i << std::endl;
		i--;
	}
	return 0;
}

练习1.11:

编写程序,提示用户输入两个整数,打印出这两个整数所指定范围内的所有整数。

(此程序可判断输入两个值的大小,并按照递增的顺序打印两个值范围内的所有整数,包括两个值在内。若按照递减的顺序原理相同。)

#include "stdafx.h"
#include<iostream>

int main() 
{
	int i, j;
	std::cout << "please input two numbers:" << std::endl;
	std::cin >> i >> j;
	if (i >= j)
	{
		while (j <= i) {
			std::cout << j << std::endl;
			j++;
		}
	}
	else {
		while (i <= j) {
			std::cout << i << std::endl;
			i++;
		}
	}
	return 0;
}

练习1.13:

用 for 循环重做1.4.1节中的所有练习。

//for循环实现 50 到 100 间整数相加
#include "stdafx.h"
#include<iostream>


int main() 
{
	int sum = 0;
	for (int val = 50; val <= 100; val++)
		sum += val;
	std::cout << " sum of 50 to 100 is: "<<sum << std::endl;
	return 0;
}
//for 循环按递减顺序打印 10 到 0 间整数
#include "stdafx.h"
#include<iostream>


int main() 
{
	for (int i = 10; i >= 0; i--)
		std::cout << i << std::endl;
	return 0;
}
//提示用户输入两个数,for 循环打印两个数间的所有整数
#include "stdafx.h"
#include<iostream>

int main() 
{
	int i, j, max, min;
	std::cout << "please input two numbers:" << std::endl;
	std::cin >> i >> j;
	if (i >= j)
		max = i, min = j;
	else {
		max = j, min = i;
	}
	for (int val = min; val <= max; val++)
		std::cout << val << std::endl;
	return 0;
}

练习1.16:

编写程序,从 cin 中读取一组数据,输出其和。

#include "stdafx.h"
#include<iostream>


int main() 
{
	int sum = 0, val = 0;
	std::cout << "please intput numbers:" << std::endl;
	while (std::cin>>val) 
		sum += val;
	std::cout << " sum of these numbers is: " << sum << std::endl;
	return 0;
}

练习1.20:

在网站 http://www.informit.com/title/0321714113 上,第一章的代码目录中包含了头文件 Sales_item.h将它拷贝到你自己的工作目录中。用它编写一个程序,读取一组书籍销售记录,将每条记录打印到标准输出上。

#include "stdafx.h"
#include<iostream>
#include"Sales_item.h"


int main()
{
	Sales_item book;
	std::cin >> book;
	std::cout << book << std::endl;
    return 0;
}

使用输入方法如下:

练习1.21:

编写程序,读取两个 ISBN 相同的 Sales_item 对象,输出它们的和。

#include"stdafx.h"
#include<iostream>
#include"Sales_item.h"

int main() 
{
	Sales_item book1, book2;
	std::cin >> book1 >> book2;
	std::cout << book1 + book2 << std::endl;
	return 0;
}

练习1.22:

编写程序,读取多个具有相同 ISBN 的销售记录,输出所有记录的和。

#include"stdafx.h"
#include<iostream>
#include"Sales_item.h"

int main()
{
	Sales_item salessum, sales;
	std::cin >> salessum;
		while (std::cin >> sales)
			salessum += sales;
		std::cout << salessum;
	return 0;
}

练习1.23:

编写程序,读取多条销售记录。并统计每个 ISBN (每本书)有几条销售记录。

#include"stdafx.h"
#include<iostream>
#include"Sales_item.h"

int main() {
	Sales_item salessum, sales;
	int cnt = 1;
	if (std::cin >> salessum){
		while (std::cin >> sales) {
			if (sales.isbn() == salessum.isbn())
				++cnt;
			else {
				std::cout << " the note of " << salessum.isbn() << " is " << cnt << std::endl;
				cnt = 1;
				salessum = sales;
			}
		}
		std::cout << " the note of " << salessum.isbn() << " is " << cnt << std::endl;//记住打印最后一条记录
	}
	return 0;
}
//此程序只能读取多条ISBN号相同连续的记录 类似:xxxxccc,若为:xcxcxcx,则不能处理 

第二章

练习2.3、2.4:

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

#include "stdafx.h"
#include<iostream>

int main()
{
	unsigned u = 10, u2 = 42;
	std::cout << u2 - u << std::endl;
	std::cout << u - u2 << std::endl;

	int i = 10, i2 = 42;
	std::cout << i2 - i << std::endl;
	std::cout << i - i2 << std::endl;
	std::cout << i - u << std::endl;
	std::cout << u - i << std::endl;
    return 0;
}

结果分别对应如下:

32;
4294967264;(32位)
32;
-32;
0;
0;

练习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;

定义有区别,第一种定义数据类型为十进制,第二种为八进制。八进制时,“int month = 09”是无效的定义,9 基于八进制时应该有进位。

练习2.7:

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

(a) “who goes with F\145rgus?\012”;

(b)3.14e1L;

(c)1024f;

(d)3.14L;

解答:

(a)字符串字面值。\145输出为字母 e ,\012表示换行符;

(b)扩展精度浮点型字面值。3.14以 e 为底,10 的 1 次方;

(c)单精度浮点型字面值;

(d)扩展精度浮点型字面值;

练习2.8: 

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

#include "stdafx.h"
#include<iostream>


int main()
{
	std::cout << "\062\115\n" << std::endl;
	std::cout << "\062\t\x4d\012" << std::endl;
    return 0;
}

输出结果: (转义字符参照ASCII码) 

练习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)非法定义。std::cin>>输入符号相当于给变量赋值,初始化不是赋值,因此该变量是未定义的,正确表达为:

          int input_value = 0;

         std::cin>>input_value;

(b)非法定义.。此表达为列表初始化,变量类型为整形,初始化值为浮点数,不匹配,存在初始化数据丢失的风险。正确表达为:

         double i = { 3.14 };

(c)非法定义。wage变量没有被定义,变量定义的形式的是在类型说明符后紧跟多个变量名,并且以逗号隔开,以分号结束。正确表达为:

          double wage;

          double salary = wage = 9999.99;

(d)非法定义。与(b)相同,将浮点数赋予整型变量作为初始化值了。正确表达为:

           double i = 3.14;

练习2.10: 

下列变量的初始值分别是什么?

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

变量 global_str 是定义于函数体之外的,由其类决定的(每个类各自决定其促石化对象的方式,此处为 string 类),非显示的初始化,为一个空串。

变量 global_int 为定义于函数体之外的,其被初始化为 0。

变量 local_ int 为定义于函数体内的内置类型,没有被初始化,其值是未定义的。

变量 local_str 为类的非显示初始化,定义于函数体内,被初始化为一个空串。

练习2.11: 

指出下面的语句是声明还是定义。

(a)extern int ix = 1024;

(b)int iy;

(c)extern int iz;

解答:

(a)定义。(若出现在函数体内部,则会引发错误)

(b)定义。

(c)声明。

练习2.12:

请指出下面的名字哪些是非法的?

(a)int double = 3.14;

(b)int _;

(c)int catch-22;

(d)int 1_or_2;

(e)double Double;

解答:

(a)非法定义。double 为关键字,不能被用作标识符。

(b)正确。(注意,定义在函数体外的标识符不能以下画线开头。)

(c)非法定义。c++中标识符只能包括字母、数字、下画线。

(d)非法定义。标识符必须以字母或下画线开头。

(e)正确。 

 练习2.13:

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

int i = 42;
int main()
{
	int i = 100;
	int j = i;
	std::cout << j << std::endl;
	return 0;
}

 输出结果 j = 100;

练习2.14: 

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

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

解答:

程序合法,输出结果为:100 45 。在 for 语句中定义的 i 值,只能在 for 语句中访问。

练习2.15:

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

(a)int ival = 1.01;

(b)int &rval1 = 1.01;

(c)int &rval2 = ival;

(d)int &rval3;

解答:

(a)合法的;但赋值为浮点数,会被保存为整数。

(b)不合法,引用不是对象,它只是一个已经存在的对象的另一个名字,不能被定义;

(c)合法;

(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)合法,将3.14159这个值赋予变量 d;

(b)合法,将 r1 指向的对象 i 赋给 r2 指向的对象 d,并且类型会发生转变;

(c)合法,将 r2 指向的对象 d 赋给 i,并且类型会发生转变;

(d)合法,将 d 赋给 r1指向的对象,并且类型会发生转变;

练习2.17:

执行下面的代码将输出什么结果?

#include "stdafx.h"
#include<iostream>

int main()
{
	int i, &ri = i;
	i = 5, ri = 10;//执行的操作是将 10 赋予 ri 指向的对象 i;
	std::cout << i << " " << ri << std::endl;
    return 0;
}

 输出如下:

练习2.18: 

编写代码分别更改指针的值以及指针所指对象的值。

#include "stdafx.h"
#include<iostream>

int main()
{
	int i = 42, d = 36;//定义两个 int 型变量
	int *p = &i;//定义指针 p 指向变量 i 的地址
	std::cout << i << " " << d << " " << p << "\n" << std::endl;//输出此时变量 i、d 的值以及指针 p 的值
	p = &d;//更改指针使其指向变量 d 的地址,相当于更改了指针的值
	*p = 11;//更改指针所指对象的值,此时指针指向的对象是 d
	std::cout << i << " " << d << " " << p << "\n" << std::endl;
	//输出此时变量 i、d 的值以及指针 p 的值,更改了指针 p 的值以及变量 d 的值
    return 0;
}

 输出结果如下:

练习2.19: 

说明指针和引用的主要区别。

指针和引用都能提供对其它对象的间接访问,两者最大的不同在于指针本身是一个对象,允许对指针赋值和拷贝,但引用不是;其次,指针无须在定义时赋初始值,但是引用必须被初始化。 

练习2.20: 

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

int i = 42;
	int *p1 = &i;
	*p1 = *p1 * *p1;

 解答:

此段代码将变量 i 平方后在赋值到 i;输出 i 为 1764,等价于 i = i *  i= 42*42;

练习2.21:

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

int i = 0;

(a)double*   dp = &i;

(b)int *ip = i;

(c)int *p = &i;

解答:

(a)不合法。i 为 int 类型的值,不能用于初始化 double 类型的指针。

(b)不合法。不能把 int 变量直接赋值给指针。

(c)合法。指针指向变量 i 的地址

 练习2.22:

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

 if (p) // ...

if (*p) // ..

解答:

 if (p) // ... 如果 p 的值为 0,条件值为 false,看 p 是否为空指针;

if (*p) // ..如果 p 指向的对象的值为 0,条件值为 false,看 p 指向的对象值是否为 0;

练习2.23: 

给定指针 p, 你能知道它是否指向了一个合法的对象吗?如果能,叙述判断的思路,如果不能,说明原因。

不能直接判断。例如存在 void* 型指针,无法确定其类型,也无法确定该对其进行哪些操作,需要更多的信息联合判断。 

练习2.24:

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

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

解答:

因为 void* 是一种特殊的指针类型,其指针的类型不确定,可以指向任意类型对象的地址,但 long* 型是确定的,为长整型,与变量 i 的类型不匹配,因此指针 lp 的定义是非法的。 

练习2.25: 

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

(a)int*  ip,i,&r = i;

(b)int i,*ip = 0;

(c)int*  ip,ip2;

解答:

(a)ip 是一个 int 型指针,i 为 int 型变量,r 为一个引用,与 i 绑定在一起;

(b)i 为一个 int 型变量,ip 为一个 int 型指针,值为 0 ,即为空指针; 

(c)ip 为一个 int 型指针,ip2 是一个 int 型变量;

练习2.26: 

下面哪些句子是合法的?如果有不合法的句子,请说明为什么?

(a)const int buf;

(b)int cnt = 0;

(c)const int sz = cnt;

(d)++cnt;++sz;

解答:

 (a)不合法,const 对象必须初始化;

(b)合法;

(c)合法;

(d)不合法,const 对象值不能被改变,++sz 操作改变了 const sz 对象的值;

练习2.27:

下面那些初始化是合法的?请说明原因。

(a)int i = -1,&r = 0;

(b)int *const p2 = &i2;

(c)const int i = -1,&r = 0;

(d)const int *const p3 = &i2;

(e)const int *p1 = &i2;

(f)const int &const r2;

(g)const int i2 = i,&r = i;

解答: 

(a)不合法,引用类型的初始值必须是一个对象;

(b)合法,常量指针 p2 指向 i2 的地址;

(c)i 是一个常量,r 是一个常量引用(与引用不同,引用初始值必须为一个对象);

(d)合法,常量指针 p3 指向 i2 的地址;

(e)合法,p1 为指向常量的指针;

(f)不合法,&const r2 是对常量 r2 的引用,未经初始化,const 对象必须初始化;

(g)合法;

练习2.28: 

说明下面这些定义是什么意思,挑出其中不合法的。

(a)int i,*const cp;

(b)int *p1,*const p2;

(c)const int ic,&r = ic;

(d)const int *const p3;

(e)const int *p; 

 解答:

(a)不合法,cp 为常量指针,必须初始化;

(b)不合法,p2 为常量指针,必须初始化;

(c)不合法,const 对象必须初始化,ic 为 const 对象,没有初始化;

(d)不合法, p3 为指向常量的常量指针,必须初始化;

(e)合法,p 为指向常量的指针;

练习2.29:

假设已有上一个练习中定义的那些变量,则下面的哪些语句是合法的?请说明原因。

(a)i = ic;

(b)p1 = p3;

(c)p1 = &ic;

(d)p3 = &ic;

(e)p2 = p1;

(f)ic = *p3;

解答: 

(a)合法,拷贝常量 ic 的值,并不会改变它;

(b)不合法,p1 为指向普通变量的指针,p3 为常量指针,类型不匹配;

(c)不合法,p1 为指向普通变量的指针,而 ic 为常量,p1 会改变只想对象的值;  

(d)不合法,p3 为指向常量的常量指针,自己本身是一个常量,一旦初始化完成,其值不能再被改变;

(e)不合法,p2 是常量指针,初始化完成后,其值不能再被改变;

(f)不合法,ic 为常量,不能在被赋值;

练习2.30: 

对于下面这些语句,请说明对象被声明成了顶层 const 还是底层 const ?

(a)const int v2 = 0;

(b)int v1 = v2;

(c)int *p1 = &v1,&r1 = v1;

(d)const int *p2 = &v2,*const p3 = &i,&r2 = v2;

解答:

v2 自己本身是一个常量,为顶层 const;

p2 为指向常量的指针,为底层 const;

p3 靠右的 const 是顶层,靠左的 const 是底层;

r2 是对常量的引用,是底层 const;

练习2.31:

假设已有上一个练习中所做的那些声明,则下面的哪些语句是合法的?请说明顶层 const 和 底层 const 在每个例子中有何体现。

(a) r1 = v2;

(b)p1 = p2;

(c)p2 = p1;

(d)p1 = p3; 

(f)p2 = p3;

 解答:

(a) 合法,拷贝 v2 的值并不会改变它;

(b)不合法,p1 是指向普通变量的指针,p2 是指向常量的指针,是底层 const ,p1 与 p2 不匹配;

(c)合法,p2 是底层 const ,允许将非常量变为常量;

(d)不合法,p3 是底层 const ,p1 是指向常量的指针,不匹配;

(e)合法,p2 和 p3 均为底层 const;

练习2.32:

下面的代码是否合法?如果非法,请设法将其修改正确。

int null = 0,*p = null;

解答: 

不合法,不能把 int 变量直接赋值给指针。

修改:int null = 0,*p = &null; 

练习2.33:

利用本节定义的变量,判断下列语句的运行结果。

a = 42;

b = 42;

c = 42;

d = 42;

e = 42;

f = 42;

解答: 

(需要参考书中的定义) 

a = 42;// a 是一个整数,因此可以将 42 赋值给 a;

b = 42;// b 是一个整数,可以将 42 赋值给 b ,auto 会忽略顶层 const 属性,b 不是常量;

c = 42;// c 是一个整数,可以将 42 赋值给 c;

错误;// d 为一个整形指针,正确语句应为 *d = 42;// 指针 d 的值为 42;

错误;// e 为一个指向整形常量的指针,正确语句应为 e = &a;

错误;// g 为一个整形常量引用,与常量 ci 绑定,不能修改;

练习2.34: 

基于上一个练习中的变量和语句编写一段程序,输出赋值前后变量的内容,你刚才的推断正确吗?如果不对,请反复研读本节的示例直到你明白错在何处为止。

解答: 

按照练习2.33定义的程序语句如下:

#include "stdafx.h"
#include<iostream>

int main()
{
	int i = 0, &r = i;// i 是一个整数,r 是对 i 的引用;
	auto a = r;// a 是一个整数;
	const int ci = i, &cr = ci;// ci 是一个整形常量,cr 是对整形常量的引用;
	auto b = ci;// b 是一个整数,auto 忽略掉了 ci 的顶层 const;
	auto c = cr;// c 与 b 同,是一个整数
	auto d = &i;// d 是一个整形指针,指向整数 i;
	auto e = &ci;// e 是一个指向整形常量 ci 的指针(对常量对象取地址是一种底层 const);
	auto &g = ci;// g 是一个对整形常量 ci 的应用,与 ci 绑定;
	std::cout << " a = " << a << "\n" << std::endl;
	std::cout << " b = " << b << "\n" << std::endl;
	std::cout << " c = " << c << "\n" << std::endl;
	std::cout << " d = " << d << "\n" << std::endl;
	std::cout << " e = " << e << "\n" << std::endl;
	std::cout << " g = " << g << "\n" << std::endl;
	//练习2.33:
	a = 42;
	b = 42;
	c = 42;	
	d = 42;
	e = 42;
	g = 42;
	
        std::cout << " a = " << a << "\n" << std::endl;
	std::cout << " b = " << b << "\n" << std::endl;
	std::cout << " c = " << c << "\n" << std::endl;
	std::cout << " d = " << d << "\n" << std::endl;
	std::cout << " e = " << e << "\n" << std::endl;
	std::cout << " g = " << g << "\n" << std::endl;
    return 0;
}

下图展示编译软件中显示的错误类型,分别对应 d 、e、g、,由此可知与上一练习中分析的相同; 

下面是修改正确后的语句:

#include "stdafx.h"
#include<iostream>

int main()
{
	int i = 0, &r = i;// i 是一个整数,r 是对 i 的引用;
	auto a = r;// a 是一个整数;
	const int ci = i, &cr = ci;// ci 是一个整形常量,cr 是对整形常量的引用;
	auto b = ci;// b 是一个整数,auto 忽略掉了 ci 的顶层 const;
	auto c = cr;// c 与 b 同,是一个整数
	auto d = &i;// d 是一个整形指针,指向整数 i;
	auto e = &ci;// e 是一个指向整形常量 ci 的指针(对常量对象取地址是一种底层 const);
	auto &g = ci;// g 是一个对整形常量 ci 的应用,与 ci 绑定;
	std::cout << " a = " << a << "\n" << std::endl;
	std::cout << " b = " << b << "\n" << std::endl;
	std::cout << " c = " << c << "\n" << std::endl;
	std::cout << " d = " << d << "\n" << std::endl;
	std::cout << " e = " << e << "\n" << std::endl;
	std::cout << " g = " << g << "\n" << std::endl;
	std::cout << "\n" << std::endl;
	//练习2.33:
	a = 42;
	b = 42;
	c = 42;	
	//d = 42;
	//e = 42;
	//g = 42;

	*d = 42;//对 d 指向的对象即 i 赋值;
	e = &a;//此时 e 指向整数 a 的地址;

	std::cout << " a = " << a << "\n" << std::endl;
	std::cout << " b = " << b << "\n" << std::endl;
	std::cout << " c = " << c << "\n" << std::endl;
	std::cout << " d = " << d << "\n" << std::endl;
	std::cout << " e = " << e << "\n" << std::endl;
	std::cout << " g = " << g << "\n" << std::endl;
    return 0;
}

运行结果如下:

练习2.35: 

判断下列定义推断出的类型是什么,然后编写程序进行验证。

const int i = 42;

auto j = i;

const auto &k = i;

auto *p = &i;

const auto j2 = i,&k2 = i; 

解答:

i 为常整数;

j 为整数;

k 为整形常量引用;

p 为指向整形常量的指针;

j2 为一个常整数;

k2 为整形常量引用;

程序运行如下:

#include "stdafx.h"
#include <iostream>
#include <typeinfo>
using std::cout;
using std::endl;


int main()
{
	const int i = 42;
	auto j = i;
	const auto &k = i;
	auto *p = &i;
	const auto j2 = i, &k2 = i;
	cout << "i is " << typeid(i).name() << "\n" << endl;
	cout << "j is " << typeid(j).name() << "\n" << endl;
	cout << "k is " << typeid(k).name() << "\n" << endl;
	cout << "p is " << typeid(p).name() << "\n" << endl;
	cout << "j2 is " << typeid(j2).name() << "\n" << endl;
	cout << "k2 is " << typeid(k2).name() << "\n" << endl;
    return 0;
}

运行结果如下: 

 

练习2.36:

关于下面的代码,请指出每一个变量的类型及程序结束时它们各自的值。

int a = 3,b = 4;

decltype(a) c = a;

decltype ((b)) d = a;

++c;

++d;

解答:

a 为一个整数,数值为 4;

b 为一个整数,数值为 4;

c 为一个整数,数值为 4;

d 为一个整形引用,与 a 绑定,数值为 4;

注:此时由于 d 是一个引用且与 a 绑定,所以最后 a 的输出数值已经由 d 改变,所以不再是 3 而是 4;

程序验证如下:

#include "stdafx.h"
#include<iostream>
using std::cout;
using std::endl;


int main()
{
	int a = 3, b = 4;
	decltype(a) c = a;
	decltype((b)) d = a;
	++c;
	++d;
	cout << "a =  " << a << " and type is " << typeid(a).name() << "\n" << endl;
	cout << "b =  " << b << " and type is " << typeid(b).name() << "\n" << endl;
	cout << "c =  " << c << " and type is " << typeid(c).name() << "\n" << endl;
	cout << "a =  " << d << " and type is " << typeid(d).name() << "\n" << endl;
	return 0;
}

结果如图:

练习2.37: 

赋值是会产生引用的一类典型表达式,引用的类型就是左值的类型。也就是说,如果 i 是 int ,则表达式 i = x 的类型是 int&。根据这一特点,请指出下面代码每一个变量的类型和值。

int a = 3,b = 4;

decltype(a) c = a;

decltype(a = b) d = a;

解答: 

a 为整数,值为 3;

b 为整数,值为 4;

c 为整数,值为 3;

d 为整形引用,值为 3; 

练习2.38: 

说明 decltype 指定类型和由 auto 指定类型有何区别。请举出一个例子, decltype 指定的类型和 auto 指定的类型一样;再举出一个例子,decltype 指定的类型和 auto 指定类型不一样。

解答: 

 区别:再返回变量的类型中, auto 一般会忽略掉顶层 const,底层 const 会保留下来 ,而 decltype 返回变量的类型则包括顶层 const 和引用在内。

举例如下:

#include "stdafx.h"
#include<iostream>
using std::cout;
using std::endl;

int main()
{
	int m = 5, &n = m;
	//auto 与 decltype 指定类型相同时
	auto a = m;//a 为一个整数
	decltype(m) b = m;//b 为一个整数
	cout << "a =  " << a << " and type is " << typeid(a).name() << "\n" << endl;
	cout << "b =  " << b << " and type is " << typeid(b).name() << "\n" << endl;
	//auto 与 decltype 指定类型不同时
	auto i = n;//i 为一个整数
	decltype(n) t = n;//t 为一个整型引用
	cout << "i =  " << i << " and type is " << typeid(i).name() << "\n" << endl;
	cout << "t =  " << t << " and type is " << typeid(t).name() << "\n" << endl;
    return 0;
}

练习 2.39:

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

解答:  

#include "stdafx.h"

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

 错误提示如下:

练习2.40:

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

解答: 

struct Sales_data { 
	std::string bookNo;//定义一个类型为 string 的变量,书号
	unsigned unit_sold = 0;//定义一个类型为 unsigned 的变量,销售量
	double revenue = 0.0;//定义一个类型为 double 的变量,销售额
	double unit_price = 0.0;//定义一个类型为double 的变量,销售单价
      //此为举例,可自定义变量
};

 练习2.41:

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

解答: (注:编程过程中由于题目中说明的是输入相同 ISBN 号的数据记录,因此程序中没有写判断 ISBN 号是否相同这一步骤,在测试程序时注意要输入相同的 ISBN 号)

//用自己定义的 Sales_data 类改写练习1.20。读取一组书籍销售记录并将结果打印到标准输出上

//用自己定义的 Sales_data 类改写练习1.20。读取一组书籍销售记录并将结果打印到标准输出上
#include "stdafx.h"
#include<iostream>
#include<string>

struct Sales_data {
	std::string bookNo;//书号ISBN
	unsigned unit_sold = 0;//销售量
	double revenue = 0.0;//销售额
};

int main()
{
	Sales_data book;
	double price = 0.0;//销售单价
	//首先读入书号ISBN、销售量、单价
	std::cin >> book.bookNo >> book.unit_sold >> price;
	//计算销售额并打印结果到标准输出上
	book.revenue = book.unit_sold*price;
	std::cout << book.bookNo << " total revenue is " << book.revenue << std::endl;
	return 0;
}

 

//用自己定义的 Sales_data 类改写练习1.21。读取 ISBN 号相同的两组书籍并计算这两个项目的“和” 

//用自己定义的 Sales_data 类改写练习1.21。读取 ISBN 号相同的两组书籍并计算这两个项目的“和”
#include"stdafx.h"
#include<iostream>
#include<string>

struct Sales_data {
	std::string bookNo;//书号ISBN
	unsigned unit_sold = 0;//销售量
	double revenue = 0.0;//销售额
};//注意不要忘记加分号

int main()
{
	Sales_data book1, book2;//两本 ISBN 号相同的书籍
	double price = 0.0, price1 = 0.0, price2 = 0.0;//平均销售单价、book1销售单价、book2销售单价
	double total_revenue = 0.0;//总销售额
	//首先读入两组 ISBN 号相同的书籍记录book1、book2 
	std::cin >> book1.bookNo >> book1.unit_sold >> price1 >> book2.bookNo >> book2.unit_sold >> price2;
	//计算两个项目的和,包括总销售量、总销售额、平均售价
	total_revenue = book1.unit_sold*price1 + book2.unit_sold *price2;
	price = total_revenue / (book1.unit_sold + book2.unit_sold);
	std::cout << book1.bookNo << " " << book1.unit_sold + book2.unit_sold << " " << total_revenue << " " << price << std::endl;
	return 0;
}

 //用自己定义的 Sales_data 类改写练习1.22。读取多个具有相同 ISBN 的销售记录,并输出他们的和:

//用自己定义的 Sales_data 类改写练习1.22。读取多个具有相同 ISBN 的销售记录,并输出他们的和
#include"stdafx.h"
#include<iostream>
#include<string>

struct Sales_data {
	std::string bookNo;//书号ISBN
	unsigned unit_sold = 0;//销售量
	double revenue = 0;//销售额
};

int main()
{
	double a_price = 0.0, salessum_price = 0.0, sales_price = 0.0;//平均销售单价
	Sales_data salessum, sales;//定义总项目和单项
	//首先读入第一个输入的项,并将其初始化为 salessum
	std::cin >> salessum.bookNo >> salessum.unit_sold>>salessum_price;
	salessum.revenue = salessum.unit_sold*salessum_price;//首先计算出第一项的销售额
	while (std::cin >> sales.bookNo >> sales.unit_sold >> sales_price) {
		sales.revenue = sales.unit_sold*sales_price;
		salessum.unit_sold = salessum.unit_sold + sales.unit_sold;//将第一项作为总项不断与输入项相加,求得总销售量
		salessum.revenue = salessum.revenue + sales.revenue;//求得总销售额
		a_price = salessum.revenue / salessum.unit_sold;//求出平均销售单价
	}
	std::cout << salessum.bookNo << " " << salessum.unit_sold << " " 
		      << salessum.revenue << " " << a_price << " " << std::endl << "\n";
	return 0;
}

 (此段程序用到 while 循环,当输入结束时,退出 while 循环简单的方式就是输入和以上格式不同的字符即可,这里使用的是N N)

//用自己定义的 Sales_data 类改写练习1.23、1.24。 读取多条销售记录,并统计每个ISBN有几条销售记录,每个 ISBN 应该聚集在一起。

//用自己定义的 Sales_data 类改写练习1.23、1.24。 读取多条销售记录,并统计每个ISBN有几条销售记录,每个 ISBN 应该聚集在一起。
#include"stdafx.h"
#include<iostream>
#include<string>

struct Sales_data {
	std::string bookNo;
	unsigned unit_sold = 0;
	double revenue = 0.0;
};

int main() {
	Sales_data salessum, sales;
	double price1 = 0.0, price2 = 0.0;
	double total_revenue = 0.0;
	int cnt = 1; //设置计数器 cnt
	if (std::cin >> salessum.bookNo >> salessum.unit_sold >> price1) { //使得第一个输入的组为salessum
		salessum.revenue = salessum.unit_sold*price1;
		while (std::cin >> sales.bookNo >> sales.unit_sold >> price2) { //如果继续输入则为sales
			sales.revenue = sales.unit_sold*price2;
			if (sales.bookNo == salessum.bookNo) {
				++cnt;//如果输入的组的书号 ISBN 相同,则计数器加一
				salessum.revenue = salessum.revenue + sales.revenue;
			}
			else {
				std::cout << " the note of " << salessum.bookNo << " is " << cnt 
                          << " and the total revenue is " << salessum.revenue << std::endl;
				cnt = 1; // 如果输入的某一组 ISBN 与之前不同,则输出此时计数器的值,即为销售记录的条数,并将计数器置为1
				salessum = sales;
			}
			}
			std::cout << " the note of " << salessum.bookNo << " is " << cnt 
                      << " and the total revenue is " << salessum.revenue << std::endl;
		}// 直到输入结束,输出最后一条 ISBN 的销售记录
	return 0;
}
//如题目,ISBN 记录应该连在一起,此程序只能读取多条ISBN号相同连续的记录 类似:xxxxccc,若为:xcxcxcx,则不能处理 

 //用自己编写的Sales_data文件改写练习1.25。运行书中的书店程序

//用自己编写的Sales_data文件改写练习1.25。运行书中的书店程序
#include"stdafx.h"
#include<iostream>
#include<string>

struct Sales_data {
	std::string bookNo;
	unsigned unit_solds = 0;
	double revenue = 0.0;
};

int main()
{
	Sales_data totals;
	double price1 = 0.0, price2 = 0.0;
	if (std::cin >> totals.bookNo >> totals.unit_solds >> price1) {
		totals.revenue = totals.unit_solds*price1;
		Sales_data trans;
		while (std::cin >> trans.bookNo >> trans.unit_solds >> price2) {
			trans.revenue = trans.unit_solds*price2;
			if (totals.bookNo == trans.bookNo) {
				totals.unit_solds += trans.unit_solds;
				totals.revenue += trans.revenue;
			}
			else {
				std::cout << " The note of " << totals.bookNo << " unit sold is " 
					      << totals.unit_solds << " total revenue is " << totals.revenue << "\n" << std::endl;
				totals = trans;

			}
		}
		std::cout << " The note of " << totals.bookNo << " unit sold is " 
			      << totals.unit_solds << " total revenue is " << totals.revenue << "\n" << std::endl;
	}
	else {
		std::cerr << " No data?! " << "\n" << std::endl;
		return -1;
	}
	return 0;
}

 (N N表示结束符)

练习2.42: 

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

解答:Sales_data.h文件如下

#ifndef SALES_DATA_H
#define SALES_DATA_H

#include <iostream>
#include <string>

struct Sales_data {
	std::string bookNo;
	unsigned unit_sold = 0;
	double revenue = 0.0;
	double price = 0.0;

	void oridata(Sales_data item);//设置原始数据的对应值
	void cins();//设置输入函数
	void data_revenue();//设置求销售额函数
	void sumdata(Sales_data item);//设置项相加函数
	double averdata();//设置求平均销售单价函数
	void couts();//设置输出函数
};
#endif

void Sales_data::cins() {
	std::cin >> bookNo >> unit_sold >> price;
}

void Sales_data::oridata(Sales_data item) {
	bookNo = item.bookNo;
	unit_sold = item.unit_sold;
	revenue = item.revenue;
	price = item.price;
}

void Sales_data::data_revenue() {
	revenue = unit_sold*price;
}

void Sales_data::sumdata(Sales_data item) {
	if (bookNo != item.bookNo)
	return;
	unit_sold += item.unit_sold;
	revenue += item.revenue;
}

double Sales_data::averdata() {
	if (unit_sold != 0)
		return revenue / unit_sold;
	else
		std::cout<< "no sales";
}

void Sales_data::couts() {
	double aver_revenue = averdata();
	std::cout << bookNo << " " << unit_sold << " " << revenue << " " << aver_revenue << "\n";
}

使用方法如下: 

#include "stdafx.h"
#include<iostream>
#include<string>
#include"Sales_data.h"

//1.20读取一组书籍销售记录并将结果打印到标准输出上
int main()
{
	Sales_data book;
        book.cins();
	book.data_revenue();
	book.couts();
	return 0;
}*/

运行结果如下: 

#include "stdafx.h"
#include<iostream>
#include<string>
#include"Sales_data.h"

//1.21读取 ISBN 号相同的两组书籍并计算这两个项目的“和”
int main()
{
	Sales_data book1, book2;
	book1.cins();
	book2.cins();
	book1.data_revenue();
	book2.data_revenue();
	book2.sumdata(book1);
	book2.couts();
	return 0;
}

运行结果如下:

#include "stdafx.h"
#include<iostream>
#include<string>
#include"Sales_data.h"

//1.22读取多个具有相同 ISBN 的销售记录,并输出他们的和
int main()
{
	Sales_data salessum, sales;
	salessum.cins();
	salessum.data_revenue();
	while (std::cin >> sales.bookNo >> sales.unit_sold >> sales.price) {
		sales.data_revenue();
		salessum.sumdata(sales);
	}
	salessum.couts();
	return 0;
}

//1.23、1.24 读取多条销售记录,并统计每个ISBN有几条销售记录
#include "stdafx.h"
#include<iostream>
#include<string>
#include"Sales_data.h"

int main() {
	Sales_data salessum, sales;
	int cnt = 1;
	if (std::cin >> salessum.bookNo >> salessum.unit_sold >> salessum.price) {
		salessum.data_revenue();
		while (std::cin >> sales.bookNo >> sales.unit_sold >> sales.price) {
			sales.data_revenue();
			if (sales.bookNo == salessum.bookNo) {
				salessum.sumdata(sales);
				++cnt;
			}
			else {
				std::cout << "\n";
				std::cout << " the sum of " << salessum.bookNo << " is " << " \n";
				salessum.couts();
				std::cout << " the note of " << salessum.bookNo << " is " << cnt << "\n";
				std::cout << "\n";
				cnt = 1;
				salessum = sales;
			}
		}
		std::cout << "\n";
		std::cout << " the sum of " << salessum.bookNo << " is " << "\n";
		salessum.couts();
		std::cout << " the note of " << salessum.bookNo << " is " << cnt << "\n";
		std::cout << "\n";
	}
	return 0;
}

运行结果如下:

 

 

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值