本文答案,部分參考於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
思維導圖
這一章的導圖
如果這篇文章對你有張幫助的話,可以用你高貴的小手給我點一個免費的贊嗎
相信我,你也能變成光.
如果你有任何建議,或者是發現了我的錯誤,歡迎評論留言指出.