C++ 習題整理(1)

習題2.1

int、long 和short 類型之間有什麼差別? 

【解答】 

它們的最小存儲空間不同,分別爲16 位、32 位和16 位。一般而言,short 類型爲半個機器字(word)長,int 類型爲一個機器字長,而long 類型爲一個或兩個機器字長(在32 位機器中,int 類型和long 類型的字長通常是相同的)。因此,它們的表示範圍不同。


習題2.2 
unsigned 和signed 類型有什麼差別? 

【解答】 
前者爲無符號類型,只能表示大於或等於0 的數。後者爲帶符號類型,可以表示正數、負數和0。


習題2.3 
如果在某機器上short 類型佔16 位,那麼可以賦給short 類型的最大數是什麼?unsigned short 類型的最大數又是什麼? 

【解答】 
若在某機器上short 類型佔16 位,那麼可以賦給short 類型的最大數是215-1,即32767;而unsigned short 類型的最大數爲216-1,即65535。


習題2.4 
當給16 位的unsigned short 對象賦值100000 時,賦的值是什麼? 

【解答】 34464。 
100000 超過了16 位的unsigned short 類型的表示範圍,編譯器對其二進制表示截取低16 位,相當於對65536 求餘(求模,%),得34464。

習題2.5 
float 類型和double 類型有什麼差別? 【解答】 

二者的存儲位數不同(一般而言,float 類型爲32 個二進制位,double 類型爲64 個二進制位),因而取值範圍不同,精度也不同(float 類型只能保證6 位有效數字,而double 類型至少能保證10 位有效數字)。


習題2.6 
要計算抵押貸款的償還金額,利率、本金和付款額應分別選用哪種類型?解釋你選擇的理由。
 

【解答】 
利率可以選擇float 類型,因爲利率通常爲百分之幾。一般只保留到小數點後兩位,所以6 位有效數字就足以表示了。本金可以選擇long 類型,因爲本金通常爲整數。long 類型可表示的最大整數一般爲231-1(即2147483647),應該足以表示了。付款額一般爲實數,可以選擇double 類型,因爲float 類型的6 位有效數字可能不足以表示。


習題2.7 
解釋下列字面值常量的不同之處。

(a) 'a',L'a',"a",L"a" 
(b) 10,10u,10L,10uL,012,0xC 

(c) 3.14,3.14f,3.14L 

【解答】 
'a'爲char 型字面值,L'a'爲wchar_t 型字面值,"a"爲字符串字面值,L"a"爲寬字符串字面值。

 (b) 10,10u,10L,10uL,012,0xC 
10 爲int 型字面值,10u 爲unsigned 型字面值,10L 爲long 型字面值,10uL爲unsigned long 型字面值,012 爲八進制表示的int 型字面值,0xC 爲十六進制表示的int 型字面值。 
(c) 3.14,3.14f,3.14L 

3.14 爲double 型字面值,3.14f 爲float 型字面值,3.14L 爲long double 型字面值。


習題2.8 
確定下列字面值常量的類型: (a) –10 (b) -10u (c) -10. (d) -10e-2 

【解答】 (a) int 型 
(b) unsigned int 型 (c) double 型 (d) double 型


習題2.9 
下列哪些(如果有)是非法的?

 (a) "Who goes with F\145rgus?\012" 

(b) 3.14e1L

 (c) "two" L"some" 

(d) 1024f 

(e) 3.14UL 

(f) "multiple line 

comment" 

【解答】 
 (c) 非法。因爲字符串字面值與寬字符串字面值的連接是未定義的。 
(d) 非法。因爲整數1024 後面不能帶後綴f。 (e) 非法。因爲浮點字面值不能帶後綴U。 
(f) 非法。因爲分兩行書寫的字符串字面值必須在第一行的末尾加上反斜線。


習題2.10 
使用轉義字符編寫一段程序,輸出2M,然後換行。修改程序,輸出2,跟着一 
個製表符,然後是M,最後是換行符。 

