c++ primer(第五版)学习笔记及习题答案代码版(第二章)

笔记较为零散,都是自己不熟悉的知识点。
习题答案至于一个.cc 中,需要演示某一题直接修改 #define NUM**, 如运行2.23题为#define NUM223;

chapter 2

1、当我们把一个超出其取值范围的值赋给一个指定类型的对象时,结果取决于这种类型是signed还是unsigned的。

       A 对于unsigned类型,编译器必须调整越界值使其满足要求。编译器会将该值对 unsigned 类型的可能取值数目求模,然后取所得值。比如 8 位的unsigned char,其取值范围从 0 到 255(包括 255)。如果赋给超出这个范围的值,那么编译器将会取该值对 256 求模后的值。例如,如果试图将 336 存储到 8 位的 unsigned char 中,则实际赋值为 80,因为 80 是 336 对 256 求模后的值。

eg:  unsighed char a = -1;      a 为-1%256= (-1+256)%256 = 255

对于 unsigned 类型来说,负数总是超出其取值范围。unsigned 类型的对

象可能永远不会保存负数。有些语言中将负数赋给 unsigned 类型是非法的,但

在 C++ 中这是合法的。

    B当将超过取值范围的值赋给 signed 类型时,由编译器决定实际赋的值。在实际操作中,很多的编译器处理 signed 类型的方式和 unsigned 类型类似。也就是说,赋值时是取该值对该类型取值数目求模后的值。然而我们不能保证编译器都会这样处理 signed 类型。

2、

20 // decimal

024 // octal

0x14 // hexadecimal

以 0(零)开头的字面值整数常量表示八进制,以 0x 或 0X 开头的表示十

六进制。

       通过增加后缀,能够强制将字面值整数常量转换为 long、unsigned 或 unsigned long类型。通过在数值后面加 L 或者 l(字母“l”大写或小写)指定常量为 long 类型。(定义长整型时,应该使用大写字母 L。小写字母 l 很容易和数值 1 混淆。)

128u /* unsigned */                  1024UL /* unsigned long*/

1L /* long */                             8Lu /* unsignedlong*/

       通常可以用十进制或者科学计数法来表示浮点字面值常量。使用科学计数法

时,指数用 E 或者 e 表示。默认的浮点字面值常量为 double 类型。在数值的

后面加上 F 或 f 表示单精度。同样加上 L 或者 l 表示扩展精度(再次提醒,

不提倡使用小写字母l)。下面每一组字面值表示相同的值:

3.14159F                   .001f                   12.345L                     0.

3.14159E0f          1E-3F              1.2345E1L                 0e0

在char类型之前加上L可以得到wchar_t类型的宽字符面值: L'a'

3、

非打印字符的转义序列

       如果连接字符串字面值和宽字符串字面值,将会出现什么结果呢?例如:

// Concatenating plain andwide character strings is undefined

std::cout <<"multi-line " L"literal " << std::endl;

       其结果是未定义的,也就是说,连接不同类型的行为标准没有定义。这个程

序可能会执行,也可能会崩溃或者产生没有用的值,而且在不同的编译器下程序

的动作可能不同。

4、

C++ 的格式非常自由。特别是有一些地方不能插

入空格,其中之一是在单词中间。特别是不能在单词中间断开一行。但可以通过

使用反斜线符号巧妙实现:

// ok: A \ before a newlineignores the line break

std::cou\

t << "Hi"<< st\

d::endl;

等价于

std::cout <<"Hi" << std::endl;

可以使用这个特性来编写长字符串字面值:

5、

“初始化不是赋值”:初始化时在创建变量并给它赋初值,则赋值则是擦除对象的当前值并用新值代替。

C++ 支持两种初始化变量的形式:复制

初始化和直接初始化。复制初始化语法用等号(=),直接初始化则是把初始化

式放在括号中:

int ival(1024); //direct-initialization

int ival = 1024; //copy-initialization

要知道,直接初始化语法更灵活且效率更高

6、

声明用于向程序表明变量的类型和名字。定义也是声明:当定义变量时我们

声明了它的类型和名字。可以通过使用extern 关键字声明变量名而不定义它。

不定义变量的声明包括对象名、对象类型和对象类型前的关键字extern:定义负责创建与名字关联的实体。

extern int i; // declares butdoes not define i

int i; // declares and definesi

如果声明有初始化式,那么它可被当作是定义,即使声明标记为 extern:

extern double pi = 3.1416; //definition

变量能且只能被定义一次,但是可以被多次声明。

7、

引用即别名

int &refVal2;  //报错,引用必须被初始化

