




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
練習(xí)2.16語言不應(yīng)該支持所謂的Type-constraint(類型約束)語法。有三個(gè)理由:
它會(huì)使templates更復(fù)雜。
無論如何用戶總是能夠檢驗(yàn)Type是否提供了“得以順利將此template實(shí)例化”的必要函數(shù);
如果他們遺漏了,編譯器會(huì)對(duì)此實(shí)例化行為發(fā)出錯(cuò)誤訊息,指出某個(gè)函數(shù)有所謂的隱式約束
(implicitconstraint),而不只是發(fā)出錯(cuò)誤信息說這個(gè)template的實(shí)例化是錯(cuò)誤的。
請(qǐng)看L&L練習(xí)2.16出現(xiàn)的腳注,其中所描述的習(xí)慣。
練習(xí)2.17這是正確的語意。另一種做法是在classtemplate被產(chǎn)生出來時(shí)即檢驗(yàn)此一template的所有可能
用法。這會(huì)造成編譯時(shí)間的嚴(yán)重浪費(fèi)。不過此種語意的缺點(diǎn)是,以某個(gè)類型將template實(shí)例化,在程
序A中也許可以有效運(yùn)作,在程序B中也許不能成功,視被調(diào)用的函數(shù)而定。
練習(xí)2.18以下事情有可能在這個(gè)函數(shù)中出現(xiàn)錯(cuò)誤:
file_name可能是個(gè)空字符串(emptystring)0
ifstreamconstructor可能無法打開文件,即使file_name是一個(gè)有效字符串。
文件起始處可能并不內(nèi)含一個(gè)int數(shù)值。
elem_cnt可能收到一個(gè)不正確的值:太大、或0、或負(fù)值。
allocate_array()為elem_cnt個(gè)元素分配空間,可能失敗。
while循環(huán)讀到太多元素;這個(gè)循環(huán)會(huì)在遇到EOF(或讀取int失敗)時(shí)結(jié)束,但它并未考慮pi
所指數(shù)組的大小。
sort__array()會(huì)對(duì)pi所指向的數(shù)組排序,該數(shù)組假想有elem_cnt個(gè)元素。但是while循
環(huán)可能在讀入elem_cnt個(gè)元素之前就結(jié)束,因?yàn)檩斎攵说膇nts個(gè)數(shù)不足,并因而造成數(shù)組的
剩余部分沒有初值。
sort_array()可能會(huì)收到一個(gè)無效指針pi,因?yàn)榇颂幉⑽礄z查allocate_array()的返回值:
這個(gè)錯(cuò)誤可能會(huì)造成程序在循環(huán)內(nèi)當(dāng)?shù)簟?/p>
練習(xí)2.19int*alloc_and_init(stringfile_name)
(
ifstreaminfile(file_name.c_str());
intelem_cnt;
infile>>elem_cnt;
try(
int*pi=allocate_array(elem_cnt);
intelem;
intindex=0;
while(cin>>elem)
pi[index++]=elem;
sort_array(pi,elem_cnt);
register_data(pi);
returnpi;
)
catch(constnoMem&n){
cout<<nallocate_array()error"<<n<<endl;
}
catch(inti){
cout<<nsort_array()error"<<i<<endl;
)
catch(conststring&s){
cout<<nregister_data()error'*<<s<<endl;
)
)
練習(xí)2.20int*alloc_and_init(stringfile_name)
(
try(
ifstreaminfile(file_name.c_str());
if(Jinfile)
throw"cannotopenfileH;
intelem_cnt;
infile>>elem_cnt;
if(!infileIIelem_cnt<=0)
throw"invalidelem_cntH;
int*pi=allocate_array(elem_cnt);
intelem;
intindex=0;
while(cin>>elem){
if(index>=elem_cnt)
throw"toomanyinputelements";
pi[index++]=elem;
}
sort_array(pi,index);
register_data(pi);
returnpi;
)
catch(constnoMem&n){
cout<<nallocate_array()errorn<<n<<endl;
throw;//重新丟出(rethrow)exception以便通知用戶
)
catch(inti){
cout<<nsort_array()errorn<<i<<endl;
throw;
)
catch(conststring&s){
cout<<nregister_data()error"<<s<<endl;
throw;
)
catch(constchar*s){
cout<<"error:“<<s<<endl;
throw;
)
)
練習(xí)2.21a.利用“前置修飾詞表示法”來訪問Exercisenamespace中的類型定義。
b.利用usingdeclaration來訪問類型定義。
c.利用namespace別名機(jī)制(aliasmechanism)。
d.利用usingdirectiveo
a.利用前置修飾詞表示法來訪問Exercisenamespace中的類型定義。
intmain()
(
//使用修飾詞表示法(*qualifiednamenotation*)
constintsize=1024;
Exercise::Array<Exercise::String>as(size);
Exercise::List<int>il(size);
//...
Exercise::Array<Exercise::String>*pas=
newExercise::Array<Exercise::String>(as);
Exercise::List<int>*pil=newExercise::List<int>(il);
Exercise::print(*pas);
}
b.利用usingdeclaration來訪問類型定義。
intmain()
(
//使用,usingdeclaration,
usingExercise::String;
usingExercise::Array;
usingExercise::print;
usingExercise::List;
constintsize=1024;
Array<String>as(size);
List<int>il(size);
〃…
Array<String>*pas=newArray<String>(as);
List<int>*pil=newList<int>(il);
print(*pas);
)
c.利用namespace的別名機(jī)制(aliasmechanism)。
intmain()
{
//使用namespacealias
namespaceE=Exercise;
練習(xí)2.22constintsize=1024;
E::Array<E::String>as(size);
E::List<int>il(size);
//...
E::Array<E::String>*pas=newE::Array<E::String>(as);
E::List<int>*pil=newE::List<int>(il);
E::print(*pas);
)
d.利用usingdirectiveo
intmain()
//使用,usingdirective'
usingnamespaceExercise;
constintsize=1024;
Array<String>as(size);
List<int>il(size);
//...
Array<String>*pas=newArray<String>(as);
List<int>*pil=newList<int>(il);
print(*pas);
)
練習(xí)2.22(a)vector<string>svecl(pals,pals+5);
svecl是一個(gè)由strings組成的vector,并以字符串所組成的數(shù)組pals作為初值。
(b)vector<int>ivecl(10);
ivecl是個(gè)vector,擁有10個(gè)ints,每一個(gè)都被初始化為0。
(c)vector<int>ivec2(10,10);
ivec2是一個(gè)vector,擁有10個(gè)ints,每一個(gè)都被初始化為10。
(d)vector<string>svec2(svecl);
svec2是一個(gè)vector,并以vectorsvecl作為初值。
(e)vector<double>dvec;
dvec是一個(gè)空的vector,內(nèi)部元素的類型是doubles。
練習(xí)2.23template<classelemType>
elemType
min(constvector<elemType>&vec);
下面是完整的程序:
#include<iostream>
#include<vector>
usingnamespacestd;
template<classelemType>
elemTypemini(constvector<elemType>&vec)
(
elemTypeminimum;
if(vec.size()>=1)
minimum=vec[0];
else
throw"Emptyvector-index";
for(inti=1;i<vec.size();i++)
if(vec[i]<minimum)
minimum=vec[i];
returnminimum;
)
練習(xí)2.23template<classelemType>
elemTypemin2(constvector<elemType>&vec)
vector<elemType>::const_iteratoriter=vec.begin();
elemTypeminimum;
if(iter<vec.end())
minimum=*iter;
else
throw"Emptyvector-iteratorn;
for(++iter;iter<vec.end();++iter)
if(*iter<minimum)
minimum=*iter;
returnminimum;
)
intmain()
intarray[]={9,4,5,6,1,3,7,8,2Z0};
vector<int>a(array,array+10);
cout<<"shouldbe0:n<<mini(a)<<endl;
cout<<"shouldbe0:n<<min2(a)<<endl;
vector<int>b(array,array+9);
cout<<"shouldbe1:“<<mini(b)<<endl;
cout<<"shouldbe1:“<<min2(b)<<endl;
vector<int>c;
try(
cout<<"shouldbel:n<<mini(c)<<endl;
cout<<"shouldbel:n<<min2(c)<<endl;
catch(char*s){
cerr<<"Exception:n<<s<<endl;
return0;
)
其中函數(shù)mini()和min2()十分類似,都使用for循環(huán),都在vector成空的時(shí)候丟出?個(gè)
exceptionomini()使用索引法:
for(inti=1;i<vec.size();i++)
if(vec[i]<minimum)
minimum=vec[i];
min2()使用iterator0兩者的參數(shù)都是?個(gè)constvector<elemType>&vec,所以我們不能使
用截至目前我們所見的?般性iterator。我們必須改用const_iterator(見L&L,12.4節(jié)):
for(++iter;iter<vec.end();++iter)
if(*iter<minimum)
minimum=*iter;
我們使用解引用(dereference)operator*來取用vector內(nèi)的數(shù)據(jù)。
主:程序以數(shù)組array作為vectora的初值:
intarray[]={9,4,5,6,1,3,7,8,2,0);
vector<int>a(array,array+10);
然后調(diào)用函數(shù)mini。和min2()?獲得的結(jié)果相同。我們也試了另一個(gè)vectorb,以數(shù)組的前九
個(gè)元素作為初值,并以一個(gè)空的vectorc練習(xí)exception處理機(jī)制。
練習(xí)3.1文字常量'a'表示單一字符a(類型為char。L,a'也表示單?字符a,但其類型為wchar_t,
因?yàn)榍皩?dǎo)詞L代表“寬字符”。
文字常量"a"和L"a"都是字符串,內(nèi)含單?一字符a和一個(gè)null字符(或是null寬字符)。
"a"的類型是“常量字符所形成的數(shù)組”,L"a"的類型則是“常量寬字符所形成的數(shù)組”。
(b)10,10u,10L,10uL,012,OxC
以上全都表示十進(jìn)制整數(shù)常量10。其中10,012和OxA的類型都是int,因?yàn)樗鼈儧]有任何修
飾詞。012的前導(dǎo)詞0表示這是個(gè)八進(jìn)位常量,OxA的前導(dǎo)詞Ox則表示它是一個(gè)十六進(jìn)制常量。
10u的類型是unsignedint)10L的類型是long,10uL的類型是unsignedlong。
(c)3.14,3.14f,3.14L
這些浮點(diǎn)數(shù)文字常量的類型都不相同。沒有任何修飾詞的3.14,類型為double(雙精度,這是
預(yù)設(shè)類型)。3.14f表現(xiàn)的是單精度浮點(diǎn)數(shù),3.14L表現(xiàn)的是多精度浮點(diǎn)數(shù)。
第3章
練習(xí)3.2(c)合法,但是其結(jié)果未有定義,因?yàn)椤皩蓚€(gè)不同類型的字符串連接起來,其行為未有定義”
(L&L,
p.78;簡(jiǎn)體版p.64)。
(e)和(f)不合法。3.14UL之所以不合法是因?yàn)閁(unsigned)被施加于?個(gè)浮點(diǎn)數(shù)文字常量身上。
(f)字符串需要在第一行最后加上一個(gè)倒斜線,才能延續(xù)到第二行:
(f)"multipleline\
comment"
另一種做法是把分據(jù)兩行的單一長(zhǎng)字符串寫為兩個(gè)字符串:
(f)"multipleline”
"comment
練習(xí)3.3(d)和(e)是不合法的。
(d)doublesalary=wage=9999.99;
此處wage被使用之前未曾先定義過。修正做法之一是把兩個(gè)變量分開定義、設(shè)初值,像這樣:
doublesalary=9999.99,wage=9999.99;
(e)cin>>intinput_value;
使用cin時(shí)并不允許“同時(shí)定義變量”。正確的做法是先定義好變量,再將?個(gè)值讀入變量之中:
intinput_value;
cin>>input_value;
練習(xí)3.4所謂lvalue(左值),是變量的地址,或是某個(gè)“代表對(duì)象在內(nèi)存中的位置”的表達(dá)式。所謂rvalue
(右值),就是變量的值。見L&L,3.2.1節(jié)。
變量名稱如果出現(xiàn)在賦值(assignment)運(yùn)算符的左側(cè),它就是一個(gè)lvalue。變量名稱或文字常
量如果出現(xiàn)于賦值(assignment)運(yùn)算符的右側(cè),它就是?個(gè)rvalue。例如:
ivar=val+2;
此處的ivar是個(gè)lvalue,val和2都是rvalueso
練習(xí)3.5(a)externstringname;
stringname("exercise3.5a");
第一個(gè)句子,externstringname;是name的聲明,告訴編譯器說,name所代表的對(duì)象,其
類型為string。此行并未分配內(nèi)存。
第二個(gè)句子,stringname("exercise3.5a");是個(gè)定義,告訴編譯器說,name所代表的對(duì)
象的類型為string,并進(jìn)行內(nèi)存分配操作,同時(shí)設(shè)好初值。
(b)externvector<string>students;
vector<string>students;
第一個(gè)句子是students的聲明,告訴編譯器說其類型為,?個(gè)“由strings組成的vector”。
沒有分配任何內(nèi)存。
第二個(gè)句子是個(gè)定義,告訴編譯器說,students所代表的對(duì)象類型為“由strings組成的
vectorMo此行將分配內(nèi)存,并以vector的defaultconstructor進(jìn)行初值設(shè)定工作。string的
defaultconstructor不會(huì)被調(diào)用,因?yàn)関ector是空的。
練習(xí)3.6(a),(c),(d)和(e)無效。
(a)和(c)之所以無效,因?yàn)樗鼈兤髨D使用保留字。double和namespace都是保留字(關(guān)鍵字)。
(d)內(nèi)含一個(gè)無效的符號(hào),(e)的名稱以數(shù)字開頭。
以卜是修訂后的結(jié)果:
(a)doublepi=3.14159;
(c)stringnamespace_string;
(d)stringcatch_22;
(e)charone_or_two=11';
(e)char_l_or_2=*1*;//另一種做法
練習(xí)3.7兩個(gè)string對(duì)象都將藉由stringclass的defaultconstructor加以初始化。
global_int會(huì)被初始化為0,而不會(huì)被初始化(所以其初值可能是任意數(shù)值)。
Global(全局)變量和對(duì)象可被其它函數(shù)訪問:local(局部)變量和對(duì)象只在它們定義所在的塊
內(nèi)可見。見L&L,3.2.3節(jié)。
練習(xí)3.8
33
練習(xí)3.8該語句有誤,因?yàn)樗髨D將?個(gè)int*數(shù)值賦值給一個(gè)int對(duì)象。另?個(gè)錯(cuò)誤:pi3是個(gè)“指
針的指針”,其值為0,而解引用null指針會(huì)造成運(yùn)行時(shí)刻錯(cuò)誤。
(b)*pi2=*pi3;
該語句也有一個(gè)錯(cuò)誤,理由與(a)相同。
(c)ival=pi2;
道理相同,企圖將一個(gè)int*數(shù)值賦值給一個(gè)int對(duì)象,是錯(cuò)誤的行為。
(d)pi2=*pil;
該語句有誤,因?yàn)樗鼘?個(gè)int數(shù)值賦值給個(gè)int*對(duì)象。
(e)pil=*pi3;
此處pil被賦值為pi3所指內(nèi)容。這個(gè)操作是合法的。如果pi3并未指向一個(gè)有效地址,該
行會(huì)發(fā)生運(yùn)行時(shí)刻錯(cuò)誤,但行為不可預(yù)期。
(f)ival=*pil;
由于(e)會(huì)在運(yùn)行時(shí)刻失敗,所以pil未被適當(dāng)?shù)爻跏蓟?。?duì)一個(gè)未被正確初始化的指針進(jìn)行
解引用操作,會(huì)發(fā)生錯(cuò)誤。
如果此行之前的那些定義都成立,那么此行會(huì)將ival賦值給ival。這是因?yàn)閜il被初始化為
ival的地址,所以解引用pil會(huì)獲得ival的值,此值再被賦值給ival。
(g)pil=ival;
此行錯(cuò)誤,因?yàn)閜il的類型是int*,而ival的類型是int。
(h)pi3=&pi2;
此行正確,因?yàn)閜i3的類型是int**,而pi2的類型是int*,因此&pi2的類型也是int**。
練習(xí)3.9
上述第二行將指針pi前進(jìn)1,024個(gè)位置。如果pi是個(gè)int指針,那么在“int為32位”
的環(huán)境下就是前進(jìn)了4096個(gè)字節(jié)。如果pi最初指向一個(gè)有著適當(dāng)大小的數(shù)組(亦即ival2代表
該數(shù)組內(nèi)的某元素),那么這就不見得是個(gè)錯(cuò)誤。
練習(xí)3.10問題在于Pi2定義時(shí)并未指向一塊已獲分配的空間,而foobar()卻企圖對(duì)其參數(shù)所指的內(nèi)存
做寫入操作。本例中的pi2初值為0,所以foobar()試圖將1024寫入地址為0的內(nèi)存中。除非
指針被賦以?個(gè)實(shí)際值,否則運(yùn)行時(shí)刻的行為沒有定義。下面是修改方式之一:
intfoobar(int*pi){
if(pi){
*pi=1024;
return*pi;
練習(xí)3.11
35
}else{
return0;
}
}
intmain()
{
intival2=0;
intival=foobar(&ival2);
return0;
)
這次我們不再定義一個(gè)int指針,而是定義?個(gè)int對(duì)象ival2,并將其地址傳給foobar()。
問題真正的解決點(diǎn)是在foobar()中對(duì)pi的測(cè)試操作。任何人如果事先不知道指針是否有值,都應(yīng)
該先行測(cè)試,然后才對(duì)指針做操作。
練習(xí)3.11由于指針扮演如此突顯的角色,執(zhí)行時(shí)期的任何指針檢驗(yàn)操作都會(huì)導(dǎo)致不可接受的效率成本。編
譯時(shí)期的指針檢驗(yàn)工作很困難,因?yàn)橥鶡o法決定這些指針在執(zhí)行時(shí)期會(huì)有什么值。
程序員之間流傳著指針的某些使用準(zhǔn)則,包括:總是將指針初始化、不要無視編譯器發(fā)出的錯(cuò)誤
信息或警告信息如“強(qiáng)制轉(zhuǎn)換為指針變量(explicitcaststopointervariables)”等等。
練習(xí)3.12(a)charch="Thelong,windingroad";
這是錯(cuò)誤的,因?yàn)閏h是單個(gè)字符,卻被初始化為一個(gè)字符串。
(b)intival=&ch;
(c)char*pc=&ival;
以上兩行都不正確,因?yàn)樗鼈兤髨D以不兼容的數(shù)值作為變量的初值:把char*交給int,把int
*交給char*o
(d)stringst(&ch);
語法上正確。但是如果ch未被正確地初始化,st可能會(huì)有不如預(yù)期的結(jié)果。另一個(gè)重點(diǎn)是,
string(constchar*)constructor期望獲得一個(gè)以null為結(jié)束符號(hào)的char數(shù)組。
(e)pc=0;
正確。
(f)st=pc;
語法正確。執(zhí)行結(jié)果視pc的值而定。
(9)ch=pc[0];
語法正確。執(zhí)行結(jié)果視pc的值而定。
(h)pc=st;
(i)pc=*0*;
以上兩行都不正確,因?yàn)闆]有任何隱式轉(zhuǎn)換可以將string或constchar轉(zhuǎn)換為char
(j)st=&ival;
這一行也不正確,因?yàn)闆]有任何可接受的轉(zhuǎn)換行為可以將int*轉(zhuǎn)換為stringo
(k)ch=*pc;
語法正確。執(zhí)行結(jié)果視pc的值而定。
(1)*pc=ival;
以上操作將一個(gè)int數(shù)值賦值給一個(gè)char??赡軙?huì)發(fā)生上溢(overflow)情況。執(zhí)行結(jié)果視ival
和pc的值而定。
練習(xí)3.13第一個(gè)while循環(huán)會(huì)持續(xù)累加ent,直到st的值為0。如果st并不是從0開始起算,那么
循環(huán)會(huì)一直進(jìn)行,直到st的值爆掉(超過st的容量)為止。
第二個(gè)while循環(huán)會(huì)累加ent,直到st所指的值為0。如果st指向一個(gè)C-style字符串,
那么循環(huán)會(huì)持續(xù)進(jìn)行,直到字符串的尾端為止。
練習(xí)3.14這些程序都進(jìn)行1,000,000次循環(huán),循環(huán)內(nèi)對(duì)字符串做內(nèi)存分配、復(fù)制、比較、內(nèi)存釋放操作。
一開始,有一個(gè)基本字符串在循環(huán)之外獲得初值。循環(huán)之內(nèi)則決定基本字符串的長(zhǎng)度。在C-style版
本內(nèi),這長(zhǎng)度值用來分配?個(gè)新的char數(shù)組,并將基本字符串復(fù)制到該數(shù)組。class版本內(nèi)則定義
一個(gè)新字符串并以基本字符串作為初值。接下來基本字符串被拿來和新字符串比較,如有差異就將錯(cuò)
誤計(jì)數(shù)器加lo最后,C-style版明白釋放新字符串的空間,class版則依賴classdestructor完成內(nèi)存
釋放操作。
class版所花時(shí)間比較少,主要原因是字符串長(zhǎng)度系儲(chǔ)存于stringclass內(nèi),成為其成員之一。
當(dāng)C-style版調(diào)用strlen時(shí),整個(gè)字符串必須被走過一遍,才能知道其長(zhǎng)度。注意,在我的系統(tǒng)中,
class版比C-style版慢。某些系統(tǒng)在string身上使用referencecounting(引用計(jì)數(shù))技巧,那么就
會(huì)比較快。(譯注:關(guān)于“引用計(jì)數(shù)”技巧,可參考More助認(rèn)C++(ScottMeyers著,侯捷譯,
培生2000)的條款29)。
練習(xí)3.15加上某些可作用于子字符串身上的額外操作,可能會(huì)有益處。例如在一個(gè)字符串中搜尋子字符串,
以及對(duì)子字符串進(jìn)行替換、復(fù)制、比較或串接等操作。
其它有益的操作還包括大小寫轉(zhuǎn)換、文字轉(zhuǎn)為整數(shù)(atoiO)>文字轉(zhuǎn)為浮點(diǎn)數(shù)(atof())等等。
練習(xí)3.16?個(gè)可被修改的對(duì)象,類型為int。
(b)constintic;
一個(gè)固定不變(不可修改)的對(duì)象,類型為int。
(c)constint*pic;
pic是個(gè)指針,指向一個(gè)類型為int的常量對(duì)象。pic本身可被修改,但是它所指的對(duì)象內(nèi)容
不可修改。
(d)int*constcpi;
cpi是常量指針,指向?個(gè)類型為int的對(duì)象。cpi不可修改,但其所指對(duì)象可以修改。
(e)constint*constepic;
epic是常量指針,指向一個(gè)類型為int的常量對(duì)象。不論epic或是其所指對(duì)象都不可以修改。
(b),(d),和<e)都是不合法的定義,因?yàn)槌A繉?duì)象必須有初值。任何人如果企圖修改常量對(duì)象,
會(huì)引發(fā)錯(cuò)誤信息。
練習(xí)3.17合法。i不是常量,初值設(shè)定為-1。
(b)constintic=i;
合法。ic是常量,初值設(shè)定為i。之后無法修改其值。
(c)constint*pic=⁣
合法。pic是個(gè)指針,指向一個(gè)類型為int的常量對(duì)象。pic可被修改,但其所指對(duì)象是常量。
由于ic已有定義,所以上述初始化行為是合法的。
(d)int*constcpi=⁣
不合法。cpi是一個(gè)常量指針,指向int,但ic卻是個(gè)constinto
(e)constint*constepic=⁣
合法。此處epic是一個(gè)常量指針,指向constint,ic的類型也是constinto不論是epic
或其所指對(duì)象ic,都無法修改。
練習(xí)3.18(a)i=ic;
合法。i不是常量,所以可以被修改。
(b)pic=⁣
合法。pic不是常量,所以它可以被修改,不過它所指的對(duì)象的類型必須是constinto
(c)cpi=pic;
不合法。cpi是常量,所以它不可以被修改。
(d)pic=epic;
合法。pic不是常量,所以它可以被修改,但是它所指的對(duì)象的類型必須是constinto
(e)epic=⁣
不合法。epic是常量,所以不能被修改。
(f)ic=*cpic;
不合法。ic是常量,所以不能被修改。
練習(xí)3.19(b)intSrvall=1.01;
無效。能夠儲(chǔ)存文字常量者,必須是一個(gè)constreference0可修改如下:
constint&rvall=1.01;
(d)int&rval3=&ival;
無效。rval3的類型是int而非int★<,可修改如下:
int&rval3=ival;
或
int*const&rva13=Sival;
(f)int&rval4=pi;
無效。rval4的類型是int而非int可修改如下:
int*const&rval4=pi;
(h)int&*prvall=pi;
無效。一個(gè)“指向reference”的指針是不合法的??尚薷娜缦拢?/p>
int*&prvall=pi;
(j)constint&*prval2=&ival;
無效。?個(gè)“指向referencen的指針是不合法的??尚薷娜缦拢?/p>
int*const&prval2=&ival;
練習(xí)3.20(a)rvall=3.14159;
無效,因?yàn)槲淖殖A啃枰粋€(gè)constreference來容納。
(b)prvall=prval2;
無效,因?yàn)閜rvall和prva12都是“指向reference”的指針,而那是不合法的。
(c)prval2=rvall;
無效,因?yàn)閜rval2是?個(gè)“指向reference"的指針,而那是不合法的。
(d)*prval2=ival2;
無效,因?yàn)閜rval2是一個(gè)“指向reference的指針,而那是不合法的。
練習(xí)3.21第一個(gè)語句正確:它將ival的地址設(shè)給指針pi。
第二個(gè)語句錯(cuò)誤,因?yàn)槲覀儫o法將int*(ival的地址)轉(zhuǎn)換為constint(referenceri的
類型是constint)o
最后一個(gè)語句錯(cuò)誤,因?yàn)閞val未曾定義。
練習(xí)3.22(a)intia[buf_size];
不合法,因?yàn)閎uf_size不是一個(gè)常量。
(b)intia[get_size()];
不合法,因?yàn)間et_size()不是一個(gè)常量表達(dá)式。
(d)intia[2*7-14];
不合法,因?yàn)榉峙浯笮?的數(shù)組是錯(cuò)誤的行為。
(e)charst[11]=nfundamentaln;
不合法。沒有足夠的空間來放置字符串初值。應(yīng)該再多一個(gè)元素,用來放置字符串尾端的字
符。
練習(xí)3.23數(shù)組的索引從0開始。因此,ia的元素索引為0~9。但是for循環(huán)內(nèi)的索引碼卻是下
面是修改后的版本:
intmain(){
constintarray_size=10;
intia[array_size];
for(intix=0;i<array_size;++ix)
ia[ix]=ix;
//...
)
練習(xí)3.24(a)vector<vector<int>>ivec;
正確。
(b)vector<int>ivec={0,1,1,2,3,5,8};
不正確。這種初始化形式無法用于vector對(duì)象身上。
(c)vector<int>ivec(ia,ia+7);
正確。
(d)vector<string>svec=ivec;
不正確?!癷nt所組成的vector"無法轉(zhuǎn)換為“string所組成的vector"。
(e)vector<string>svec(10,string("nulln));
正確。
練習(xí)3.25boolis_equal(constint*ia,intia_sizezconstvector<int>&ivec)
inti=0;
for(vector<int>::const_iteratorit=ivec.begin();
it!=ivec.end();++it){
//如果到達(dá)數(shù)組尾端,不要再繼續(xù)前進(jìn)
if(i==ia_size)
break;
〃如果發(fā)現(xiàn)?個(gè)不同值,立刻返回
if(ia[i++]!=*it)
returnfalse;
}
returntrue;
)
下面是測(cè)試程序。
intmain()
constintasize=7;
intia6eq[6]=0,1,1,2,3,5};
intia6ne[6]=0z1,1,3,3Z5};
intia8eq[8]=0,1,1,2,3,5,8,13);
intia8ne[8]=0,lr1,2,3,5,9,13);
intiane[asize]1/1,1,2,3,5,8};
intia[asize]0,1,1,2,3,5,8);
vector<int>ivec(ia,ia+asize);
cout<<nis_equal(ia6eq,6,ivec):";
if(is_equal(ia6eq,6,ivec))
cout<<"equal\nn;
else
cout<<"notequal\nn;
cout<<nis_equal(ia6ne,6,ivec):**;
if(is_equal(ia6ne,6,ivec))
cout<<"equal\nn;
else
cout<<nnotequal\nn;
nH
cout<<is_equal(ia8eqz8,ivec):;
if(is_equal(ia8eq,8,ivec))
cout<<"equal\nn;
else
cout<<"notequal\nn;
cout<<nis_equal(ia8ne,8,ivec):H;
if(is_equal(ia8ne,8,ivec))
cout<<"equal\n*';
else
cout<<"notequal\n*';
cout<<"is_equal(ia,asize,ivec):n;
if(is_equal(ia,asize,ivec))
cout<<"equal\n*';
else
cout<<"notequal\nn;
cout<<nis_equal(iane,asize,ivec):n;
if(is_equal(iane,asize,ivec))
cout<<"equal\nH;
else
cout<<nnotequal\nH;
return0;
)
練習(xí)3.26我們知道那些重復(fù)的代碼涉及_size和.string的初始化行為。我將這些代碼抽取出來放進(jìn)
兩個(gè)privateoverloadedmemberfunctionsinit(),并在constructorsassignmentoperators內(nèi)的適
步地點(diǎn)放置適當(dāng)?shù)暮瘮?shù)調(diào)用。
首先,在Stringclass的private區(qū)段內(nèi)為新函數(shù)加上聲明:
private:
int_size;
char*_string;
voidinit(constchar*);
voidinit(constStrings);
共同的初始化程序代碼現(xiàn)在被我放進(jìn)兩個(gè)新函數(shù)內(nèi):
inlinevoid
String::init(constchar*s)
(
if(!s){
_size=0;
_string=0;
}else{
_size=strlen(s);
_string=newchar[__size+l];
strcpy(_string,s);
)
)
inlinevoid
String::init(constString&rhs)
{
_size=rhs._size;
if(!rhs._string)
_string=0;
else{
_string=newchar[_size+l];
strcpy(_stringzrhs,_string);
)
)
接下來更改constructors,以便調(diào)用initU):
inlineString::String()
(
init(0);
)
inlineString::String(constchar*s)
init(s);
}
inlineString::String(constString&rhs)
init(rhs);
)
assignmentoperators的修改方式極為類似:
inlineString&
String::operator=(constchar*s)
delete[]_string;
init(s);
return*this;
inlineStrings
String::operator=(constString&rhs)
if(this!=&rhs){
delete[]_string;
init(rhs);
return*this;
}
練習(xí)3.27修改方式非常直接易懂。首先為新字母加上對(duì)應(yīng)的計(jì)數(shù)器:
bCnt=0,dCnt=0,fCnt=0,sCnt=0,tCnt=0
接下來在switch語句中為這些輔音加上新的cases。我們還是需要為每?個(gè)輔音累加
notVowel的值。
case1b:caseB*:++bCnt;++notVowel;break;
case*d:caseD*:++dCnt;++notVowel;break;
case*f:caseF1:++fCnt;++notVowel;break;
case1s:caseS*:++sCnt;++notVowel;break;
case1t:caseT*:++tCnt;++notVowel;break;
最后,修改輸出部分以顯示輔音個(gè)數(shù)。下面是整個(gè)程序。
#include*'string.h
intmain()
intaCnt=0,eCnt=0ziCnt=0,oCnt=0,uCnt=0,
bCnt-0,dCnt=0,fCnt=0,sCnt=0,tCnt=0,
theCnt=0,itCnt=0,wdCnt=0,notVowel=0;
nn
Stringbuf,the(the)zit;
while(cin>>buf){
++wdCnt;
cout<<buf<<
if(wdCnt%12==0)
cout<<endl;
if(bufthe||buf“The”)
++theCnt;
elseif(bufitIIbufnItn)
++itCnt;
for(intix=0;i<buf.size();++ix){
switch(buf[ix]){
caseacaseA:++aCnt;break;
caseecaseE:++eCnt;break;
case1icaseI:++iCnt;break;
casecase0:++oCnt;break;
caseucaseU:++uCnt;break;
case*bcaseB:++bCnt;++notVowel;break;
case,dcaseD:++dCnt;++notVowel;break;
casecaseF:++fCnt;++notVowel;break;
casecaseS:++sCnt;++notVowel;break;
casecaseT:++tCnt;++notVowel;break;
default:++notVowel;break;
cout<<
<<Wordsread:“<<wdCnt<<
<<the/The:u<<theCnt<<n\n
<<it/It:"<<itCnt<<n\n\n
<<non-vowelsread:n<<notVowel<<*'\n
<<<<aCnt<<M\n
<<<<eCnt<<M\n
<<<<iCnt
<<o<<oCnt
<<u<<uCnt<<"\n\n
<<b<<bCnt
<<d<<dCnt?H\n
<<<<fCnt
<<<<sCnt
<<t<<tCnt<<endl;
return0;
練習(xí)3.28下面是其實(shí)現(xiàn)代碼:
inlineint
String::count(charch)const
intchCnt=0;
for(intix=0;i<_size;++ix)
if(_string[ix]ch)++chCnt;
returnchCnt;
我必須修改原先的程序以測(cè)試這一新函數(shù)。對(duì)于計(jì)算元音個(gè)數(shù)而言,這是非常缺乏效率的做法,
但這使我們得以拿兩種做法互相比較。
#include"string.h"
intmain()
(
intaCnt=0,eCnt=0,iCnt=0,oCnt=0,uCnt=0,
theCnt=0,itCnt=0,wdCnt=0;
Stringbuf,the("the"),it(nit");
while(cin>>buf){
++wdCnt;
cout<<buf<<**;
if(wdCnt%12==0)
cout<<endl;
if(buf==the||buf=="The")
++theCnt;
elseif(buf==itIIbuf==n11")
++itCnt;
aCnt+=buf.count(*a1);
aCnt+=buf.count(*A1);
eCnt+=buf.count(re');
eCnt+=buf.count(*E');
iCnt+=buf.count(Ti');
iCnt+=buf.count(*1');
oCnt+=buf.count(*o');
oCnt+=buf.count(*0,);
uCnt+=buf.count(1u');
uCnt+=buf.count(1U1);
)
cout<<n\n\n”
<<Wordsread:'*<<wdCnt<<*'\n\n
<<the/The:n?theCnt?”\n”
<<it/It:"<<itCnt<<n\n\n
<<a<<aCnt<<n\n"
<<<<eCnt?“\n”
<<i<<iCnt<<'*\nn
<<o<<oCnt?H\n
<<u<<uCnt<<endl;
return0;
)
練習(xí)3.29卜面是我們的新函數(shù):
inlineString
String::operator+(constString&rhs)const
StringnewString;
if(!rhs._string)
newString=*this;
elseif(!_string)
newString=rhs;
else{
newString._size=_size+rhs._size;
newString._string=newchar[newString._size+1];
strcpy(newString._string,_string);
strcat(newString._string,rhs._string);
)
returnnewString;
}
我們首先檢查是否有任何一個(gè)字符串是空字符串。如果有,就返回非空字符串的一份副本。如果
兩者都是空字符串,則返回其中一個(gè)空字符串的新副本。
如果兩個(gè)操作數(shù)都不是空字符串,我們就計(jì)算新的大小:
newString._size=_size+rhs._size;
并分配內(nèi)存給新字符串使用:
newString._string=newchar[newString._size+1];
利用c標(biāo)準(zhǔn)程序庫所提供的函數(shù),我們復(fù)制第一個(gè)字符串:
strcpy(newString._string,_string);
然后為它接上第二個(gè)字符串:
strcat(newString._string,rhs._string);
最后,返回新字符串。
下面是一個(gè)小型測(cè)試程序。
#include“string"
intmain()
{
Stringempty;
Stringstrl(nThecow
Stringstr2("jumpedoverthemoon.");
Stringstr3=strl+str2;
cout<<"String1:|n<<strl<<
cout<<"String2:|n<<str2<<
//測(cè)試空字符串的連接
str3-str3+empty;
str3=empty+str3;
cout<<"String1+String2:|n<<str3<<H!\nn;
return0;
)
練習(xí)4.1表達(dá)式:
dvall/dval
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- Unit 1 Meeting new people Lesson 5(教學(xué)設(shè)計(jì))-2024-2025學(xué)年人教PEP版(2024)英語三年級(jí)下冊(cè)
- 2 我學(xué)習(xí)我快樂 教學(xué)設(shè)計(jì)-2024-2025學(xué)年道德與法治三年級(jí)上冊(cè)統(tǒng)編版
- 8安全記心上 第一課時(shí) 平安出行(教學(xué)設(shè)計(jì))-部編版道德與法治三年級(jí)上冊(cè)
- 股份合同范本
- 會(huì)所餐飲合同范本
- 菜地整治合同范本
- 出包合同范本
- 入股服裝合同范本
- 8《小心火災(zāi)》教學(xué)設(shè)計(jì)-2024-2025學(xué)年三年級(jí)上冊(cè)綜合實(shí)踐活動(dòng)魯科版
- 紡織合同范本
- 《道路建筑材料緒論》課件
- 2025年湖南現(xiàn)代物流職業(yè)技術(shù)學(xué)院高職單招職業(yè)技能測(cè)試近5年常考版參考題庫含答案解析
- 第二十章手術(shù)減肥及體形塑造美容手術(shù)美容外科學(xué)概論講解
- 2025年蘇州衛(wèi)生職業(yè)技術(shù)學(xué)院高職單招職業(yè)技能測(cè)試近5年??及鎱⒖碱}庫含答案解析
- 履帶式剪叉高空作業(yè)平臺(tái)安全操作規(guī)程
- 《水稻育秧技術(shù)新》課件
- 2024-2025年第一學(xué)期初中德育工作總結(jié)
- 圍手術(shù)期手術(shù)患者護(hù)理要點(diǎn)
- 男科話術(shù)完整版本
- 統(tǒng)編版五年級(jí)道德與法治下冊(cè)全冊(cè)完整課件
- 直系親屬關(guān)系證明(存根)(共1頁)
評(píng)論
0/150
提交評(píng)論