【解答】 
輸出2M、然後換行的程序段: // 輸出"2M"和換行字符 std::cout << "2M" << '\n'; 修改後的程序段: 
// 輸出'2', '\t', 'M'和換行字符 
std::cout << '2' << '\t' << 'M' << '\n'; 

習題2.11 
編寫程序,要求用戶輸入兩個數——底數(base)和指數(exponent),輸出 底數的指數次方的結果。
 

【解答】 

#include <iostream> int main() { 
// 局部對象 int base, exponent; long result=1; 
// 讀入底數(base)和指數(exponent) 
std::cout << "Enter base and exponent:" << std::endl; std::cin >> base >> exponent; if (exponent < 0) { 
std::cout << "Exponent can't be smaller than 0" << std::endl; return -1; } 
if (exponent > 0) { // 計算底數的指數次方 
for (int cnt = 1; cnt <= exponent; ++cnt) result *= base; } 
std::cout << base 
<< " raised to the power of " << exponent << ": " << result << std::endl; return 0; }


習題2.12 
區分左值和右值,並舉例說明
。 

【解答】 
左值(lvalue)就是變量的地址,或者是一個代表“對象在內存中的位置”的表達式。右值(rvalue)就是變量的值,見2.3.1 節。變量名出現在賦值運算符的左邊,就是一個左值;而出現在賦值運算符右邊的變量名或字面常量就是一個右值。 例如: val1=val2/8 
這裏的val1 是個左值,而val2 和8 都是右值。


習題2.13 
舉出一個需要左值的例子。

 【解答】 
賦值運算符的左邊(被賦值的對象)需要左值,見習題2.12


習題2.14

下面哪些(如果有)名字是非法的?更正每個非法的標識符名字。 
(a) int double = 3.14159; (b) char _; (c) bool catch-22; (d) char 1_or_2 ='1'; (e) float Float = 3.14f; 

【解答】 
(a) double 是C++語言中的關鍵字,不能用作用戶標識符,所以非法。此語句可改爲:double dval = 3.14159;。 (c) 名字catch-22 中包含在字母、數字和下劃線之外的字符“-”,所以非法。可將其改爲:catch_22;。 
(d) 名字1_or_2 非法,因爲標識符必須以字母或下劃線開頭,不能以數字開頭。可將其改爲:one_or_two;。


習題2.15 
下面兩個定義是否不同?有何不同? int month = 9, day = 7; int month =09, day = 07; 
如果上述定義有錯的話,那麼應該怎樣改正呢? 

【解答】 
這兩個定義不同。前者定義了兩個int 型變量,初值分別爲9 和7;後者也定義了兩個int 型變量,其中day 被初始化爲八進制值7;而month 的初始化有錯:試圖將month 初始化爲八進制值09,但八進制數字範圍爲0~7,所以出錯。可將第二個定義改爲:int month =011, day = 07;


習題2.16 
假設calc 是一個返回double 對象的函數。下面哪些是非法定義?改正所有的非法定義。 

(a) int car = 1024, auto = 2048; 

(b) int ival = ival; 
(c) std::cin >> int input_value;

 (d) double salary = wage = 9999.99; 

(e) double calc = calc(); 【解答】 
(a) 非法:auto 是關鍵字,不能用作變量名。使用另一變量名,如aut 即可更正。 
(c) 非法:>>運算符後面不能進行變量定義。改爲:int input_value;std::cin >> input_value; 
(d) 非法:同一定義語句中不同變量的初始化應分別進行。改爲:double salary = 9999.99, wage = 9999.99; 注意,(b)雖然語法上沒有錯誤,但這個初始化沒有實際意義,ival 仍是未初始化的。

習題2.17 

