实例介绍
c++之父编的那本c++课后习题的参考答案
」8C+艉序設计晤言〉題解 对练习的简短指南 《C++程序设计语言》一书中的练习是希望能成为一种媒介,帮助拓展人们对于语言中各 种可能情况的理解。作为一个整体,它们糰盖了C++程序设计语言的知识和求解元素中相当 广阔的范围。然而我发现,这里所选出的大部分练习可以归到下面所提出的几个类别中的某 类或某几类 事实和结构:这些练习可用于检查一个人对语言规范的熟悉程度。下列练习都属于这一 类:42、4.3、47、5I、55、56、6.1、6.2、65、6.6、67、6.9、7.1、72、7、14、84、 85、8,7、99、10.1.104、11.1、11.7、12.1、131、13.15、152、16.15、20.1。 φ常旯愤用法和良妤实践:阐释C++语言常常怎样用于解决各种各祥小的程序设计问题 参见练习53、54、57、5,10、5.11、512、513、63、6.10、6,11、6.12、613、6,14、 616、617、6.19、6.22、7.3、74、7.6、7.7、7.9、7.11、7.16、7.18、7.19、8.1、8.10、 95、10.2、10.5、10.12、10.19、11.3、11.4、11.8、141、142、14.9、153,16.1、 162、163、166、173、17.5、182、185、18.10、18,11、18.14、19.1、192、19,3、 20.5、20.16、21.1、21.2、21.12、21.18、21.24、22.1、222、22.4、25.1、25.5、25.7、 25.19。 ·试验:这些练习所包含的程序或者是用于阐明某些依赖于实现的行为,或者是有关性能 的问题。有些练丬包含一些小的基准测试,对于获取对各种C++特征和技术的代价的直 观理解,这些练习将很有价值。这方面的练习有43、44、4.5、46、5.8、6.8、8.6、 8.8、9.3、7.l、18.19,20.15 ·高级惯用法和设计技术;讨论一些更特殊的问题。对于这些练习,我通常会试着去强调 能够引出一个解答的某种一般思维过程。要将由此得到的思想应用于你的具体情况,还 需要做一些并不简单的调整。这样的练习包折719、12.10、13,2、13.16、14.10、21.13、 2.8 琐碎的和令人讨的东两:母种序设计话言都有它自己小小的偏狄之处,对这些的滥 用将导致晦涩难懂的程序。少数几个练习探素了软件开发中这些比较阴暗的部分。也有 些这类东西虽然无害,但也并非最基本的。这方面的练习有4.6、59、615、10.15、 11.10、11.20、11.21、129。 事实上,大部分练习都属于前两个类别,这说明该书强调的还是C++的基本内容。当然,一 且建立了这种基础,更高级的材料也就会变得更容易理解,并能获得更高的作效率。与此 梱反,属于试验一类的练习通常并不需要熟悉C++的高级特征。 建议 不要强迫自己严格按編号顺序去做这些练习。采取下面方式或许会有所帮助:开始先做 属于第一个类别的练习,增强一下你对最基本的幺西的埋解;而后再去做属于第二类别的练 习(常兕惯用法和良好实践),使自己能较流畅地把握该章所讨论的基本语言兀素。与《C+ 程序设计语言》一样,本书的索引也提供了对有关感兴趣题目的快速而易用的引证。 通常,你不必在完全熟悉了《C+程序设计语言》的一章中的所有材料之后再去试着做 习。当然,通过阅读 Stroustrup的书的第2章和第3章(有关“概览”的两章),取得对这种语 章引论3 言的一个总体认识,则是非常有意义的事情。 特别有趣的是那些长一些的练习。练习153是一个流行棋盘游戏的完整的面向对象设计和 实现。作为符合标准的基本元素实现的例子,练习182是一个算法,习19.3是个完整的迭 代器的遭配器。练习20,梢短一些,但对此目的而言却很有价值。有关展示标准库威力的例 子请见练习612,它针对一紐数据计算出一些不同的统计量。如果你想寻找一个能磨炼你在 更传统的特征方面(语句和表达式)拔能的例了,试一下练习6,22 我相信,要想从本书中获得更多的东西,最好是先不要去看所建议的解答,而是自己去 试蒼做练习。一旦你找到了某个练习的一个解,你可以将且己的解与书中的解比较。在某此 情况下,这一比较可能说明哪个解对于该练习是更“自然的解答”。但更多出现的情况是,你 可能发现,存在着许多不同的方法去完成同一件丁作、如果你在合理的时间内还不能找到 个解,本书中对于该练习的讨论可能提供一些澄消问题的线索。这个讨论常常能引导你考虑 出一个与我所提供的解答不同的解,这也是很有价值的实践。 在做这里的许多练习时,最好是实际地太实现有关的解。在描绘一个解的过程中可以学 到许多东酉,也能使你确信所采用的方式是合理的。当然,实际的实现还需要进一步去关注3 许多细节问题,良好的软件设计技能也需要包括对于细节的合理考虑方面的蘑练。对于试验 类别的练习,这一说法就更止确了在做这些练习时,应当毫不犹豫地去修改这些试验,以 使你能进步认识怎么能使C++程序运行,怎样才能做得更好。 当然,还需要有良好的评价能力,能认清基本机制与具体细节之间的差异。在某些情况 下,你可能发现在实现所提出的解时出现了一些令人心烦的情况,原因是所用C++实现并不 完全符合语言的O规范。第3章将处理这一方面可能遇到的大部分常见问题。 《C++程序设计语言〔特别版)》自然是研究所提出的解答时最推崇的信息来源。一旦你 熟悉了其中的大部分技术,你也可能希望进一步去钻研吏多的技术文献。学术界有许多讨论 C++的优秀著作,它们提供了许多超出《+程序设计语言》讨论范围的材料。我想强调的是 下面几本: Efective C++ 50 Specific Ways to improve Your Programs and Designs(Second Edition) Scott Meyers, Reading, MA: Addison Wesley Longman, 1997 More Ejective C++: 35 New Ways to Improye your Programs and Designs, Scott Meyers Reading, MA: Addison Wesley Longman, 199 The Design and Evolution of C++. Bjarne Stroustrup. Reading, MA: Addison Wesley Longman,199.(《C+语言的设计和演化》.裘宗燕译,机械工业出版社,2002) 前两本书描述了许多实践性的规则和技术,它们可以导致更强健的,常常也是吏高效的 C++程序。书中介绍了一些具有普避意义的设计原则和特殊编码技木。 第二本书描述了直至1993年底为止的C++语盲的演化过程。我已经深刻地认识到,对这 一演化过程的理解,对于我们确定应当怎样最好地使用C+的丰富结构集合极有帮助。它也 能帮助我们处理好C++的某些黴妙特征,使之更直观、更容易掌握, 最后我还想指出,C++社团非常庞大。与朋友和同事开展有关技术、语义和设计原则方面 的讨论是极有价值的。此外,现在有许多有关C++程序设计的会议和电子论坛。特别是,我 已经发现 Usenet论坛 comp. langc+ moderater和eomp.std++对各种各样的C+问题都 有极富见解的讨论。 第2章C++概念 本书无意作为一本C++程序设计语言的独立教材。《C++程序设计语言》是满足这一需要 的最佳资源。当然,对一些基概念做个总结,在术语方面达成一种共识也是很冇用的、符 合习惯的。 你可以安全地跳过这一章,在需要快速复习某些C++基本问题时再转回来。如果需要更完 整的深人的信息,那么请参考 Stroustrup的书。 语言和实现 程序设计语言是一个抽象的事物,它是一组描述程序行为的规则和约定。对这一抽象事 物的具体化就是一个语言实现一个设备,实际上常常是一个程序,它能将一个程序描述 转变为(翻译为)一个实际的行为。该转变过程将始终强制性地要求由该程序设计语言所没 定的那些规则。 对于C++,在绝大多数情况下,这种实现是一个縞译器,编译器是一个能够将文本(源代 码)翻译为可执行程序的程序。一旦翻译完成之后,得到的程序就可以在某个目标平台(计 算机)上重复执行了。 本书假定你已经在一定程度上了解这些概念。某些实践性考虑还将在练习41讨论。 调法单词 C+源代码逼常被划分为多个文件(91节)这种源文件经过预处理之后,注释都被剔除, 宏都被替换掉∫。这样得到的结果通常被称为编译单位。一个编译单位是一八谪法单词的序 5列,训法单词包括:单词、数字和各种符号。它们都是C+话言里具有独立意义的最小实体 例如,下面这一小段C++代码 int const hundred 100 由六个词法单词组成:“int”、“cns"、“ hundred"、"=”、“100″和“;”。楫识符是一类词 法单词,其“拼写形式”可以由程序员自由选择。它们是字母、数字和下划线(_)组成的任 意序列,但是不能以数字开头。请注意,字母的大小写是有意义的。某些序列虽然符合条件 但是不能作为标识符: 关健字(A.2节)和某些符号的替代表示形式:“int”和“ const”是关键词的例子 and”是符号“&&”(逻枰与操作)的替代表小形式的例子。C+程序设计语言中有63 个关键词和1个替代表示形式 a保韶的名字:为使具体实现能引进自己的名字而保留一些名字有时是方便的。包含连续 的两个下划线的名字(如re__ served),以及以下划线开头后面紧跟着一个大写字母的 名字(如 Reserved)是为此而保留的,因此不应该作为用户定义的标识符 词法单词通常用空白宇符分隔,但这些空白字符本身并无意义。在许多情况下,从一个词法 第2章C++概念 单词到下一个词法单词的翻译并不要求有这种空白的存在,也不限制在词法单词之间的空白 字符的个数。例如,上面那个声明也可以以下面两种形式出现 int const nundred=100 t nt const hundred 109 但下面形式就不会工作了 ntconst hundred =100: 没有空白字符分隔, incont:被看是一个标识符假定是用户自己定义的—-而不是连 续的两个关键字。 空白字符的某些使用可能损害源代码的清晰性,我们的第三个例子说明了这类情况。但 无论如何,个人的爱好可能不同,这些形成了源代码的不同风格,本书并不想在这个方面去 强调某些特定的规划。许多项目确实要求遵守共C++源代码的格式规则,以便使源文件更 容易理解(另见493节和练习623 名字、声明和作用域 C++程序里的许多实体都需要通过名宇去引用。引进或者重新引进名字的描述形式通常称 为声明。如果在某编译单位的一部分里面,可以通过某个声明所引进的简单名字去引用这个[6 声明,该部分就称为这个名字的作用域。例如 ant a =3 intb=2;//<-全局b的作用域由此开始 ntb=;/<-全局b的作用域在此停业 局邵b的作用域开始 ++b;//引用局都的b }//≤-局部b的作用域结束,全局b的作用域恢复 正如本例所示,两个不同的声明可以关联于同一名字。在出现这种情况时,“最内层”的名字 将屏蔽外层名字。在某些情况下,被屏蔽的名字以及并非位于活动作用域里的名字可以通过 通常称为限定名的方式访问,这种名字包含一个作用域解析运算符“∷:”。例如: int a1 nesp日N{ int a, b roid fot a=1;//(被屏蕺的)全局a的限定名 -18;非限定名访问内层a d go t a=1;//全局的a N:a=7;/名字卒间N作用域中的a(限定名 6《Ct程序爱计評言》題解 位于作用域解析运算符左边的限定符必须或者是-个名字空间的名字(82节),或者是一个 类的名字(10.2节)。这也意味着,局部于某个函数的名字不能通过限定名的方式访问。 对象、类型、引用和函数 对象悬那种占据着一块连续存储区域(计算机内存)的东西。然而,随机的-组连续信 息位通常并不被看做是对象。相反,一个对象总有一个与其物理的位组相关联的类型、类型 是一组属性和可应用操作,这些性和可应用操作确定了组成一个对象的位组应该如何解释。 例如,在许多系统里,定义 char c= 1: 和 boo] b= true; 的结果将得到同样的物理的二进制值的集合。然而由干它们的类型不同,++C和++b很可能具 有不同的物理值。 C+有一组内部的基本类型, bool char, unsigned inti和 double是其中的一些例于(42 节、4.3节、44节、45节)其他的类型被称为复合类型,可以通过许多不同方式建立。这些 复合类型可以归为如下几个类别 枚举(4.8节 类(包括结构,57节,第10章) ·联合(1042节) 数组(52节〕 ·指针(5.1节,5.3节) 引用(55节) ·函数(第7章) 虽然函数和引用也具有类型,它们却不是C++语喜的意义下的对象。引用不过是对象的“别 名”—一因,在运行时它们可能并不占用任何存储空间,在某些时候,这些别名可能被 ¢++编译器聲换掉。在典型情况下,函数确实需要为它们的表示占用运行时存储空间,但是 C++和其他大部分程序没计语言一样,不允许程序员去使用函数所占据的空间。这就使我们 无法去写(例如冫能自我修改的代码。 左值和右值表达式 对象的存在是因为显式地定义了它们,或者是分配了它们(例如,通过使用neW运算符)。 如果一个表达式引用这样的对象,这个表达式通常被称为是一个左表达式,否则称为右值 表达式。例如 trit a nt點=& a=2;!/a是左值,2是右值 nb=B;!·和a都是方值 h= new ?nt;//newi是右值,b是左值 nt const&r1=* ew int;//“new』nt是左值 a=ri;/r是左值 第2章C++概念 int fo tb-f():/′是右值 int& co: a亠q);/g是左值 术语左值( lvalue)中的“左”(L}是从C语言的前身(例如BCPL,第1章〕那卫继承来的, 在那此语言,左值只能出现在赋值的左边,而右值则不能出现在赋值左边。在现代的C以及 在C++里,左值却未必出现在赋值左边.因为被引用的对象可以是 const。这种左值也被称为 不可修改的左值。C++还提供了修改右值的方式,但极少需要去用它。 算术运算符(+、-、%、*等)的结果和数调用的结果通常都是右值,除非它们返回 引用 初始化和赠值 初始化(495节)是为一个对象建立第一个值的过程,而另一方面,赋值(23.1节)是 个操作,通常用于改变一个对象的值,其以前的值已经存在了。赋值用词法单词“=”表示 有时初始化也用这一符号表示: 9 irta=12://初始化(定义) a=13://嬷信 简而言之,当“=”符号出现在声明里的时候,它就表示初始化;否则就表示赋值 不用“=”符号也可以描述初始化。例如 inta(12);//与上面一样 还有,函数参数的传递也是通过初始化机制:例如: void f(x x)[/ ! void g() t Xa;//假定X是某个类型 f〔a)://参数x通过初始化取得a值 对于类,你可以通过提供构造函数的方式定义自己选择的初始化过程(102.3节,104节), 可以通过提供 operator=的方式定义自己的赋值运算(1044.1节)。请记住,初始化时绝不会 调用你的 perator=,即使某个初始化是用“=”符号表示的c 声明的语法形式 出现在声明中的大部分常用语法是比较盲观的,但最一般的语法规则则常常令人吃惊。 下面的讨论总结了第5章、第6章、第7章和第10章中说明的基础知识 变量和常量 个声明由以下四部分组成(491节) 1.一组(可选的)描述符。 2.一个基类型 3.一个声明符。 8《C++程序设计语言》题膚 4.一个可选的初始式。 描述符或者是对应与被声明实体相关联的一些属性,例如 extern(92节)、 virtual(12.2.6 节)和 explicit(11.71节}:或者是对应于与被声明实体的类型相关联的一些属性〈例如 cnst,5.4节)。有趣的是,对于描述符出现的顺序只有很少的限制,而且事实上,它们有时 甚至会出现在基类型的后而。例如,下面所有声胡合法,而且是等价的 extern irt const c onst int extern c ranst extern nt c: nnt extern const c: 几乎所有程序员都愿意将与类型相关的描述符(类型描述符)放得靠近基类型,而将其他描 述符放在基类型和类型描述符的前面。上面声明通常被排列为下面两种形式之 extern const int o;/ const是类型描述符 extern int constc;// extern不是 前一种排列形式最为流行,但由于练习51中将要解释的原因,有时第二种形式更合适。 基类型可以是一个基本类型(如 float},也叫以是一个enum、 class(或 struct)或者 unon的名字。如果这一基类型不是基本关型,其名字可以是跟定的(见前面)或者加修饰的。 所谓修饰的意思是,在一个(可能加了限定的)名字之前叮以有下列关键词中的某一个 enum、 struct、 class和 urton。例如 names pace N t enum E t two =2, seven=7 E&://名字E无狠定也无修怖 enum E b;//加修饰但无限定的名字E enum N:;:Ec;//加修饰且限定敏名字E 个声明的声明符部分包括被声明的名字,可能还环绕着某些可选的声明运算符,它们用于 修改与该名字关联的基类型。这些运算符用于创建引用、指针、数组、函数和这些东世的组 合。让我们先考虑指针的憤况,指针声明时使用个前缀的星号“”。指向整数的指针p可以 声明如下 int >p: 上面我们说远如何将关键字 const关联于一个基类型。例如, nt const中p const int *gi 意味着p和q是指向整数的指针,但是却不能通过它们去修改它们所指向的整数。有时我们可 能希望表达指针本身不能被修改。做这件事情的方式就将关键字cns放在声明运算符“” 之后 int 1 i int *const cp &1 int const“ const cpc=; 后一声明所描述的指针cpc本身不能修改,被它所指的东西也不能通过cp修改: rp=3;/可以:不是拍向 const甚类型的指针 int 第2章C十挺念9 Cp s cpc=&j;:!!锴误:不能修改cons1指针 p=2;/错误:指针指向cans类壁 引用的声明语法与指针类似,但其中的声朗运算符是“&”而不是星号。不过,引用绝不会是 const int const &r &s=5:∥啡以:引 const int int& const cr;!/错误;没仃cons引用 C+还有另一个限定符 volatile,它可以出现在cons能出现的所有地方(至少在语法上是如此〉 这个限定符用于描述被限定的实体可能我同步地发生变化,也就是说,该变化不是山执行当 前线程引起的。 volatile的使用比 const少得多,其蔗义也更不精确,主要是想告诉C++编译器, 在进行优化时,对这种艰定的实体应该更保守些。 const和 volatile也可能一起使用,但这种用 法就更竿见了: int volatile strange int volatile *const cpv =&strange int const voTatile &rcv strange; 最后一个声明说rcv不能用于修改被它引用的实体,但事实上某种“外在影响”鄣可能改变被 引用的值。例如,该变量可能映射到一个硬件时钟,该时钟可能每做秒更新一次,但你的程 序却不能修改它。限定符coms和ve有时被称为cv限定符。 数组 数组用对由方括号构成的后级声明描述符声明,括号中有一个可选的常量(常量表达 式)下面是几个例子 dub1ept「3 dub1 e coords】={1.9,1.2};/推断出 coords(21 int cor宄tⅵa1s〔?]={8,1 虽然你可以有 const值的数组,但却没有将 const应用于声明运算符本身的语法形。例如 inta[2} const;//错湜:没有cons限定数组 正如可以有指向指针的指针一样,我们也可以声明数组的数组(但却没有引用的引用) int*cnst"pp:/?一个指针, /!它指向一个指向n的 const描针 inta[19[26];110个数组的教组,其中每个数组包含20个in int&&rr:/′错误! aa的声明说明了位于左边的“[0”首先使用,也就是说,a是一个包含10个项的数组,而 不是包含20个顶的数组。另一方面,对于前缓的声明运算符,列是最右的运算符首先使用 pp是一个非 const指针。 不同声明运算符可以混用 int*p[1];//指针的数组 你可能会感到疑惑,这究竞是一个指针的数组,还是一个指向数组的指针?前者是正确的, 因为后缀声明运算符都比前缀声明运算符的优先级更高。要想改变这一既定的顺序,我们就 需要使用括号: int(a)[1Q1://指向数组的指针 【实例截图】
【核心代码】
标签:
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论