一般在初始化变量时,初始值会被拷贝到新建的对象中。然而定义引用时,程序把引用和它的初始值bind在一起,而不是将初始值拷贝给引用。

double dval=3.14;

int &refval5 = dval;  //报错:此处引用类型的初始值必须是int型对象。

因为引用不是对象,没有实际地址,所以不能定义指向引用的指针。

double dval;

double *pd = &dval;

double *pd2 = pd;  //正确,初始值是指向double对象的指针。

int *pi = pd;        //错误:指针pi的类型和pd的类型不匹配。

pi = &deval;        //错误:试图把double型对象的地址赋给int型指针。

int *pi = nullptr;  //等价于int *pi = 0;

int *p2;             //直接将p2初始化为字面常量0;

//需要首先#include<cstdlib>

int *p3 = NULL;             //等价于int *p3 = 0;

 新标准下,最好使用nullptr,同时尽量避免使用NULL。

8、

指向指针的引用

int i =42;

int *p;

int *&r = p;     //r是一个对指针p的引用

r = &i;          //r引用了一个指针,因此给r赋值&i就是令p指向i

*r = 0;          //解引用r得到i,也就是p指向的对象,将i的值改为0

9、

const int k;    //错误,k是一个未经初始化的常量

//file_1.cc定义并初始化了一个常量,该常量能被其他文件访问。

extern const int bufSize =fun();

//file_1.h 头文件

extern const int bufSize; //与file_1.cc中定义的bufSize是同一个。

 

double dval = 3.14;

const int &ri = dval;

弄清楚当一个常量引用被绑定到另一种类型上时发生了什么,编译器将上述代码变成:

const int temp = dval;   //由双精度浮点数生成一个临时的整型变量

const int &ri = temp;   //让ri绑定这个临时量

 

10。

一般来说非常量可以转换为常量,但反之则不行。

int i = 0;

const int ci =42;    //不允许改变ci的值,这是一个顶层const

int &r = ci;         //错误:普通的int& 不能绑定到int常量上

const int &r2 =i;    //正确:const int& 可以绑定到一个普通int上

 11、

const int sz = size();    //只有当size是一个constexpr函数时才是一条正确的声明语句

算数类型、引用和指针都属于字面值类型。自定义类Sales_items、IO库、string类型则不属于字面值类型,也就不能被定义成constexpr。

在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关。

const int *p = nullptr;        //p是一个指向整型常量的指针

constexpr int *q =nullptr;     //q是一个指向整数的常量指针

q和p类型相差甚远,p是一个指向常量的指针,而q是一个常量指针,因为constexpr将它所定义的对象置为了顶层const。

 

别名声明

using SI = Sales_items;    //SI 是 Sales_item的同义词

typedef char *pstring;

const pstring cstr = 0;     //cstr是指向char的常量指针

const pstring *ps;          //ps是一个指针,它的对象是指向char的常量指针

 12.

auto item = val1 + val2;   //item初始化为val1和val2相加的结果

auto也能在一条语句中声明多个变量,但是所有变量的初始基本数据类型必须都是一样的。

auto一般会忽略掉顶层const,同时顶层const 会保留下来。

#include<iostream>

#define NUM241
using namespace std;
int i = 42;
string global_str;
int global_int;

