C++primer 习题解答第七章.docx

上传人:b****2 文档编号:1952083 上传时间:2023-05-02 格式:DOCX 页数:17 大小:27.62KB
下载 相关 举报
C++primer 习题解答第七章.docx_第1页
第1页 / 共17页
C++primer 习题解答第七章.docx_第2页
第2页 / 共17页
C++primer 习题解答第七章.docx_第3页
第3页 / 共17页
C++primer 习题解答第七章.docx_第4页
第4页 / 共17页
C++primer 习题解答第七章.docx_第5页
第5页 / 共17页
C++primer 习题解答第七章.docx_第6页
第6页 / 共17页
C++primer 习题解答第七章.docx_第7页
第7页 / 共17页
C++primer 习题解答第七章.docx_第8页
第8页 / 共17页
C++primer 习题解答第七章.docx_第9页
第9页 / 共17页
C++primer 习题解答第七章.docx_第10页
第10页 / 共17页
C++primer 习题解答第七章.docx_第11页
第11页 / 共17页
C++primer 习题解答第七章.docx_第12页
第12页 / 共17页
C++primer 习题解答第七章.docx_第13页
第13页 / 共17页
C++primer 习题解答第七章.docx_第14页
第14页 / 共17页
C++primer 习题解答第七章.docx_第15页
第15页 / 共17页
C++primer 习题解答第七章.docx_第16页
第16页 / 共17页
C++primer 习题解答第七章.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

C++primer 习题解答第七章.docx

《C++primer 习题解答第七章.docx》由会员分享,可在线阅读,更多相关《C++primer 习题解答第七章.docx(17页珍藏版)》请在冰点文库上搜索。

C++primer 习题解答第七章.docx

C++primer习题解答第七章

第七章函数

题目00形参和实参有什么区别?

【解答】形参是在函数定义的形参表中进行定义,是一个变量,其作用域为整个函数。

而实参出现在函数调用中,是一个表达式。

进行函数调用时,用传递给函数的实参对形参进行初始化。

题目01下列哪些函数是错误的?

为什么?

请给出修改意见

(a)intf()

{

strings;

//...

returns;

}

(b)f2(inti){/*...*/}

(c)intcalc(intv1,intv1)/*...*/}

(d)doublesquare(doublex)returnx*x;

【解答】

(a)是错误的。

因为函数头中所定义的返回值类型为int,return语句世纪返回的表达式的类型为string,两个类型不同,而string类型又不能隐式转换为int类型。

可修改为:

