C++Primer_課後習題第四章

本文答案,部分參考於C++ Primer 習題集

第一章答案

第一章

第二章答案

第二章

第三章答案

第三章

4.1

結果是105

(5+((10*20)/2))=(5+(200/2))=5+100=105

4.2

*(vec.begin())
*(vec.begin())+1

4.3

這題參考與答案

正如題目所說,C++語言規定了非常少的二元運算符(邏輯與運算符,邏輯或運算符,逗號運算符)的求值順序,其他絕大多數二元運算符的求值順序並沒有明確規定,這樣做提高了代碼的生成效率,但是可能引發潛在的缺陷.

關鍵是缺陷的風險有多大?我們知道,對於沒有執行順序的運算符來說,如果表達式指向並修改了同一個對象,將會引發錯誤併產生未定義的行爲;而如果運算對象彼此無關,它們既不會改變同一對象的狀態也不執行IO任務,則函數的調用順序不受限制.

就作者的觀點而言,這樣的做法在一定程度上是可以接受的,前提是在編寫程序時注意以下兩點:

①	搞不明白的時候用括號()

②	一旦改變了某個運算對象的值,在表達式的其他地方就不要再使用這個運算對象了.

4.4

((12/3)*4)+(5*15)+((24%4)/2)

測試程序

#include<iostream>
#include<vector>
#include<cctype>
#include<string.h>
using namespace std;

int main(void) {
	int a=0;
	a=12/3*4+5*15+24%4/2;
	cout<<a;
	return 0;
}

4.5

(a)

-86

(b)

-16

©

0

(d)

-2

4.6

a%2==0

4.7

溢出:是一種常見的算術運算cowu,因爲再計算機中存儲某種類型的內存空間有限,所以該類型的表示能力(範圍)也是有限的,當計算機的結果超過範圍時,就會產生未定義的數值,這種錯誤就叫溢出.

#include<iostream>
#include<vector>
#include<cctype>
#include<string.h>
using namespace std;

int main(void) {
	int i=2000*2000*2000;
	int j=-100000*2000000;
	int z=-999999*888888*7888888;
	return 0;
}

4.8

參考答案

對於邏輯與運算符來說,當且僅當兩個運算對象都爲真時,結果爲真;對於邏輯或運算符來說,只要兩個運算對象中的一個爲真結果就爲真

邏輯與運算符和邏輯或運算符都是先求左側運算對象的值,再求右側運算對象的值,當且僅當左側運算對象無法確定表達式的結果時,纔會計算右側運算對象的值.

這種策略就是短路求值,其策略是:對於邏輯與運算來說,當且僅當左側運算對象爲真才計算右側運算對象,對於邏輯或運算符來說,當且僅當左側運算對象爲假時,才計算右測運算對象

PS:邏輯與運算和邏輯或運算符,是C++裏面僅有的幾個規定了求值順序的運算符,相等性運算符的兩個運算對象都需要值,C++沒有規定求值順序.

4.9

	const char *cp = "Hello World";
	if(cp && *cp){
		cout<<"True";
	}

邏輯或運算符,先計算左邊的,

cp是一個char指針,if裏面的cp就是判斷這個指針是不是一個空指針,如果這個指針不是空指針,

我們再來判斷 *cp ,就是判斷cp指針指向的那個字符串式不是一個空串.

這個可以看到,不是空指針,指向的也不是空串.那馬if裏面的內容爲true

,可以輸出

4.10

#include<iostream>
#include<vector>
#include<cctype>
#include<string.h>
using namespace std;

int main(void) {
	int t=0;
	while(cin>>t){
		if(t!=42)
			cout<<t<<endl;
		else
			break;
	}
	return 0;
}

4.11

if(a>b&&b>c&&c>d)

4.12

	//如果j<k 爲真  那麼就是i!=1   
	//如果j<k 爲假	那麼就是i!=0

4.13

(a)

d的值是3.0

i 的值是3

(b)

i 的值是3

d的值是3.5

4.14

第一條語句會報錯—賦值語句的左側運算符必須是右值

第二條語句語法上是正確的,但是語義可能不符

應該把= 改爲 ==

4.15

因爲類型不匹配.

我們可以改爲同一類型

或者把指針單獨賦值

例如:

	double dval;
	int ival,*pi;
	dval=ival=0;
	*pi=0;

4.16

	if((p=getPtr())!=0)
	if(i==1024)