int main(){
/* 2.1 */
#ifdef NUM21
	cout<<"最小存储空间不同,分别是16,32,16位"
		"unsigned只能表示大于等于o的数,signed为带符号类型,可表示正数、负数和0."
		"float为单精度,double为双精度,32位系统中float占4个字节,double占8个字节。"<<endl;
#endif
/* 2.2 */
#ifdef NUM22
	cout<<"利率选择float类型,保留到小数点两位数;本金long类型,一般用整数表示;付款用double,一般为实数。"
#endif
/* 2.3 */
#ifdef NUM23
	unsigned u = 10, u2 = 42;
	cout<<u2-u<<endl;
	cout<<u-u2<<endl;
	int i = 10, i2 = 42;
	cout<< i2 - i<<endl;
	cout<< i - i2 <<endl;
	cout<< i - u <<endl;
	cout<< u - i <<endl;
#endif
/* 2.5 */
#ifdef NUM25
	cout<<"(a)'a'为char类型,L'a'为wchat_t型字面值,“a”为字符串字面值,L”a“为宽字符串型字面值;"
		"(b)10为int型,10u位unsigned型,10L为long型,10uL为unsigned long型,012为八进制表示的int型,0xC为十六进制表示的int型;"
		"(c)3.14位double型,3.14f为float型,3.14L为long double型;"
		"(d)10为int型,10u为unsigned型,10.为double型,10e-2为double型。"<<endl;
#endif
/* 2.6 */
#ifdef NUM26
	int month = 09, day = 07;
	cout<<"第二行错误,八进制没有9这个数字。"<<endl;
#endif
/* 2.7 */
#ifdef NUM27
	cout<<"(a)string型;(b)long double型;(c)float型;(d)long double型。"<<endl;
#endif
/* 2.8 */
#ifdef NUM28
	cout << 2 << "\115\012";
	cout << 2 << "\t\115\012"<<endl;
#endif
/* 2.9 */
#ifdef NUM29
	cin >> int input_value;
	int i ={3.14};
	double salary = wage = 9999.99;
	int i = 3.14;
#endif
/* 2.10 */
#ifdef NUM210
	int local_int;
	string local_str;
	cout <<"global_str:"<<global_str<<"global_int:"<<global_int<<"local_str:"<<local_str<<"local_int:"<<local_int<<endl;
#endif
/*2.11*/
#ifdef NUM211
	cout<<"(a)extern int ix =1024; 定义."
		"(b)int iy; 定义."
		"(c)extern int ix;  声明"<<endl;
#endif
/*2.12*/
#ifdef NUM212
    cout << "(a)double是c++中的关键字,不能用作用户标识符,非法。改为int dval = 3.14159;\n"
	"(c)catch-22 包含在字母、数字和下划线之外的字符“-”,非法。改为catch_22;\n"
	"(d)名字1_or_2非法,因为标识符必须以字母和下划线开始,不可以数字开头。改为one_or_two。"<<endl;	
#endif
/*2.13*/
#ifdef NUM213
	int i = 100;
	int j = i;
	cout<< j <<endl;
#endif
/*2.14*/
#ifdef NUM214
	int i = 100, sum=0;
	for(int i = 0; i != 10; ++i)
		sum += i;
	cout<< i<<" "<<sum<<endl;
#endif
/* 2.15 */
#ifdef NUM215
	cout<<"(b)非法,引用是对对象的引用,不能绑定字面值"
		"(d)引用必须初始化"<<endl;
#endif
/* 2.16 */
#ifdef NUM216
	cout<<"都是合法的,(b)中进行自动类型转换,(c)和(d)中的数值会被截取"<<endl;
#endif
/* 2.17 */
#ifdef NUM217
	int i, &ri =i;
	i = 5; ri = 10;
	cout<< i <<" "<< ri <<endl;
#endif
/* 2.18 */
#ifdef NUM218
	int *p = 0;
	int val1(1),val2(2);
	p = &val1;
	cout<<*p <<endl;
	p = &val2;
	cout <<*p<<endl;
	val2 =3;
	cout<<*p <<" "<<val2<<endl;
	*p = 4;
	cout<<*p <<" "<<val2<<endl;
#endif
/* 2.19 */
#ifdef NUM219
	cout<<"引用并非是对象而是别名,只能绑定一个对象,指针指向的对象可以改变。"<<endl;
#endif
/* 2.20 */
#ifdef NUM220
	cout<<"p1指向i,i的值改变成42*42"<<endl;
#endif
/* 2.21 */
#ifdef NUM221
	cout<<"(a)不合法,左右值类型不匹配。"
		"(b)不合法,不能将int类型赋给int*类型的指针"<<endl;
#endif
/* 2.22 */
#ifdef NUM222
	cout<<"是否p为空指针,是否p所指向的值为0."<<endl;
#endif
/* 2.23 */
#ifdef NUM223
	cout<<"不能,在指针使用之前应该判断它是否为合法的。"<<endl;
#endif
/* 2.24 */
#ifdef NUM224
	cout<<"void是特殊类型的指针,可以指向任何类型的对象;而longa类型的指针不能指向int型对象。 "
#endif
/* 2.25 */
#ifdef NUM225
	cout<<"(a)ip是指向int型的指针,r是i的引用,"
		"(b)ip是null指针,"
		"(c)ip是指向int型指针,ip2是int整型。"<<endl;
#endif
/* 2.26 */
#ifdef NUM226
	cout<<"(a)非法,没有初始化const类型;(d)非法,不能改变const类型变量。"<<endl;
#endif
/* 2.27 */
#ifdef NUM227
	cout<<"(a)不合法,r必须引用一个对象。(f)r2是一个引用,不能成为常量。"<<endl;
#endif
/* 2.28 */
#ifdef NUM228
	cout<<"(a)不合法,cp没有初始化,(b)不合法,p2没有初始化,(c)不合法,ic没有初始化,(d)不合法,p3是一个指向常量对象的常量指针,需要初始化,(e)合法,p是指向const int类型的指针。"<<endl;
#endif
/* 2.29 */
#ifdef NUM229
	cout<<"(b)不合法,指针类型不一样,(c)p3const类型不能赋值给非const类型,"
		"(d)p3是const类型指针,其值不能被改变,(e)cosnt型指针不能被改变,(f)ic的值不能被改变。"<<endl;
#endif
/* 2.30 */
#ifdef NUM230
	cout<<"v2是一个顶层的const;p2是一个底层的const,"
	     "const int *const p3:靠左的const是底层的cosnt,靠右的const是顶层的const"<<endl;
#endif
/* 2.31 */
#ifdef NUM231
	cout<<"r1=v2; 合法,底层的const初始化r1;" 
		"p1 = p2; 不合法,p2中包含底层const;"
		"p2 = p1; 合法,可以将int*转换为cosnt int*;"
		"p1 = p3; 不合法, p3拥有一个底层const而p1没有;"
		"p2 = p3;合法,p3 p2都拥有底层const。"<<endl;
#endif
/* 2.32 */
#ifdef NUM232
	cout<<"不合法,int变量null不能直接赋给指针,改为int null = 0, *p = nullptr;"<<endl;
#endif
/* 2.33 */
#ifdef NUM233
	cout<<"a为int型整数;b为int型整数;c为int型整数;不合法,d是int*, 应该是*d=42; 不合法,e是const int*,应该是e = &c; 不合法,g是const int&引用。"<<endl;
#endif
/* 2.34 */
#ifdef NUM234
	int i = 0, &r = i;
	auto a = r;
	const int ci = i, &cr = ci;
	auto b = ci;
	auto c = cr;
	auto d = &i;
	auto e = &ci;
	auto &g = ci;
	a = 42; b = 42; c = 42; d = 42; e = 42; g = 42;
#endif
/* 2.35 */
#ifdef NUM235
	const int i = 42;
	auto j = i; const auto &k = i; auto *p = &i;
	const auto j2 = i; &k2 = i;
	cout<< i << " "<< k <<" "<< p <<" "<<j2<<" "<<j2<<" "<<k2<<endl; 
	cout<<"j 是int型;k是const int&型;p是const int*类型;j2是const int型;k2是const int&." <<endl;
#endif
/* 2.36 */
#ifdef NUM236
	int a = 3, b =4;
	decltype(a) c = a;
	decltype((b)) d =a;
	++c;
	++d;
	cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
	cout<<"c是int型,d是a的引用。"<<endl;
#endif
/* 2.37 */
#ifdef NUM237
	int a = 3, b =4;
	decltype(a) c = a;
	decltype(a = b) d =a;
	cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
	cout<<"c是int型,d是int型的引用,"<<endl;
#endif
/* 2.38 */
#ifdef NUM238
	cout<<"decltype和auto在处理顶层const方面存在差异。"<<endl;
	int i = 0, &r = i; 
	//same
	auto a = i; 
    decltype(i) b = i; 
	// different 
    auto c = r;  
    decltype(r) d = i; 
#endif
/* 2.39 */
#ifdef NUM239
	cout<<"Error message: [Error] expected ';' after struct definition"<<endl;
#endif
/* 2.40 */
#ifdef NUM240
	struct Sale_date{
		string bookISBN;
		string bookName;
		unsigned units_sold = 0;
		double price  = 0.0;
		double revenue = 0.0;
	}
#endif
/* 2.41 */
#ifdef NUM241
/* 1.5.1*/
	struct Sale_date{
		string bookNo;
		unsigned units_sold;
		double revenue;
	};
	Sale_date book;
	double price;
	cin >> book.bookNo >> book.units_sold >> price;
	book.revenue = book.units_sold * price;
	cout << book.bookNo <<" "<<book.units_sold<<" "<<book.revenue<<endl;
/* 1.5.2*/
	Sale_date book1, book2;
	double price1, price2;
	cin >> book.bookNo >> book.units_sold >> price1;
	cin >> book.bookNo >> book.units_sold >> price2;
	book1.revenue = book1.units_sold * price1;
	book2.revenue = book2.units_sold * price2;
	if(book1.bookNo == book2.bookNo){
		unsigned totalCnt = book1.units_sold + book2.units_sold;
		double totalRevenue = book1.revenue + book2.revenue;
		cout<< book1.bookNo <<" "<<totalCnt<<" "<<totalRevenue<<" ";
		if(totalCnt != 0)
			cout <<totalRevenue/totalCnt<<endl;
		else 
			cout <<"no sales."<<endl;
	}else{
		cout<<"Must be the same ISBN."<<endl;
		return -1;
	}
#endif
	return 0;
}

参考资料:

c++ primer中文版第五版,电子工业出版社。
c++ primer第四版习题解答,人民邮电出版社。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值