stringf(){strings;//…Returns;}

(b)是错误的。

因为该函数定义中没有指定返回类型,在标准C++中,定义函数时不指定返回类型是非法的。

可修改为:

Intf2(inti){/*…*/}

(c)是错误的。

缺少括住函数体在左花括号,而且两个形参不应该同名。

可修改为:

Intcaic(intv1,intv2){/*…*/}

(d)是错误的。

缺少括住函数体的一对花括号。

可修改为:

Doublesquare(doublex){returnx*x;}

题目02编写一个带有两个int型形参的函数,产生第一个参数的第二个参数次幂的值。

编写程序传递两个int数值调用该函数,请检验其结果。

【解答】

//7-3.cpp

//函数Power带有两个int型形参,产生第一个参数的第二个参数次幂的值。

//主函数传递两个int型数值调用power函数

#include

Usingnamespacestd;

Intpower(intx,inty)//该函数返回x的y次幂

{Intresult=1;For(intloop=1;loop<=y;++loop)Result*=x;Returnresult;}

Intmain(){

Intxval,yval;

Cout<<”entertwointegers(thesecondoneshouldbeequaltoorbiggerthan0):

”<

Cin>>xval>>yval;

If(yval<0){

Cout<<”thesecondintegershouldbeequaltoorbiggerthan0”<

}

Cout<<”resultofraising”xval<<””tothepowerof<

注意,当输入的证书较大时,该power函数的计算结果容易溢出。

题目03编写一个函数,返回其形参的绝对值。

【解答】可编写如下abs函数,返回形参x的绝对值:

Intabs(intx){Retrunx>0?

x:

-x;}

题目04编写一个函数,该函数具有两个形参,分别为int型和指向int型的指针,并返回这两个int值之中较大的数值。

考虑应将其指针形参定义为什么类型?

【解答】函数代码如下:

IntgetBigger(intx,constint*y){Returnx>*y?

x:

*y;}该函数无需修改指针形参所指向的值,因此,为了保护指针形参所指向的值,将指针形参定义为指向const对象的指针。

题目05编写函数交换两个int型指针所指向的值,调用并检验该函数,输出交换后的值。

【解答】

//7-6.cpp

//函数swap交换两个int型指针所指向的值。

//主函数调用swap函数,输出交换后的值

#include

Usingnamespacestd;

Voidswap(int*x,int*y)//该函数交换x和y所指向的值

{Inttemp;Temp=*x;*x=*y;*y=temp;}

Intmain(){

Intxval,yval;

Cout<<”entertwointegers:

”<

Cin>>xval>>yval;

Cout<<”beforeswapped”<<”x=”<

Swap(&xval,&yval);

Cout<<”afterswapped:

”<<”x=”<

Return0;}

题目06解释下面两个形参声明的不同之处:

voidf(T);voidf(T&);

解答】

前者声明的时T类型的形参。

在f中修改形参的值不会影响调用f时所传递的实参的值。

后者声明的时T类型的引用形参。

在f中修改形参的值世纪上相当于修改待用f时所传递的实参的值。

题目07举一个例子说明什么时候应该将形参定义为引用类型。

再举一个例子说明什么时候不应该将形参定义为引用。

【解答】

如果希望通过函数调用修改实参的值,就应该将形参定义为引用类型。

例如,用swap函数交换两数的值。

如果不将形参定义为指针类型,则需要直接修改实参的值,应该将形参定义为引用类型。

Voidswap(int&v1,int&v2){Inttmp=v2;V2=v1;V1=temp;}除了swap函数这种情况外,为了通过一次函数调用获得多个结果值,也可以使用引用形参。

另外,在向函数传递大型对象时,为了避免复制实参以提高效率,以及使用无法复制的类类型(其复制构造函数为private的类类型)座位形参类型时,也应该将形参定义为引用类型。

但这是使用形参的目的是为了避免复制实参,所以应该将实参定义为const引用。

如果不需要通过函数调用修改实参的值,就不应该将形参定义为引用类型。

例如,在求绝对值的函数中,形参就不宜定义为引用类型。

题目08将第7.2.2节定义的find_val函数的形参表中occurs的声明修改为非引用参数类型,并重新执行这个程序,该函数的行为发生了什么改变?

【解答】调用该函数后,ctr的值将不变(保持调用该函数之前的原值,不再能反映42出现的次数)。

因为在函数体中修改的时形参occurs(即cr的局部副本),对实参ctr不产生影响。

题目09下面的程序虽然是合法的,但可用性还不够好,指出并改正该程序的局限:

booltest(string&s){returns.empty();}

【解答】其局限在于:

此处使用引用形参的唯一目的是避免复制实参,但没有将形参定义为const引用,从而导致不能使用字符串字面值来调用该函数(因为非const引用形参只能与完全同类型的非const对象关联)。

可更正为:

Booltest(conststring&s){returns.empty();}

题目10何时应将引用形参定义为const对象?

如果在需要const引用时,将形参定义为普通引用,则会出现什么问题?

【解答】如果使用引用形参的唯一目的是避免复制实参,则应将应用形参定义为const对象。

如果在需要const引用时,将形参定义为普通引用,则会导致不能使用右值和const对象,以及需要进行类型转换的对象来调用该函数,从而不必要地限制了该函数的使用。

题目11什么时候应使用指针形参?

什么时候就使用引用形参?

解释两者的优点和缺点。

【解答】当函数需要处理数组且函数体不依赖于数组的长度时应使用指针形参,其他情况下应使用引用形参:

指针形参的优点是可以明确地表示函数所操纵的是指向数据元素的指针,而不是数组本身,而且可以使用任意长度的实参数组来调用函数;其缺点是函数体不能依赖于数组的长度,否则容易造成数据内存的越界访问,从而产生错误的结果或者程序崩溃。

引用形参的优点是在函数体中依赖数组的长度是安全的;其缺点是限制了可以传递实参数组,只能使用长度匹配的实参数据来调用函数。

题目12编写程序计算数组元素之和。

要求编写函数三次,每次以不同的方法处理数组边界。

【解答】

//计算数组元素之和

//三个求和函数以不同的方法处理数组边界

#include

Usingnamespacestd;

//传递指向数组第一个和最后一个元素的下一位置的指针

Intstr1(constint*begin,constint*end){Intsum=0;While(begin!

=end){Str+=*begin++;}Returnsum;}

//传递数组大小

Intsum2(constintia[],size_tsize){Intstr=0;For(size_tix=0;ix!

=size;++ix){Sum+=ia[ix];}Returnsum;}

//传递指向数组第一个元素的指针和数组大小

Intsum3(int*begin,size_tsize){Intsum=0;Int*p=begin;While(p!

=begin+size){Sum+=*p++;}Returnsum;}

Intmain(){Intia[]={1,2,3,4};Cout<<”summationfromsum1():

”<

”<

”<

题目13对象中所有元素之和。

解答】

include

#includeUsingnamespacestd;

//传递元素迭代器来处理元素

DoublevectorSum(vector:

:

iteratorbegin,vector:

:

iteratorend){

Doublesum=0.0;

While(begin!

=end){

Sum+=*begin++;}

Returnsum;}

Intmain()

{Vectordvec;//读入vector元素

Cout<<”enterdoubletypeelementsforvector(CTRL+Ztoend)”<

Doubledval;

While(cin>>dval)Dvec.push_back(dval);//求元素之和并输出结果

Cout<<”summationofelements:

”<

Return0;}

题目14编写一个主函数main,使用两个值作为实参,并输出它们的和。

【解答】

//7-15.cpp//主函数main使用两个值作为实参,并输出它们的和

#include

Usingnamespacestd;

Intmain(intargc,char**argv)

{//检查命令行参数

If(argc!

=3)

{Cout<<”youshouldusethreearguments”<

Cout<<”summationof”<

题目15Writeaprogramthatcouldaccepttheoptionspresentedinthissection.Printthevaluesoftheargumentspassedtomain.编写程序使之可以接受本节介绍的命令行选项,并输出传递给main的实参值。

【解答】//接受命令行选项,并输出传递给main的实参的值

#include

Usingnamespacestd;

Intmain(intargc,char**argv)

{Cout<<”argumentspassedtomain();”<

=argc;++i)Cout<

题目16Whenisitvalidtoreturnareference?

Aconstreference?

什么时候返回引用是正确的?

而什么时候返回const引用是正确的?

【解答】返回指向在函数调用之前已存在的对象的引用是正确的。

当不希望返回的对象被修改时,返回const引用是正确的。

题目17Whatpotentialrun-timeproblemdoesthefollowingfunctionhave?

下面函数存在什么潜在的运行时问题?

string&processText(){stringtext;while(cin>>text){/*...*/}//....returntext;}

【解答】该函数返回了局部对象test的引用。

当函数执行完毕时,将释放分配给局部对象的存储空间,这样,对局部对象的引用就会指向不确定的内存,因此函数会在运行时出错。

题目18判断下面程序是否合法;如果合法,解释其功能;如果不合法,更正它并解释原因。

int&get(int*arry,intindex){returnarry[index];}intmain(){intia[10];for(inti=0;i!

=10;++i)get(ia,i)=0;}

【解答】该程序段合法。

其功能为:

将数组ia的各个元素赋值为0.

题目19

将函数factorial重写为迭代函数(即非递归函数)。

【解答】函数如下:

Intfactorial(intval){Intresult=1;For(inti=1;i<=val;++i)Resulet*=I;Returnresult;}

题目20如是函数factorial的终止条件为:

if(val!

=0)会出现什么问题?

【解答】会出现这样的问题:

如果实参为负数x,则理论上该函数会求得x*(x-1)*…*(int型能表示的最小负数)*(int型能表示的最大整数)*(int型能表示的最大正数-1)*…*1这样的结果,但是实际运行时会因递归函数调用次数过多而发生程序栈溢出,似的程序无法继续执行。

而当实参为负数时,元factorial函数球的的结果应该为1。

题目21Writetheprototypesforeachofthefollowingfunctions:

编写下面函数的原型:

a.函数名为compare,有两个形参,都是名为matrix的类的引用,返回bool类型的值。

b.函数名为change_val,返回vector类型的迭代器,有两个形参:

一个是int型形参,另一个是vector类型的迭代器。

提示:

写函数原型时,函数名应当暗示函数的功能。

考虑这个提示会如何影响你用的类型?

【解答】函数原型如下:

Boolcompare(matrix&,matrix&);

Vector:

:

iteratorchange_val(int,vector:

:

iterator);

题目22给出下面函数,判断哪些调用是合法的,哪些是不合法的。

对于那些不合法的调用,解释原因。

doublecalc(double);intcount(conststring&,char);intsum(vector:

:

iterator,vector:

:

iterator,int);vectorvec(10);(a)calc(23.4,55.1);(b)count("abcda",'a');(c)calc(66);(d)sum(vec.begin(),vec.end(),3.8);

【解答】(b)(c)(d)合法。

(a)不合法。

因为calc函数只有一个形参,调用该函数时却传递了两个实参。

题目23Which,ifany,ofthefollowingdeclarationsareerrors?

Why?

如果有的话,指出下面哪些函数声明是错误的?

为什么?

(a)intff(inta,intb=0,intc=0);

(b)char*init(intht=24,intwd,charbckgrnd);

【解答】(b)是错误的。

因为在形参表中,具有默认实参的形参应该出现在形参表的末尾(此处ht应出现在没有指定默认实参的形参wd和bckgrnd的后面)。

题目24Giventhefollowingfunctiondeclarationsandcalls,which,ifany,ofthecallsareillegal?

Why?

Which,ifany,arelegalbutunlikelytomatchtheprogrammer'sintent?

Why?

假设有如下函数声明和调用,指出哪些调用是不合法的?

为什么?

哪些是合法的但可能不符合程序员的原意?

为什么?

//declarations

char*init(intht,intwd=80,charbckgrnd='');(a)init();(b)init(24,10);(c)init(14,'*');

【解答】(a)不合法。

因为调用init函数时必须显式指定至少一个实参。

(c)合法,但可能不符合程序员的原意。

因为这里是将char型实参’*’转换为int型再传递给形参wd。

题目25用字符's'作为默认实参重写函数make_plural。

利用这个版本的函数输出单词“success”和“failure”的单数和复数形式。

【解答】

//用字符’s’作为默认实参实现函数make_plural。

//利用个这个版本的函数输出单词”successs”和”failure”的单数和复数形式#include

#include

Usingnamespacestd;

//如果ctr不为1则返回word的复数版本

Stringmake_plural(size_tctr,conststring&word,conststring&ending{Return(ctr==1)?

word:

word+ending}

Intmain(){Cout<<”singularversion:

”<

”<

”<

”<

题目26Explainthedifferencesbetweenaparameter,alocalvariableandastaticlocalvariable.Giveanexampleofaprograminwhicheachmightbeuseful.解释形参、局部变量和静态局部变量的差别。

并给出一个有效使用了这三种变量的程序例子。

【解答】从本质上说,三者均都属于局部作用域中的变量,其中局部变量又可区分为普通(非静态)局部变量和静态局部点亮。

他们的差别在于:

(1)形参的作用域为整个函数体,而普通(非静态)局部变量和静态局部变量的作用域为:

从定义处到包含该变量定义的块的结束处。

(2)形参由调用函数时所传递的实参初始化;而普通(非静态)局部变量和静态局部变量通常用初始化式进行初始化,且均在程序执行流程第一次经过该对象的定义语句时进行初始化。

静态局部变量的初始化在整个程序执行过程中进行一次。

(3)形参和普通(非静态)局部变量均属自动变量,在每次调用函数时创建,并在函数结束时撤销;而静态局部变量的生命期却跨越了函数的多次调用,它在创建后直到程序结束时才撤销。

例如:

如果需要连续输出1…x之间的所有数的阶乘,可用如下程序:

//读入上限值upLmt,输出(1…upLmt)之间所有整数的阶乘

#include

Usingnamespacestd;

//用于辅助求阶乘的函数

Inttac(intx)//x为形参

{Staticresult=1;//result为静态局部变量

Result*=x;Returnresult;}

Intmain(){IntupLmt;//upLmt为普通(非静态)局部变量

Cout<<”entervalueofupperlimit:

”<>upLmt;

//依次输出(1…upLmt)之间的所有整数的阶乘

For(inti=1;i<=upLmt;++i)

Cout<

=”<

Return0;}

题目27Writeafunctionthatreturns0whenitisfirstcalledandthengeneratesnumbersinsequenceeachtimeitis

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2