4.17

答案就是P321頁的注意事項

一句話,前置版本可以節省空間和時間.

4.18

會出錯,這樣的話,我們無法輸出第一個元素,而且會輸出最後一個元素的下一個元素–也就是一個不存在的元素

因爲前置的是先加一再解的

4.19

(a)

看ptr的指向下一個對象的下一個地址是否有意義.

如果ptr指向的一個的整形變量,那就ptr++就是無意義的,但是在語義上是合法的.

如果ptr指向的是一個數組,而且指向的數組的下一個地址元素是有意義的,那麼ptr++也是有意義的.

如果ptr指向的是一個數組,而且指向的數組的下一個地址元素是⑤意義的,那麼ptr++就是非法的

但是在不會報錯,因爲 *ptr++返回的還是 *ptr的值,但是ptr會指向一個錯誤的地方

舉個例子

#include<iostream>
#include<vector>
#include<cctype>
#include<string.h>
using namespace std;

int main(void) {
	int a[3]={1,2,3},*ptr=0,b=0;
	//ptr = a;//這種情況是可以的
	//ptr = a+2;	//這種情況就不行了
	ptr = &b;	//這種情況也是不行的
	if(*ptr++){
		cout<<"True";
	}
	ptr = a;
	if(*ptr++){
		cout<<"True";
	}
	if(*ptr){
		cout<<"True";
	}
	
	return 0;
}

(b)

先執行ival++ 判斷 ival 的值是不是大於0 如果大於0

判斷 ival++完的值是不是大於0

如果都大於0 那麼表達式結果就爲0

©

先求出vec[ival]的值

在求vec[ival+1]的值

然後再比較

(b)和(c)的寫法都不太好

最好改爲

ival && (ival+1)
vec[ival]<=vec[ival+1]

4.20

(a)

是合法的,後置的遞增運算符的優先級高於解引用運算符,其含義是解引用當前迭代器所處位置的對象內容,然後把迭代器的位置向後移動一位.

(b)

是非法的,解引用iter 得到vector對象當前的元素,結果是一個string,顯然string沒有後置遞增操作.

©

是非法的,解引用運算符的優先級低於點運算符,所以該式子先計算iter.empty(),迭代器是沒有empty函數的

(d)

合法的

(e)

非法的.

該式子先解引用iter,得到迭代器當前所指的元素,結果是一個string,顯然string沒有後置遞增操作.

(f)

合法的

iter+±>empty() 等於 (*iter++).empty()

就是引用迭代器當前對象的內容得到一個字符串,再判斷它是不是空,然後在向下移動一位迭代器.

4.21

#include<iostream>
#include<vector>
#include<cctype>
#include<string.h>
using namespace std;

int main(void) {
	vector<int> arr{1,2,3,4,5,6,7,8,9,10};
	for(auto &t:arr){
		t=(t%2 == 1?t*2:t);
	}
	for(auto t:arr){
		cout<<t<<endl;
	}
	return 0;
}

4.22

只使用條件運算符

#include<iostream>
#include<vector>
#include<cctype>
#include<string>
using namespace std;

int main(void) {
	int grade ;
	cin>>grade;
	string finalgrade;
	finalgrade = (grade>=90)? "high pass":(grade>=75)?"pass":(grade>=60)?"low pass":"fail";
	cout<<finalgrade;
	return 0;
}

使用if和else

#include<iostream>
#include<vector>
#include<cctype>
#include<string>
using namespace std;

int main(void) {
	int grade ;
	cin>>grade;
	string finalgrade;
	if(grade>=90){
		finalgrade="high pass";
	}
	else if(grade>=75){
		finalgrade="pass";
	}
	else if(grade>=60){
		finalgrade="low pass";
	}
	else{
		finalgrade="fail";
	}
	cout<<finalgrade<<endl;
	return 0;
}

if 和else的更加容易理解

但是條件運算符的代碼更加的簡潔.

各有利弊吧.

4.23

	string s="word";
	string p1=s+s[size()-1]=='s'?"":"s";

沒有給條件運算符加上括號.

(s+s[size()-1])=='s'?"":"s";

這是非法的因爲加起來的東西是一個字符串,'s’是一個字符

正確的該法

	string s="word";
	string p1=s+(s[size()-1]=='s'?"":"s");

題目的原意

先判斷字符串s的最後一個字符是否是’s’,如果是,什麼也不做,如果不是,在s的末尾加一個字符’s’,我們應該添加括號強制限定運算符的執行順序.