下列變量的初始值(如果有)是什麼? std::string global_str; int global_int; int main() { 
int local_int; std::string local_str; // ... return 0; } 

【解答】 
global_str 和local_str 的初始值均爲空字符串,global_int 的初始值爲0,local_int 沒有初始值。


習題2.18 
解釋下列例子中name 的意義: extern std::string name; 
std::string name("exercise 3.5a"); extern std::string name("exercise 3.5a"); 

【解答】 
第一條語句是一個聲明,說明std::string 變量name 在程序的其他地方定義。 
第二條語句是一個定義,定義了std::string 變量name,並將name 初始化爲"exercise 3.5a"。 
第三條語句也是一個定義,定義了std::string 變量name,並將name 初始化爲"exercise 3.5a",但這個語句只能出現在函數外部(即,name 是一個全局變量)。


習題2.19 
下列程序中j 的值是多少? 

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

【解答】 
j 的值是100。j 的賦值所使用到的i 應該是main 函數中定義的局部變量i,因爲局部變量的定義會屏蔽全局變量的定義。


習題2.20 
下列程序段將會輸出什麼?

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

【解答】 輸出爲: 100 45 
for 語句中定義的變量i,其作用域僅限於for 語句內部。輸出的i 值是for 語句之前所定義的變量i 的值。


習題2.21 
下列程序合法嗎? 

int sum = 0; 
for (int i = 0; i != 10; ++i) sum += i; 
std::cout << "Sum from 0 to " << i << " is " << sum << std::endl; 

【解答】 
不合法。因爲變量i 具有語句作用域,只能在for 語句中使用,輸出語句中使用i 屬非法。



習題2.22 
下列程序段雖然合法,但是風格很糟糕。有什麼問題呢?怎樣改善? 
for (int i = 0; i < 100; ++i) // process i 

【解答】 
問題主要在於使用了具體值100 作爲循環上界:100 的意義在上下文中沒有體現出來,導致程序的可讀性差;若100 這個值在程序中出現多次,則當程序的需求發生變化(如將100 改變爲200)時,對程序代碼的修改複雜且易出錯,導致程序的可維護性差。改善方法:設置一個const 變量(常量)取代100 作爲循環上界使用,併爲該變量選擇有意義的名字。

習題2.23 
下列哪些語句合法?對於那些不合法的使用,解釋原因。 

(a) const int buf; 

(b) int cnt = 0; const int sz = cnt; 

(c) cnt++; sz++; 

【解答】 
(a) 不合法。因爲定義const 變量(常量)時必須進行初始化,而buf 沒有初始化。 

(b) 合法。 
(c) 不合法。因爲修改了const 變量sz 的值。

習題2.24 
下列哪些定義是非法的?爲什麼?如何改正?

 (a) int ival = 1.01; 

(b) int &rval1 = 1.01;

 (c) int &rval2 = ival;

 (d) const int &rval3 = 1; 

【解答】 
(b)非法。因爲rval1 是一個非const 引用,非const 引用不能綁定到右值,而1.01 是一個右值。可改正爲:int &rval1 = ival;(假設ival 是一個已定義的int 變量)


習題2.25 
在習題2.24 給出的定義下,下列哪些賦值是非法的?如果賦值合法,解釋賦值的作用。 
(a) rval2 = 3.14159; (b) rval2 = rval3; (c) ival = rval3; (d) rval3 = ival; 

【解答】 
(d)非法。因爲rval3 是一個const 引用,不能進行賦值。合法賦值的作用: 
(a)將一個double 型字面值賦給int 型變量ival,發生隱式類型轉換,ival 得到的值爲3。 (b)將int 值1 賦給變量ival。 (c)將int 值1 賦給變量ival。


習題2.26 
(a)中的定義和(b)中的賦值存在哪些不同?哪些是非法的?

 (a) int ival = 0; (b) ival = ri; const int &ri = 0; ri = ival; 

【解答】 
int ival = 0; 定義ival 爲int 變量,並將其初始化爲0。 const int &ri = 0; 定義ri 爲const 引用,並將其綁定到右值0。 
ival = ri; 將0 值賦給ival。 
ri = ival; 試圖對ri 賦值,這是非法的,因爲ri 是const 引用,不能賦值。 


題2.27 
下列代碼輸出什麼?

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

【解答】 輸出:

10 10 
ri 是i 的引用,對ri 進行賦值,實際上相當於對i 進行賦值,所以輸出i 和ri 的值均爲10。


習題2.28 
編譯以下程序,確定你的編譯器是否會警告遺漏了類定義後面的分號。 class Foo { // empty 
} // Note: no semicolon int main() { return 0; } 
如果編譯器的診斷結果難以理解,記住這些信息以備後用。
 

【解答】 
在筆者所用的編譯器中編譯上述程序,編譯器會給出如下錯誤信息: 
error C2628: 'Foo' followed by 'int' is illegal (did you forget a ';'?)(第4 行) 
warning C4326: return type of 'main' should be 'int or void' instead of'Foo' (第5 行) 
error C2440: 'return' : cannot convert from 'int' to 'Foo' (第6 行) 
也就是說,該編譯器會對遺漏了類定義後面的分號給出提示。


習題2.29 
區分類中的public 部分和private 部分。 

【解答】 
類中public 部分定義的成員在程序的任何部分都可以訪問。通常在public 部分放置操作,以便程序中的其他部分可以執行這些操作。類中private 部分定義的成員只能被作爲類的組成部分的代碼(以及該類的友元)訪問。通常在private 部分放置數據,以對對象的內部數據進行隱藏。



習題2.30 
定義表示下列類型的類的數據成員: 

(a) 電話號碼  (b)地址 
(c) 員工或公司  (d)夢芭莎優惠券網裏面的文章 

【解答】 (a) 電話號碼 

class Tel_number { public:

//...對象上的操作 private: 
std::string country_number; std::string city_number; std::string phone_number; }; (b) 地址 class Address { public: 
//...對象上的操作 private: 
std::string country; std::string city; std::string street; std::string number; }; 
(c) 員工或公司 class Employee { public: 
// ...對象上的操作 private: std::string ID; std::string name; char sex; Address addr; Tel_number tel; }; 
class Company { public: 
// ...對象上的操作 private: 
std::string name; Address addr; Tel_number tel; }; 
(d) 某大學的學生 class Student { public: 
// ...對象上的操作 private: std::string ID; std::string name; char sex; 
std::string dept; // 所在系 

std::string major; Address home_addr; Tel_number tel; }; 
注意,在不同的具體應用中,類的設計會有所不同,這裏給出的只是一般性的簡單例子。


習題2.31 
判別下列語句哪些是聲明,哪些是定義,請解釋原因。 

(a) extern int ix = 1024  

(b) int iy

(c) extern int iz  

(d) extern const int &ri 

 【解答】 
(a)是定義,因爲extern 聲明進行了初始化。 (b)是定義,變量定義的常規形式。 (c)是聲明,extern 聲明的常規形式。 (d)是聲明,聲明瞭一個const 引用。


習題2.32 
下列聲明和定義哪些應該放在頭文件中?哪些應該放在源文件中?請解釋原因。 

(a) int var  
(b) const double pi = 3.1416; 

(c) extern int total = 255  
(d) const double sq2 = squt (2.0) 

 【解答】 
(a)、(c)、(d)應放在源文件中,因爲(a)和(c)是變量定義,定義通常應放在源文件中。(d)中的const 變量sq2 不是用常量表達式初始化的,所以也應該放在源文件中。 
(b)中的const 變量pi 是用常量表達式初始化的,應該放在頭文件中。參見2.9.1 節。


習題2.33 
確定你的編譯器提供了哪些提高警告級別的選項。使用這些選項重新編譯以前選擇的程序,查看是否會報告新的問題。 

【解答】 
在筆者所用的編譯器(Microsoft Visual C++ .NET 2003)中,在Project 菜單中選擇Properties 菜單項,在ConfigurationProperties→C/C++→General→Warning Level 中可以選擇警告級別。

















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