4.24

finalgrade=((grade>90)?"high pass":(grade<60))?"fail":"pass";

4.25

在這裏插入圖片描述

4.26

C++規定,unsigned long int至少要佔32位,

但是unsigned int 最少只要佔16位,所以,可能會造成信息的丟失,會報錯.

4.27

(a)

3

(b)

7

©(d)

都是True

4.28

#include<iostream>
#include<vector>
#include<cctype>
#include<string>
using namespace std;

int main(void) {
	cout<<"類型名稱\t"<<"所佔空間"<<endl;
	cout<<"bool\t\t"<<sizeof(bool)<< endl;
	cout<<"char\t\t"<<sizeof(char)<<endl;
	cout<<"wchar_t\t\t"<<sizeof(wchar_t)<<endl;
	cout<<"char16_t\t\t"<<sizeof(char16_t)<<endl;
	cout<<"char32_t\t\t"<<sizeof(char32_t)<<endl;
	cout<<"short\t\t"<<sizeof(short)<<endl;
	cout<<"int\t\t"<<sizeof(int)<<endl;
	cout<<"long\t\t"<<sizeof(long)<<endl;
	cout<<"long long \t\t"<<sizeof(long long)<<endl;
	cout<<"float\t\t"<<sizeof(float)<<endl;
	cout<<"double\t\t"<<sizeof(double)<<endl;
	cout<<"long double\t\t"<<sizeof(long double)<<endl;
	return 0;
}

我的編譯環境,的結果是

類型名稱        所佔空間
bool            1
char            1
wchar_t         2
char16_t                2
char32_t                4
short           2
int             4
long            4
long long               8
float           4
double          8
long double             12
請按任意鍵繼續. . .

4.29

代碼

#include<iostream>
#include<vector>
#include<cctype>
#include<string>
using namespace std;

int main(void) {
	int x[10],*p=x;
	cout<<sizeof(x)/sizeof(*x)<<endl;
	cout<<sizeof(p)/sizeof(*p)<<endl;
	return 0;
}

輸出

10
1
請按任意鍵繼續. . .

解答

① sizeof(x)是對數組的所有的元素進行一個計算,然後相加,就相等於10個int相加

② sizeof(*x)是解引用,這裏的x是指針,解引用指針,就是一個int,所以相除爲10

③ sizeof§ p是一個指針,求的就是指針所佔空間的大小

④ sizeof(*p) 就是指針p指向的對象,也就是一個int,所以相除爲1

4.30

(a)

題目的含義

(sizeof(x))+y

我們需要改成 sizeof(x+y)

(b)

題目的含義就是

sizeof(p->men[i])

因爲->優先級比sizeof的優先級大

©

題目的順序

(sizeof(a))+b

我們應該改爲

sizeof(a+b)

(d)

不用假括號

4.31

就這題來講,沒有影響

4.32

就循環講一下

就是ix要不能等於5

ptr要沒有指向最後一個數,

循環每次都只增ix和ptr的指向

4.33

someValue 不等於0的話,x,y都加一

someValue 等於0的話,x,y都減一

4.34

(a)

fval float轉換成bool

(b)

fval + ival 自動轉換爲float,最後在賦值的時候,又轉換成double

©

ival*cval cval轉換成int 然後相加的時候,轉換成double

4.35

都發生了

(a)

‘a’ +3 bool 轉換成int 然後賦值的時候在轉換爲char

(b)

ival 轉換爲double 相乘的結果也是double,ui轉換爲double相減,最後在轉換爲float

©

ui轉換爲flaot 最後結果轉換爲double

(d)

ival轉換爲float和fval相加的結果轉換爲double

最後相加完的結果轉換爲char

然後賦值

4.36

i*=static_cast<int>(d);

4.37

	pv=static_cast<void*>(ps);		//const_cast<string*>(ps)
	i=static_cast<int>(*pc);
	pv=static_cast<void*>(&d);
	pc=static_cast<char*>(pv);

4.38

就是把

j/i 的值轉換成double

思維導圖

這一章的導圖

在這裏插入圖片描述

如果這篇文章對你有張幫助的話,可以用你高貴的小手給我點一個免費的贊嗎

相信我,你也能變成光.

在這裏插入圖片描述

如果你有任何建議,或者是發現了我的錯誤,歡迎評論留言指出.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章