C/C#/C++的区别,学习它们的先后顺序,先学习哪个更容易?

温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
会C++再学Java或C#语法是很容易的,不过Java庞大的类库才是一座山。C#的.NET类库做桌面客户端应用(比如数据库管理系统、小工具小游戏)和VCL是非常像的,拖控件RAD编程方式一样,很多控件的名字都一模一样,有的控件只是换个名字,属性和方法都是大同小异,因为C#是微软挖了Borland的Delphi之父Anders Hejlsberg才搞出来的,可以说C#是C++ Builder的表兄弟。所以,学会了C++ Builder和VCL,要转到C#,应该也是比较容易的。因此,可以先学一点C++ Builder,入门容易,有了一点经验,有需要转到其它的框架类库也是不会怯场的。如果学习Java,做Web应用,写JSP和HTML甚至JavaScript混合代码,代码风格混乱,个人感觉不纯粹不喜欢。总之觉得C++比较正统,而且它的发展(从前C到C到C++)经过了历史检验,各种特性有它的合理性和灵活性(比如指针、全局变量、头文件、宏定义、goto语句等),世界上有无数的机器无数的代码在高效率运行,吸收了很多优秀的精华,特性很全面,并且不断发展。&个人感觉对于高手来说,使用C++是自由的,他拥有整个世界。而作为初学者,我也感到C++的世界太大太深了,如果不坚持,也很容易退却。&————————————————————————————关于C++ Builder,可以参考一个入门的简单例子作为了解:初学者学习C++ Builder第一个程序(模拟聊天室),经典!以及:C++ Builder绘图示例(ZEC 模拟数字双时钟带日历秒表)从C语言的菜单界面管理系统到C++ Builder的图形用户界面,一个简单的电话簿Demo例子C++ Builder写的《ZEC 四则运算练习程序》海底海星情景C++ Builder写的《ZEC 诗歌竖排动态显示》带TTS语音朗读C++ Builder写的《ZEC 走近中国一线城市》C++ Builder随机数波形图数据折线图小工具DataGraphDemoC++ Builder写的《ZEC 石头剪刀布》游戏C++ Builder写的《ZEC 彩票刮刮看》游戏C++ Builder写的《ZEC 拼图游戏》C++ Builder写的《ZEC 僵尸版打地鼠》C++ Builder写的《ZEC 纸牌游戏21点》C++ Builder写的《ZEC 推箱子》C++ Builder写的《ZEC 扫雷游戏》C++ Builder写的《ZEC 围棋游戏》(演示程序)双人对弈可下围棋、五子棋—————————————————————————————有关:《C++ Builder(BCB)是什么?》《C++ Builder(BCB)第一课》《C++ Builder(BCB)从初学到入门》书籍推荐:《C++Builder 6程序设计教程(第二版)》 (陆卫忠,刘文亮 等编著 / /科学出版社)(当当网)《C++Builder 6编程实例精解》(赵明现),PDF,是数字版的,非扫描版的,里面还有一个俄罗斯方块游戏的完整实现。《精彩C++Builder 6程序设计》(台湾 吴逸贤),里面有10几个简单小游戏的实现,可以自己看懂以后再重写,才是自己掌握的。《C++ Builder 5高级编程实例精解》(刘滨 编著)都是较大的实用的程序。
阅读(4244)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'学C++还是C#、Java?',
blogAbstract:'个人觉得C++特性比较全面,面向对象、STL、指针。。。还有性能。除了不适合做Web应用(平台无关,Windows、Linux、Unix。。。而C++程序和框架最终还是依赖具体平台的API),可以说功能最强大(系统软件、底层驱动、游戏、图像处理、视频应用、电信领域、服务器、算法和高性能应用。。。)而Java、C#恰恰相反,指针都没有,表达一个数据结构都显得麻烦,依靠虚拟机或运行库使得平台无关因而它们适合做Web应用,C#自己写个小工具小游戏在别人电脑上还要依赖庞大的.NET框架才能运行。会C++再学Java或C#语法是很容易的,不过Java庞大的类库才是一座山。C#的.NET类库做桌面客户端应用(比如数据库管理系统、小工具小游戏)和VCL是非常像的,拖控件RAD编程方式一样,很多控件的名字都一模一样,有的控件只是换个名字,属性和',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:6,
publishTime:7,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:true,
hostIntro:'暂无介绍',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}当前位置: >>
C++入门基础知识
C++ 基础教程完整版本教程对 C++语言进行了深入浅出的介绍,从基础知识到 ANSI-C++标准的最新功 能,内容涵盖了从数组,类等基本概念到多态、模板等高级概念。教程本着实用的原 则,每一小节都结合了可以工作的程序实例,以便读者从第一课开始就可以上手实 习。 本翻译版本对许多 C++概念中的关键词保留了中英文对照,以便读者增强理解,并方 便日后阅读英文原版教材目录第一章 C++ 基础知识 (Basics of C++)........................................................................... 6 1.1 C++程序结构 (Structure of a program)............................................................ 6 1.2 变量和数据类型 (Variables and Data types )................................................. 10 第二章 控制结构和函数......................................................................................................... 40 2.1 控制结构(Control Structures)........................................................................... 40 2.2 函数 I(Functions I)............................................................................................. 50 第三章 高级数据类型(Advanced Data )......................................................................... 64 3.1 数组 (Arrays)....................................................................................................... 65 3.2 字符序列 (Character Sequences)..................................................................... 71 3.3 指针 (Pointers).................................................................................................... 78 3.4 动态内存分配 (Dynamic memory)................................................................... 89 3.6 自定义数据类型 (User defined data types).................................................. 102 第四章 面向对象编程........................................................................................................... 106 4.1 类(Classes)........................................................................................................ 107 4.2 操作符重载(Overloading operators).............................................................. 118 4.3 类之间的关系(Relationships between classes)................................................. 125 4.4 多态 (Polymorphism)............................................................................................ 1341 / 178 第五章 C++高级...................................................................................................................142 5.1 模板(Templates).................................................................................................... 143 5.2 名空间 (Namespaces)........................................................................................... 151 5.3 出错处理 (Exception handling)............................................................................156 5.4 类型转换高级 (Advacned Class Type-casting).................................................. 160 5.5 预处理指令 (Preprocessor Directives)................................................................ 165 第六章 C++ 标准函数库..................................................................................................... 170目录 1. 简介怎样使用本教程 2. C++基础Basics of C++ 1. C++程序结构Structure of a program 2. 变量和数据类型Variables and Data types 3. 常量Constants 4. 操作符/运算符Operators 5. 控制台交互Communication through console 3. 控制结构和函数Control structures and Functions2 / 178 1.控制结构Control Structures 2. 函数 IFunctions I 3. 函数 IIFunctions II 4. 高级数据类型Advanced Data 1. Arrays 2. 字符序列 数组Character Sequences 3. 指针Pointers 4. 动态内存分配Dynamic memory 5. 数据结构Data Structures 6. 自定义数据类型User defined data types 5. 面向对象编程Object-oriented Programming 1. 类,构造函数和析构函数,类的指针Classes. Constructors and Destructors. Pointers to classes. 2. 操作符重载,this,静态成员Overloading Operators. this. Static members3 / 178 3.类之间的关系Relationships between classes: friend. Inheritance 4. 虚拟成员,抽象,多态Virtual Members. Abstraction. Polymorphism 6. C++高级Advanced concepts 1. 模板Templates 2. 名空间Namespaces 3. 出错处理Exception handling 4. 类型转换高级Advacned Class Type-casting 5. 预处理指令Preprocessor Directives 7. C++ 标准函数库C++ Standard Library 1. 文件的输入输出Input/Output with files C++基础教程简介 怎样使用本教程 读者范围 本教程面向所有希望学习 C++语言的读者。如果读者有其他编程语言背景或计算机相 关基本知识可以帮助更好的理解教程内容,但这并非必须条件。4 / 178 对于 C 语言熟悉的读者可将前三章(1.1 到 3.4)当作复习,因为这部分内容主要介绍 C++中的 C 部分。不过某些 C++的语法与 C 还是有些差别,所以建议还是快速的读一 下这部分。 第四章讲述面向对象编程。 第五章主要介绍 ANSI-C++标准中的新增的功能。本教程结构 教程共分 6 章,每章分若干小节。你可以直接从主目录进入任意小节,并循每页底部 的链接向后浏览。 很多小节含有一页例题介绍该章节主要知识点的使用。建议在进入下一章学习之前最 好先阅读这些例题,理解每行代码。 学习和练习一种编程语言的最好办法是自己修改书中例题程序,设法在程序中增加新 的功能。不要不敢修改这些例题程序,这正是学习的方法。兼容性备注 ANSI-C++标准近几年来被接受为国际标准。尽管 C++语言从二十世纪 80 年代即存 在,ANSI-C++在 1997 年才被发表,2003 年又被修订过。因此很多编译器不支持 ANSI-C++中的部分新功能,特别是那些在此标准发表前即被发布的编译器。 在本教程中,那些 ANSI-C++中新增的而老一代 C++编译器大多不支持概念将备用如 下标志标出: ANSI C++新增的概念 同样对于 C 和 C++在实现上有明显不同的概念,将备用如下标志标出: C 与 C++不同的地方 编译器 本教程中所有例题程序均为 console 程序(控制台程序)。此类程序以文本形式与用户交 换信息,显示结果。 所有 C++编译器均支持 console 程序的编译。要了解更多关于如何编译的说明,请查 询你的编译器用户使用手册。5 / 178 C++编译器和开发环境推荐 很多读者询问编译器和开发环境的问题。除了常用的商用收费的 MS Visual Studio, VC++,Borland C++等工具外,还有很多免费的工具也是很好用的。这里推荐两种免 费的 C++开发软件: 1、Eclipse 的 CDT 开发工具,官方网站在 http://www.eclipse.org/cdt/ 2、开源工具 Dev-C++和 wxDev-C++第一章 C++ 基础知识 (Basics of C++)1. C++程序结构 Structure of a program 2. 变量和数据类型Variables and Data types 3. 常量Constants 4. 操作符/运算符Operators 5. 控制台交互Communication through console1.1 C++程序结构 (Structure of a program)下面我们从一个最简单的程序入手看一个 C++程序的组成结构。 // my first program in C++ #include &iostream.h&int main() { cout && “Hello World!”;6 / 178 return 0; } Hello World!上面左侧显示了我们的第一个程序的源代码,代码文件名称为 hellowworld.cpp。右边 显示了程序被编译执行后的输出结果。编辑和编译一个程序的方法取决于你用的是什 么编译器,根据它是否有图形化的界面及版本的不同,编译方法也有可能不同,具体 请参照你所使用的编译器的使用说明。 以上程序是多数初学者学会写的第一个程序,它的运行结果是在屏幕上打出”Hello World!”这句话。 虽然它可能是 C++可写出的最简单的程序之一,但其中已经包含了 每一个 C++程序的基本组成结构。 下面我们就逐个分析其组成结构的每一部分: // my first program in C++ 这是注释行。所有以两个斜线符号(//)开始的程序行都被认为是注释行,这些注释行是 程序员写在程序源代码内,用来对程序作简单解释或描述的, 对程序本身的运行不会 产生影响。在本例中, 这行注释对本程序是什么做了一个简要的描述。 # include & iostream.h & 以#标志开始的句子是预处理器的指示语句。它们不是可执行代码,只是对编译器作出 指示。在本例中这个句子# include & iostream.h & 告诉编译器的预处理器将输入输出 流的标准头文件(iostream.h)包括在本程序中。这个头文件包括了 C++中定义的基本标 准输入-输出程序库的声明。此处它被包括进来是因为在本程序的后面部分中将用到它 的功能。 C++标准函数库的所有元素都被声明在一个名空间中,这就是 std 名空间。因此为了 能够访问它的功能,我们用这条语句来表达我们将使用标准名空间中定义的元素。这 条语句在使用标准函数库的 C++程序中频繁出现,本教程中大部分代码例子中也将用 到它。 int main() 这一行为主函数(main function)的起始声明。main function 是所有 C++程序的运行的 起始点。 不管它是在代码的开头,结尾还是中间 C 此函数中的代码总是在程序开始运 行时第一个被执行。并且,由于同样的原因,所有 C++程序都必须有一个 main function。7 / 178 main 后面跟了一对圆括号(),表示它是一个函数。C++中所有函数都跟有一对圆括 号 (),括号中可以有一些输入参数。如例题中显示,主函数(main function)的内容 紧跟在它的声明之后,由花括号 ({})括起来。 cout && “Hellow World!”; 这个语句在本程序中最重要。 cout 是 C++中的标准输出流(通常为控制台,即屏幕), 这句话把一串字符串(本例中为”Hello World”)插入输出流(控制台输出)中。 cout 在的声明在头文件 iostream.h 中,所以要想使用 cout 必须将该头文件包括在程 序开始处。 注意这个句子以分号(;)结尾 。分号标示了一个语句的结束,C++的每一个语句都必须 以分号结尾。 (C++ 程序员最常犯的错误之一就是忘记在语句末尾写上分号) 。 return 0; 返回语句(return) 引起主函数 main()执行结束,并将该语句后面所跟代码(在本例中为 0) 返回。这是在程序执行没有出现任何错误的情况下最常见的程序结束方式。在后面 的例子中你会看到所有 C++程序都以类似的语句结束。你可能注意到并不是程序中的所有的行都会被执行。程序中可以有注释行(以//开 头),有编译器预处理器的指示行(以#开头),然后有函数的声明(本例中 main 函 数),最后是程序语句(例如调用 cout &&),最后这些语句行全部被括在主函数的 花括号({})内。 本例中程序被写在不同的行中以方便阅读。其实这并不是必须的。例如,以下程序 int main () { cout && & Hello World &; return 0; } 也可以被写成: int main () { cout && & Hello World &; return 0; } 以上两段程序是完全相同的。8 / 178 在 C++中,语句的分隔是以分号(;)为分隔符的。分行写代码只是为了更方便人阅读。 以下程序包含更多的语句: // my second program in C++ #include &iostream.h&int main () { cout && &Hello World! &; cout && &I'm a C++ program&; return 0; } Hello World! I'm a C++ program在这个例子中,我们在两个不同的语句中调用了 cout && 函数两次。再一次说明分行 写程序代码只是为了我们阅读方便,因为这个 main 函数也可以被写为以下形式而没有 任何问题: int main () { cout && & Hello World! &; cout && & I'm to C++ program &; return 0; }为方便起见,我们也可以把代码分为更多的行来写: int main () { cout && &Hello World!&; cout && &I'm a C++ program&; return 0; } 它的运行结果将和上面的例子完全一样。 这个规则对预处理器指示行(以#号开始的行)并不适用,因为它们并不是真正的语 句。它们由预处理器读取并忽略,并不会生成任何代码。因此他们每一个必须单独成 行,末尾不需要分号(;)9 / 178 注释 (Comments) 注释(comments)是源代码的一部分,但它们会被编译器忽略。它们不会生成任何执行 代码。 使用注释的目的只是使程序员可以在源程序中插入一些说明解释性的内容。 C++ 支持两中插入注释的方法: // line comment /* block comment */ 第一种方法为行注释,它告诉编译器忽略从//开始至本行结束的任何内容。第二种为 块注释(段注释),告诉编译器忽略在/*符号和*/符号之间的所有内容,可能包含多 行内容。 在以下我们的第二个程序中,我们插入了更多的注释。 /* my second program in C++ with more comments */#include &iostream.h&int main () { cout && &Hello World! &; // says Hello World! cout && &I'm a C++ program&; // says I'm a C++ program return 0; } Hello World! I'm a C++ program如果你在源程序中插入了注释而没有用//符号或/*和*/符号,编译器会把它们当成 C++的语句,那么在编译时就会出现一个或多个错误信息。1.2 变量和数据类型 (Variables and Data types )你可能觉得这个“Hellow World”程序用处不大。我们写了好几行代码,编译,然后 执行生成的程序只是为了在屏幕上看到一句话。的确,我们直接在屏幕上打出这句话10 / 178 会更快。但是编程并不仅限于在屏幕上打出文字这么简单的工作。为了能够进一步写 出可以执行更有用的任务的程序,我们需要引入变量(variable)这个的概念。 让我们设想这样一个例子,我要求你在脑子里记住 5 这个数字,然后再记住 2 这个数 字。你已经存储了两个数值在你的记忆里。现在我要求你在我说的第一个数值上加 1,你应该保留 6 (即 5+1)和 2 在你的记忆里。现在如果我们将两数相减可以得到结 果 4。 所有这些你在脑子里做的事情与计算机用两个变量可以做的事情非常相似。同样的处 理过程用 C++来表示可以写成下面一段代码: a = 5; b = 2; a = a + 1; result = a -很明显这是一个很简单的例子,因为我们只用了两个小的整数数值。但是想一想你的 电脑可以同时存储成千上万这样的数值,并进行复杂的数学运算。 因此,我们可以将变量(variable)定义为内存的一部分,用以存储一个确定的值。 每一个变量 (variable)需要一个标识,以便将它与其他变量相区别,例如,在前面的代 码中,变量标识是 a, b, 和 result。我们可以给变量起任何名字,只要它们是有效的标 识符。标识(Identifiers) 有效标识由字母(letter),数字(digits)和下划线 ( _ )组成。标识的长度没有限制,但是 有些编译器只取前 32 个字符(剩下的字符会被忽略)。 空格(spaces),标点(punctuation marks)和符号(symbols) 都不可以出现在标识中。 只 有字母(letters),数字(digits) 和下划线(_)是合法的。并且变量标识必须以字母开头。 标识也可能以下划线(_)开头,但这种标识通常是保留给为外部连接用的。标识不可 以以数字开头。 必须注意的另一条规则是当你给变量起名字时不可以和 C++语言的关键字或你所使用 的编译器的特殊关键字同名,因为这样与这些关键字产生混淆。例如,以下列出标准 保留关键字,他们不允许被用作变量标识名称:11 / 178 asm, auto, bool, break, case, catch, char, class, const, const_cast, continue, default, delete, do, double, dynamic_cast, else, enum, explicit, extern, false, float, for, friend, goto, if, inline, int, long, mutable, namespace, new, operator, private, protected, public, register, reinterpret_cast, return, short, signed, sizeof, static, static_cast, struct, switch, template, this, throw, true, try, typedef, typeid, typename, union, unsigned, using, virtual, void, volatile, wchar_t, while 另外,不要使用一些操作符的替代表示作为变量标识,因为在某些环境中它们可能被 用作保留词: and, and_eq, bitand, bitor, compl, not, not_eq, or, or_eq, xor, xor_eq 你的编译器还可能包含一些特殊保留词,例如许多生成 16 位码的编译器(比如一些 DOS 编译器)把 far, huge 和 near 也作为关键字。 非常重要:C++语言是“ 大小写敏感”(“case sensitive”) 的,即同样的名字字母大 小写不同代表不同的变量标识。因此,例如变量 RESULT,变量 result 和变量 Result 分别表示三个不同的变量标识.基本数据类型(Fundamental Data types) 编程时我们将变量存储在计算机的内存中,但是计算机要知道我们要用这些变量存储 什么样的值,因为一个简单的数值,一个字符,或一个巨大的数值在内存所占用的空 间是不一样的。 计算机的内存是以字节(byte)为单位组织的。一个字节(byte)是我们在 C++中能够 操作的最小的内存单位。一个字节(byte)可以存储相对较小数据:一个单个的字符或一 个小整数(通常为一个 0 到 255 之间的整数)。但是计算机可以同时操作处理由多个 字节组成复杂数据类型,比如长整数(long integers)和小数(decimals)。以下列表总 结了现有的 C++基本数据类型,以及每一类型所能存储的数据范围: 数据类型(DATA TYPES) 名称 char 字节数* 1 描述 范围* 有符号字符(character)或整数(integer ), 8 位(bits)长(signed): -128 到 127 无符号(unsigned): 0 到 255 short int (short) -32768 到 32767 2 短整数(integer )16 位(bits)长 有符号(signed):12 / 178 无符号(unsigned): 0 到 65535 long int (long) 4 长整数(integer )32 位(bits)长 有符号(signed):- 到
无符号(unsigned): 0 到
int 4 整数(integer) 有符号(signed): - 到 无符号(unsigned): 0 到
float 4 浮点数(floating point number) 3.4e + / - 38 (7 个数字(7digits)) double 8 双精度浮点数(double precision floating point number) 308 (15 digits) long double number) bool false 1 8 1.7e + / -长双精度浮点数(long double precision floating point1.7e + / - 308 (15 digits) 布尔 Boolean 值。它只能是真(true)或假(false)两值之一。 true 或 宽字符(Wide character) 。这是为存储两字节(2 bytes) 长的国 一个宽字符(1 wide characters)wchar_t2际字符而设计的类型。* 字节数一列和范围一列可能根据程序编译和运行的系统不同而有所不同。这里列出 的数值是多数 32 位系统的常用数据。对于其他系统,通常的说法是整型(int)具有根据 系统结构建议的自然长度(即一个字 one word 的长度),而 4 中整型数据 char, short, int, long 的长度必须是递增的,也就是说按顺序每一类型必须大于等于其前面一个类 型的长度。同样的规则也适用于浮点数类型 float, double 和 long double,也是按递增 顺序。 除以上列出的基本数据类型外,还有指针(pointer)和 void 参数表示类型,我们将在 后面看到。 变量的声明(Declaration of variables) 在 C++中要使用一个变量必须先声明(declare)该变量的数据类型。声明一个新变量 的语法是写出数据类型标识符(例如 int, short, float...) 后面跟一个有效的变量标识名 称。例如:13 / 178
以上两个均为有效的变量声明(variable declaration)。第一个声明一个标识为 a 的整 型变量(int variable),第二个声明一个标识为 mynumber 的浮点型变量(float variable)。声明之后,我们就可以在后面的程序中使用变量 a 和 mynumber 了。 如果你需要声明多个同一类型的变量,你可以将它们缩写在同一行声明中,在标识之 间用逗号(comma) 分隔。例如: int a, b, 以上语句同时定义了 a、b、c 3 个整型变量,它与下面的写法完全等同: 整型数据类型 (char, short, long 和 int) 可以是有符号的(signed)或无符号的 (unsigned ),这取决于我们需要表示的数据范围。有符号类型(signed)可以表示正 数和负数,而无符号类型(unsigned)只能表示正数和 0。在定义一个整型数据变量时可 以在数据类型前面加关键字 signed 或 unsigned 来声明数据的符号类型。例如: unsigned short NumberOfS signed int MyAccountB 如果我们没有特别写出 signed 或 unsigned,变量默认为 signed,因此以上第二个声明 我们也可以写成: int MyAccountB 因为以上两种表示方式意义完全一样,因此我们在源程序通常省略关键字 signed 。 唯一的例外是字符型(char)变量,这种变量独立存在,与 signed char 和 unsigned char 型均不相同。 short 和 long 可以被单独用来表示整型基本数据类型,short 相当于 short int, long 相当于 long int。也就是说 和 两种声明是等价的。 最后,signed 和 unsigned 也可以被单独用来表示简单类型,意思分别同 signed int 和 unsigned int 相同,即以下两种声明互相等同: unsigned MyBirthY unsigned int MyBirthY14 / 178 下面我们就用 C++代码来解决在这一节开头提到的记忆问题,来看一下变量定义是如 何在程序中起作用的。 // operating with variables#include &iostream.h&int main () { // declaring variables: int a,// process: a = 5; b = 2; a = a + 1; result = a -// print out the result: cout &&// terminate the program: return 0; } 4如果以上程序中变量声明部分有你不熟悉的地方,不用担心,我们在后面的章节中很 快会学到这些内容。变量的范围(Scope of variables)15 / 178 所有我们要使用的变量都必须事先声明过。C和C++语言的一个重要区别是,在 C++ 语言中我们可以在源程序中任何地方声明变量,甚至可以在两个可执行(excutable)语 句的中间声明变量,而不象在 C 语言中变量声明只能在程序的开头部分。 然而,我们还是建议在一定程度上遵循 C 语言的习惯来声明变量,因为将变量声明放 在一处对 debug 程序有好处。因此,传统的 C 语言方式的变量声明就是把变量声明放 在每一个函数(function)的开头(对本地变量 local variable)或直接放在程序开头所有 函数(function)的外面(对全局变量 global variable)。 一个变量可以是本地(local)范围内有效,叫做本地变量,也可以是全局(global)范围内 有效,叫做全局变量。全局变量要定义在一个源码文件的主体中,所有函数(包括主函 数 main())之外。而本地变量定义在一个函数甚至只是一个语句块单元中。如下图所 示: 全局变量 Global variables 可以在程序中任何地方任何函数(function)中被引用,只 要是在变量的声明之后。 本地变量 local variables 的作用范围被局限在声明它的程序范围内。如果它们是在一个 函数的开头被声明的(例如 main 函数),它们的作用范围就是整个 main 函数。在左 图的例子中,这就意味着如果在 main 函数外还另有一个函数,main 函数中声明的本 地变量(Age, ANumber, AnotherOne) 不能够被另一个函数使用,反之亦然。 在 C++中,本地变量(local variable)的作用范围被定义在声明它的程序块内(一个程 序块是被一对花括号(curly brackets{})括起来的一组语句)。如果变量是在一个函 数(function)中被声明的,那么它是一个函数范围内的变量,如果变量是在一个循环中 (loop)中被声明的,那么它的作用范围只是在这个循环(loop)之中,以此类推。 除本地和全局范围外,还有一种外部范围,它使得一个变量不仅在同一源程序文件中 可见,而且在其他所有将被链接在一起的源文件中均可见。变量初始化(Initialization of variables) 当一个本地变量( local variable)被声明时,它的值默认为未定(undetermined)。但你可 能希望在声明变量的同时赋给它一个具体的值。要想达到这个目的,需要对变量进行 初始化。C++中有两种初始化方法: 第一种,又叫做类 C (c-like) 方法,是在声明变量的时候加上一个等于号,并在后面跟 上想要的数值: type identifier = initial_16 / 178 例如,如果我们想声明一个叫做 a 的 int 变量并同时赋予它 0 这个值,我们可以这样 写: int a = 0; 另外一种变量初始化的方法,又叫做构造函数(constructor)初始化, 是将初始值用小 括号(parenthesis ())括起来: type identifier (initial_value) ; 例如: int a (0); 在 C++.中以上两种方法都正确并且两者等同 。 // 变量初始化#include &iostream&int main () { int a=5; // 初始值为 5int b(2); // 初始值为 2 // 不确定初始值a = a + 3; result = a - cout &&return 0; } 6字符串 (strings)17 / 178 字符串是用来存储一个以上字符的非数字值的变量。 C++提供一个 string 类来支持字符串的操作,它不是一个基本的数据类型,但是在一 般的使用中与基本数据类型非常相似。 与普通数据类型不同的一点是,要想声明和使用字符串类型的变量,需要引用头文件 &string&,并且使用 using namespace 语句来使用标准名空间(std),如下面例子所 示: // C++字符串例题 #include &iostream& #include &string&int main () { string mystring = &This is a string&; cout && return 0; } This is a string如上面例子所示,字符串变量可以被初始化为任何字符串值,就像数字类型变量可以 被初始化为任何数字值一样。 以下两种初始化格式对字符串变量都是可以使用的: string mystring = &This is a string&; string mystring (&This is a string&); 字符串变量还可以进行其他与基本数据类型变量一样的操作,比如声明的时候不指定 初始值,和在运行过程中被重新赋值。 // C++字符串例题 2 #include &iostream& #include &string&18 / 178 int main () { mystring = &This is the initial string content&; cout && mystring && mystring = &This is a different string content&; cout && mystring && return 0; } This is the initial string contentThis is a different string content 要了解更加详细的 C++字符串操作,建议参考 Cplusplus 上的 string 类 reference。 1.3 常量 (Constants ) 一个常量(constant)是一个有固定值的表达式。字(Literals) 字是用来在程序源码中表达特定的值。在前面的内容中我们已经用了很多的字来给变 量赋予特定的值。例如: a = 5;这句代码中 5 就是一个字常量。 字常量(literal constant)可以被分为整数(Integer Numbers), 浮点数(Floating-Point Numbers),字符(Characters)和字符串(Strings)。整数(Integer Numbers) 19 / 178 -273 他们是整型常数,表示十进制整数值。注意表示整型常数时我们不需要些引号 (quotes (&))或任何特殊字符。毫无疑问它是个常量:任何时候当我们在程序中写 1776,我们指的就是 1776 这个数值。 除十进制整数另外, C++还允许使用八进制(octal numbers)和十六进制 (hexadecimal numbers)的字常量(literal constants)。如果我们想要表示一个八进 制数,我们必须在它前面加上一个 0 字符(zero character),而表示十六进制数我们需 要在它前面加字符 0x (zero, x)。例如以下字常量(literal constants)互相等值: 75 // 十进制 decimal0113 // 八进制 octal 0x4b // 十六进制 hexadecimal 所有这些都表示同一个整数: 75 (seventy five) ,分别以十进制数,八进制数和十六 进制数表示。 像变量一样,常量也是有数据类型的。默认的整数字常量的类型为 int 型。我们可以通 过在后面加字母 u 或 l 来迫使它为无符号(unsigned)的类型或长整型(long)。 75 75u 75l 75ul // int // unsigned int // long // unsigned long这里后缀u和l可以是大写,也可以是小写。浮点数(Floating Point Numbers) 浮点数以小数(decimals)和/或指数幂( exponents)的形式表示。它们可以包括一 个小数点,一个 e 字符(表示&by ten at the Xth height&,这里 X 是后面跟的整数 值) ,或两者都包括。 3.14159 // 3.e23 // 6.02 x 10^e-19 // 1.6 x 10^-1920 / 178 3.0// 3.0以上是包含小数的以C++表示的4个有效数值。第一个是 PI,第二个是 Avogadro 数 之一,第三个是一个电子(electron)的电量(electric charge)(一个极小的数值) C 所有这些都是近似值。最后一个是浮点数字常量表示数 3。 浮点数的默认数据类型为 double。如果你想使用 float 或 long double 类型,可以在后 面加 f 或 l 后缀,同样大小写都可以: 3.14159L // long double 6.02e23f // float字符和字符串(Characters and strings) 此外还有非数字常量,例如: 'z' 'p' &Hello world& &How do you do?& 前两个表达式表示单独的字符(character),后面两个表示由若干字符组成的字符串 (string) 。注意在表示单独字符的时候,我们用单引号(single quotes (')),在表示字 符串或多于一个字符的时候我们用双引号(double quotes (&))。 当以常量方式表示单个字符和字符串时,必须写上引号以便把他们和可能的变量标识 或保留字区分开,注意以下例子: x 'x' x 指一个变量名称为 x, 而'x'指字符常量'x'。 字符常量和字符串常量各有特点,例如 escape codes,这些是除此之外无法在源程序 中表示的特殊的字符,例如换行符 newline (\n) 或跳跃符 tab (\t)。所有这些符号前面 要加一个反斜杠 inverted slash (\)。这里列出了这些 escape codes: \n \r 换行符 newline 回车 carriage return21 / 178 \t \v \b \f \a \' \& \? \\ 例如: '\n' '\t'跳跃符 tabulation 垂直跳跃 vertical tabulation backspace page feed 警告 alert (beep) 单引号 single quotes (') 双引号 double quotes (&) 问号 question (?) 反斜杠 inverted slash (\)&Left \t Right& &one\ntwo\nthree& 另外你可以数字 ASCII 码表示一个字符,这种表示方式是在反斜杠(\)之后加以 8 进制 数或十六进制数表示的 ASCII 码。在第一种(八进制 octal)表示中,数字必需紧跟反 斜杠(例如\23 或\40),第二种(十六进制 hexacedimal),必须在数字之前写一个 x 字符 (例如\x20 或\x4A)。 如果每一行代码以反斜杠 inverted slash (\)结束,字符串常量可以分多行代码表示: &string expressed in \ two lines& 你还可以将多个被空格 blankspace、跳跃符 tabulator、换行符 newline 或其他有效空 白符号分隔开的字符串常量连接在一起: &we form& &a single& &string& &of characters& 最后如果我们想让字符串使用宽字符(wchar_t),而不是窄字符(char),可以在常量的 前面加前缀 L: L&This is a wide character string&22 / 178 宽字符通常用来存储非英语字符,比如中文字符,一个字符占两个字节。 布尔型常量(Boolean Literals) 布尔型只有两个有效的值:true 和 false,其数据类型为 bool。定义常量 Defined constants (#define) 使用预处理器指令#define,你可以将那些你经常使用的常量定义为你自己取的名字而 不需要借助于变量。它的格式是: #define identifier value 例如: #define PI 3. #define NEWLINE '\n' #define WIDTH 100 以上定义了三个常量。一旦做了这些声明,你可以在后面的程序中使用这些常量,就 像使用其它任何常量一样,例如: circle = 2 * PI * cout && NEWLINE; 实际上编译器在遇到#define 指令的时候做的只是把任何出现这些 常量名(在前面的 例子中为 PI, NEWLINE 或 WIDTH)的地方替换成他们被定义为的代码(分别为 3., '\n'和 100)。因此,由#define 定义的常量被称为宏常量 macro constants。 #define 指令不是代码语句,它是预处理器指令,因此指令行末尾不需要加分号 semicolon (;) 。如果你在宏定义行末尾加了分号(;) ,当预处理器在程序中做常量替换 的时候,分号也会被加到被替换的行中,这样可能导致错误。声明常量 declared constants (const) 通过使用 const 前缀,你可以定义指定类型的常量,就像定义一个变量一样: const int width = 100; const char tab = '\t';23 / 178 const zip = 12440; 如果没有指定类型(如上面最后例子中最后一行),编译器会假设常量为整型 int。 1.4 操作符/运算符(Operators) 前面已经学习了变量和常量,我们可以开始对它们进行操作,这就要用到 C++的操作 符。有些语言,很多操作符都是一些关键字, 比如 add, equals 等等。C++的操作符 主要是由符号组成的。这些符号不在字母表中,但是在所有键盘上都可以找到。这个 特点使得 C++程序更简洁,也更国际化。运算符是 C++语言的基础,所以非常重要。 你不需要背下所有这一小节的内容,这些细节知识仅供你以后需要时参考 。 赋值 Assignation (=) 赋值运算符的功能是将一个值赋给一个变量。 a = 5; 将整数 5 赋给变量 a。= 运算符左边的部分叫做 lvalue (left value),右边的部分叫做 rvalue (right value)。lvalue 必须是一个变量,而右边的部分可以是一个常量,一个变 量,一个运算(operation)的结果或是前面几项的任意组合。 有必要强调赋值运算符永远是将右边的值赋给左边,永远不会反过来。 a = 将变量 b (rvalue)的值赋给变量 a (lvalue),不论 a 当时存储的是什么值。同时考虑到 我们只是将 b 的数值赋给 a,以后如果 b 的值改变了并不会影响到 a 的值. 例如:如果我们使用以下代码(变量值的变化显示在绿色注释部分): // 赋值符号例子#include &iostream&int main () { int a, a = 10; // a:?, b:? // a:10, b:?24 / 178 b = 4; a = b = 7;// a:10, b:4 // a:4, b:4 // a:4, b:7cout && &a:&; cout && cout && & b:&; cout &&return 0; } a:4 b:7以上代码结果是 a 的值为 4, b 的值为 7。最后一行中 b 的值被改变并不会影响到 a, 虽然在此之前我们声明了 a = (从右到左规则 right-to-left rule)。 C++拥有而其他语言没有的一个特性是赋值符 (=) 可以被用作另一个赋值符的 rvalue (或 rvalue 的一部分) 。例如: a = 2 + (b = 5); 等同于: b = 5; a = 2 + 它的意思是:先将 5 赋给变量 b,然后把前面对 b 的赋值运算的结果(即 5)加上 2 再 赋给变量 a,这样最后 a 中的值为 7。因此,下面的表达式在 C++中也是正确的: a = b = c = 5; //将 5 同时赋给 3 个变量 a, b 和 c。数学运算符 Arithmetic operators ( +, -, *, /, %) C++语言支持的 5 种数学运算符为: ? ? ? + 加 addition - 减 subtraction * 乘 multiplication25 / 178 ? ?/ 除 division % 取模 module加减乘除运算想必大家都很了解,它们和一般的数学运算符没有区别。 唯一你可能不太熟悉的是用百分号(% )表示的取模运算(module)。取模运算是取两 个整数相除的余数。例如,如果我们写 a = 11 %3;,变量 a 的值将会为结果 2,因为 2 是 11 除以 3 的余数。组合运算符 Compound assignation operators (+=, -=, *=, /=, % =, &&=, &&=, &=, ^=, | =) C++以书写简练著称的一大特色就是这些组合运算符 compound assignation operators (+=, -=, *= 和 /= 及其他) ,这些运算符使得只用一个基本运算符就可改写变量的 值: value += 等同于 value = value + a -= 5; 等同于 a = a - 5; a /= 等同于 a = a / price *= units + 1; 等同于 price = price * (units + 1); 其他运算符以此类推。例如: // 组合运算符例子#include &iostream&int main () { int a, b=3; a = a+=2; cout && // 相当于 a=a+226 / 178 return 0; } 5递增和递减 Increase and decrease 书写简练的另一个例子是递增(increase)运算符 (++)和递减(decrease) 运算符(-)。它们使得变量中存储的值加 1 或减 1。它们分别等同于+=1 和-=1。因此: a++; a+=1; a=a+1; 在功能上全部等同,即全部使得变量 a 的值加 1。 它的存在是因为最早的 C 编译器将以上三种表达式的编译成不同的机器代码,不同的 机器代码运行速度不一样。现在,编译器已经基本自动实行代码优化,所以以上三种 不同的表达方式编译成的机器代码在实际运行上已基本相同。 这个运算符的一个特点是它既可以被用作 prefix 前缀,也可以被用作后缀 suffix,也就 是说它既可以被写在变量标识的前面(++a),也可以被写在后面(a++)。虽然在简单表 达式如 a++或++a 中,这两种写法代表同样的意思,但当递增 increase 或递减 decrease 的运算结果被直接用在其它的运算式中时,它们就代表非常不同的意思了: 当递增运算符被用作前缀 prefix (++a) 时,变量 a 的值线增加,然后再计算整个表达 式的值,因此增加后的值被用在了表达式的计算中;当它被用作后缀 suffix (a++)时, 变量 a 的值在表达式计算后才增加,因此 a 在增加前所存储的值被用在了表达式的计 算中。注意以下两个例子的不同: 例1 B=3; A=++B; // A 的值为 4, B 的值为 4 A=B++; // A 的值为 3, B 的值为 4 在第一个例子中,B 在它的值被赋给 A 之前增加 1。而在第二个例子中 B 原来的值 3 被 赋给 A 然后 B 的值才加 1 变为 4。 B=3; 例227 / 178 关系运算符 Relational operators ( ==, !=, &, &, &=, &= ) 我们用关系运算符来比较两个表达式。如 ANSI-C++ 标准中指出的,关系预算的结果 是一个 bool 值,根据运算结果的不同,它的值只能是真 true 或 false。 例如我们想通过比较两个表达式来看它们是否相等或一个值是否比另一个的值大。以 下为 C++的关系运算符: == != & & &= &= 相等 Equal 不等 Different 大于 Greater than 小于 Less than 大于等于 Greater or equal than 小于等于 Less or equal than下面你可以看到一些实际的例子: (7 == 5) 将返回 false.(5 & 4)将返回 true. (3 != 2) (6 &= 6) 将返回 true. 将返回 true.(5 & 5)将返回 false. 当然,除了使用数字常量,我们也可以使用任何有效表达式,包括变量。假设有 a=2, b=3 和 c=6, (a == 5) 将返回 false.(a*b &= c)将返回 true 因为它实际是(2*3 &= 6)(b+4 & a*c)将返回 false 因为它实际是(3+4 & 2*6)28 / 178 ((b=2) == a) 将返回 true. 注意:运算符= (单个等号)不同于运算符== (双等号)。第一个是赋值运算符(将等号右 边的表达式值赋给左边的变量);第二个(==)是一个判断等于的关系运算符,用来判断 运算符两边的表达式是否相等。因此在上面例子中最后一个表达式((b=2) == a),我 们首先将数值 2 赋给变量 b,然后把它和变量 a 进行比较。因为变量 a 中存储的也是 数值 2,所以整个运算的结果为 true。 在 ANSI-C++标准出现之前的许多编译器中,就像 C 语言中,关系运算并不返回值为 真 true 或假 false 的 bool 值,而是返回一个整型数值最为结果,它的数值可以为 0, 代表&false&或一个非 0 数值(通常为 1)来代表&true&。逻辑运算符 Logic operators ( !, &&, | |) 运算符 ! 等同于 boolean 运算 NOT (取非),它只有一个操作数(operand),写在它 的右边。它做的唯一工作就是取该操作数的反面值,也就是说如果操作数值为真 true,那么运算后值变为假 false,如果操作数值为假 false,则运算结果为真 true。它 就好像是说取与操作数相反的值。例如: !(5 == 5) !(6 &= 4) !true 返回 false,因为它右边的表达式(5 == 5)为真 true. 返回 true 因为(6 &= 4)为假 false.返回假 false.!false 返回真 true. 逻辑运算符&&和| | 是用来计算两个表达式而获得一个结果值。它们分别对应逻辑运算 中的与运算 AND 和或运算 OR。它们的运算结果取决于两个操作数(operand)的关 系: 第一个操作数 a b 第二个操作数 结果a && b 结果 a| |b true true true true29 / 178 true false falsefalse true falsefalse false falsetrue true false例如 : ( (5 == 5) && (3 & 6) ) 返回 false ( true && false ). ( (5 == 5) | |(3 & 6)) 返回 true ( true | |false ).条件运算符 Conditional operator ( ? ) 条件运算符计算一个表达式的值并根据表达式的计算结果为真 true 或假 false 而返回不 同值。它的格式是: condition ? result1 : result2 (条件?返回值 1:返回值 2) 如果条件 condition 为真 true,整个表达式将返回 esult1,否则将返回 result2。 7==5 ? 4 : 3 返回 3,因为 7 不等于 5. 7==5+2 ? 4 : 3 5&3 ? a : b a&b ? a : b 返回 4,因为 7 等于 5+2.返回 a,因为 5 大于 3. 返回较大值,a 或 b.// 条件运算符例子#include &iostream&int main () { int a,b,c;a=2;30 / 178 b=7; c = (a&b) ? a :cout &&return 0; } 7上面的例子中 a 的值为 2,b 的值为 7,所以表达式(a&b)运算值为假(false),所以整个 表达式(a&b)?a:b 要取分号后面的值,也就是 b 的值 7。因此最后输出 c 的值为 7。逗号运算符 ( , ) 逗号运算符 (,) 用来分开多个表达式,并只取最右边的表达式的值返回。例如有以下代码: a = (b=3, b+2);这行代码首先将 3 赋值给变量 b,然后将 b+2 赋值给变量 a。所以最后变量 a 的值为 5,而变量 b 的值为 3。 位运算符 Bitwise Operators ( &, | , ^, ~, &&, && ) 位运算符以比特位改写变量存储的数值,也就是改写变量值的二进制表示: op & | ^ ~ && && asm AND OR XOR NOT SHL SHR Description 逻辑与 Logic AND 逻辑或 Logic OR 逻辑异或 Logical exclusive OR 对 1 取补(位反转)Complement to one (bit inversion) 左移 Shift Left 右移 Shift Right31 / 178 变量类型转换运算符 Explicit type casting operators 变量类型转换运算符可以将一种类型的数据转换为另一种类型的数据。在写 C++中有 几种方法可以实现这种操作,最常用的一种,也是与 C 兼容的一种,是在原转换的表 达式前面加用括号()括起的新数据类型: float f = 3.14; i = (int) 以上代码将浮点型数字 3.14 转换成一个整数值(3)。这里类型转换操作符为(int)。在 C++中实现这一操作的另一种方法是使用构造函数 constructor 的形式:在要转换的表 达式前加变量类型并将表达式括在括号中: i = int ( f ); 以上两种类型转换的方法在 C++中都是合法的。另外 ANSI-C++针对面向对象编程 (object oriented programming)增加了新的类型转换操作符 (参考 Section 5.4, Advanced class type-casting).sizeof() 这个运算符接受一个输入参数,该参数可以是一个变量类型或一个变量自己,返回该 变量类型(variable type) 或对象(object)所占的字节数: a = sizeof (char); 这将会返回 1 给 a,因为 char 是一个常为 1 个字节的变量类型。 sizeof 返回的值是一个常数,因此它总是在程序执行前就被固定了。其它运算符 在本教程后面的章节里我们将看到更多的运算符,比如指向指针的运算或面向对象编 程特有的运算,等等,我们会在它们各自的章节里进行详细讨论。运算符的优先度 Precedence of operators32 / 178 当多个操作数组成复杂的表达式时,我们可能会疑惑哪个运算先被计算,哪个后被计 算。例如以下表达式: a = 5 + 7 %2 我们可以怀疑它实际上表示: a = 5 + (7 %2) 结果为 6,还是 a = (5 + 7) %2 结果为 0? 正确答案为第一个,结果为 6。每一个运算符有一个固定的优先级,不仅对数学运算 符(我们可能在学习数学的时候已经很了解它们的优先顺序了),所有在 C++中出现 的运算符都有优先级。从最从最高级到最低级,运算的优先级按下表排列: 优先级 Level 操作符 Operator Description Grouping 1 2 :: 范围 从左到右 说明 结合方向() [] . -& ++ -- dynamic_cast static_cast reinterpret_cast const_cast typeid 后缀 从左到右 ++ -- ~ ! sizeof new delete 一元(前缀) *& +指针和取地址 一元符号 从右到左 从左到右 从右到左34 5 6 7 8 9 10(type) 类型转换.* -&* 指向成员的指针* / % 乘、除、取模 从左到右 +加减 从左到右 从左到右 关系操作符 从左到右&& &&位移 & & &= &=== != 等于、不等于 从左到右33 / 178 11 12 13 14 15 16 17 18& ^ | && | | ?:按位与运算从左到右按位异或运算 从左到右 按位或运算 逻辑与运算 逻辑或运算 条件运算 从左到右 从左到右 从左到右 从右到左 从右到左= *= /= % = += -= &&= &&= &= ^= | = 赋值运算 , 逗号 从左到右结合方向 Grouping 定义了当有同优先级的多个运算符在一起时,哪一个必须被首先运 算,最右边的还是最左边的。 所有这些运算符的优先级顺序可以通过使用括号 parenthesis signs (和)来控制,而且 更易读懂,例如以下例子: a = 5 + 7 %2; 根据我们想要实现的计算的不同,可以写成: a = 5 + (7 %2); 或者 a = (5 + 7) %2; 所以如果你想写一个复杂的表达式而不敢肯定各个运算的执行顺序,那么就加上括 号。这样还可以使代码更易读懂。 1.5 控制台交互(Communication through console) 控制台(console)是电脑的最基本交互接口,通常包括键盘(keyboard)和屏幕(screen)。 键盘通常为标准输入设备,而 屏幕为标准输出设备。 在 C++的 iostream 函数库中,一个程序的标准输入输出操作依靠两种数据流:cin 给 输入使用和 cout 给输出使用。另外,cerr 和 clog 也已经被实现DD它们是两种特殊设计 的数据流专门用来显示出错信息。它们可以被重新定向到标准输出设备或到一个日志 文件(log file)。 因此 cout (标准输出流)通常被定向到屏幕,而 cin (标准输入流)通常被定向到键盘。34 / 178 通过控制这两种数据流,你可以在程序中与用户交互,因为你可以在屏幕上显示输出 并从键盘接收用户的输入。输出 Output (cout) 输出流 cout 与重载(overloaded)运算符&&一起使用: cout && &Output sentence&; // 打印 Output sentence 到屏幕上 cout && 120; // 打印数字 120 到屏幕上 cout && // 打印变量 x 的值到屏幕上 运算符&&又叫插入运算符(insertion operator) 因为它将后面所跟的数据插入到它前面 的数据流中。在以上的例子中,字符串常量 Output sentence,数字常量 120 和变量 x 先后被插入输出流 cout 中。注意第一句中字符串常量是被双引号引起来的。每当我们 使用字符串常量的时候,必须用引号把字符串引起来,以便将它和变量名明显的区分 开来。例如,下面两个语句是不同的: cout && &Hello&; // 打印字符串 Hello 到屏幕上 cout && H // 把变量 Hello 存储的内容打印到屏幕上 插入运算符 insertion operator (&&)可以在同一语句中被多次使用: cout && &Hello, & && &I am & && &a C++ sentence&; 上面这一行语句将会打印 Hello, I am a C++ sentence 到屏幕上。插入运算符(&&) 的 重复使用在我们想要打印变量和内容的组合内容或多个变量时有所体现: cout && &Hello, I am & && age && & years old and my zipcode is & && 如果我们假设变量 age 的值为 24,变量 zipcode 的值为 90064,以上句子的输出将 为: Hello, I am 24 years old and my zipcode is 90064 必须注意,除非我们明确指定,cout 并不会自动在其输出内容的末尾加换行符,因此 下面的语句: cout && &This is a sentence.&; cout && &This is another sentence.&; 将会有如下内容输出到屏幕: This is a sentence.This is another sentence.35 / 178 虽然我们分别调用了两次 cout,两个句子还是被输出在同一行。所以,为了在输出中 换行,我们必须插入一个换行符来明确表达这一要求。在 C++中换行符可以写作\n: cout && &First sentence.\n &; cout && &Second sentence.\nThird sentence.&; 将会产生如下输出: First sentence. Second sentence. Third sentence. 另外,你也可以用操作符 endl 来换行,例如: cout && &First sentence.& && cout && &Second sentence.& && 将会输出: First sentence. Second sentence. 当操作符 endl 被用在 buffered streams 中时有一点特殊:它们被 flushed。不过 cout 默认为 unbuffered,所以不会被影响。 你可以暂时不管这一点。 你可以使用\n 或 endl 来指定 cout 输出换行,请注意前面所讲的两者的不同用法。输入 Input (cin) C++中的标准输入是通过在 cin 数据流上重载运算符 extraction (&&) 来实现的。它后 面必须跟一个变量以便存储读入的数据。例如: cin && 声明一个整型变量 age 然后等待用户从键盘输入到 cin 并将输入值存储在这个变量 中。 cin 只能在键盘输入回车键(RETURN)后才能处理前面输入的内容。因此即使你只要求 输入一个单独的字符,在用户按下回车键(RETURN)之前 cin 将不会处理用户的输入的 字符。36 / 178 在使用 cin 输入的时候必须考虑后面的变量类型。如果你要求输入一个整数, extraction (&&) 后面必须跟一个整型变量,如果要求一个字符,后面必须跟一个字符 型变量,如果要求一个字符串,后面必须跟一个字符串型变量。 // i/o example #include &iostream.h& int main () { cout && &Please enter an integer value: &; cin && cout && &The value you entered is & && cout && & and its double is & && i*2 && &.\n&; return 0; } Please enter an integer value: 702The value you entered is 702 and its double is 1404. 使用程序的用户可以使引起错误的原因之一,即使是在最简单的需要用 cin 做输入的程 序中(就像我们上面看到的这个程序)。因为如果你要求输入一个整数数值,而用户 输入了一个名字(一个字符串),其结果可能导致程序产生错误操作,因为它不是我 们期望从用户处获得的数据。当你使用由 cin 输入的数据的时候,你不得不假设程序 的用户将会完全合作而不会在程序要求输入整数的时候输入他的名字。后面当我们看 到怎样使用字符串的时候,我们将会同时看到一些解决这一类出错问题的办法。 你也可以利用 cin 要求用户输入多个数据 : cin && a && 等同于: cin && cin && 在以上两种情况下用户都必须输入两个数据,一个给变量 a,一个给变量 b。输入时两 个变量之间可以以任何有效的空白符号间隔,包括空格,跳跃符 tab 或换行。cin 和字符串37 / 178 我们可以像读取基本类型数据一样,使用 cin 和&&操作符来读取字符串,例如: cin && 但是,cin && 只能读取一个单词,一旦碰到任何空格,读取操作就会停止。在很多时 候这并不是我们想要的操作,比如我们希望用户输入一个英文句子,那么这种方法就 无法读取完整的句子,因为一定会遇到空格。 要一次读取一整行输入,需要使用 C++的函数 getline,相对于是用 cin,我们更建议 使用 getline 来读取用户输入。 例如: // 读取字符串例子 #include &iostream& #include &string&int main () { cout && &What's your name? &; getline (cin, mystr); cout && &Hello & && mystr && &.\n&; cout && &What is your favorite color? &; getline (cin, mystr); cout && &I like & && mystr && & too!\n&; return 0; } What's your name? AquaHello Aqua. What is your favorite color? blue I like blue too! 你可能注意到在上面的例子中,两次调用 getline 函数我们都是用了同一个字符串变量 (mystr)。在第二次调用的时候,程序会自动用第二次输入的内容取代以前的内容。38 / 178 字符串流 (stringstream) 标准头文件 &sstream& 定义了一个叫做 stringstream 的类,使用这个类可以对基于 字符串的对象进行像流(stream)一样的操作。这样,我们可以对字符串进行 抽取和插入操作,这对将字符串与数值互相转换非常有用。例如,如果我们想将一个 字符串转换为一个整数,可以这样写: string mystr (&1204&); stringstream(mystr) && 这个例子中先定义了一个字符串类型的对象 mystr,初始值为&1204&,又定义了一个整 数变量 myint。然后我们使用 stringstream 类的构造函数定义了这个类的对象,并以 字符串变量 mystr 为参数。因为我们可以像使用流一样使用 stringstream 的对象,所 以我们可以像使用 cin 那样使用操作符 && 后面跟一个整数变量来进行提取整数数 据。这段代码执行之后变量 myint 存储的是数值 1204 。 // 字符串流的使用示例 #include &iostream& #include &string& #include &sstream&int main () { float price=0; int quantity=0;cout && &Enter price: &; getline (cin,mystr); stringstream(mystr) && cout && &Enter quantity: &;39 / 178 getline (cin,mystr); stringstream(mystr) && cout && &Total price: & && price*quantity && return 0; } Enter price: 22.25Enter quantity: 7 Total price: 155.75 在这个例子中,我们要求用户输入数值,但不同于从标准输入中直接读取数值,我们 使用函数 getline 从标注输入流 cin 中读取字符串对象(mystr),然后再从这个字符串对 象中提取数值 price 和 quantity。 通过使用这种方法,我们可以对用户的输入有更多的控制,因为它将用户输入与对输 入的解释分离,只要求用户输入整行的内容,然后再对用户输入的内容进行检验操 作。这种做法在用户输入比较集中的程序中是非常推荐使用的。第二章 控制结构和函数(Control structures and Functions ) 1. 控制结构Control Structures 2. 函数 IFunctions I 3. 函数 IIFunctions II 2.1 控制结构(Control Structures) 一个程序的语句往往并不仅限于线性顺序结构。在程序的执行过程中它可能被分成两 支执行,可能重复某些语句,也可能根据一些判断结果而执行不同的语句。因此 C++ 提供一些控制结构语句 (control structures) 来实现这些执行顺序。 为了介绍程序的执行顺序,我们需要先介绍一个新概念:语句块(block of instructions)。一个语句块(A block of instructions) 是一组互相之间由分号 semicolons (;) 分隔开但整体被花括号 curly bracket signs: { and }括起来的语句。40 / 178 本节中我们将看到的大多数控制结构允许一个通用的 statement 做参数,这个 statement 根据需要可以是一条语句,也可以是一组语句组成的语句块。如果我们只需 要一条语句做 statement,它可以不被括在花括号 ({}) 内。但如果我们需要多条语句 共同做 statement,则必须把它们括在花括号内 ({}) 以组成一个语句块。条件结构 Conditional structure: if and else 条件结构用来实现仅在某种条件满足的情况下才执行一条语句或一个语句块。它的形 式是: if (condition) statement 这里 condition 是一个将被计算的表达式(expression)。如果表达式值为真,即条件 (condition)为 true,statement 将被执行。否则,statement 将被忽略(不被执行), 程序从整个条件结构之后的下一条语句继续执行。 例如,以下程序段实现只有当变量 x 存储的值确实为 100 的时候才输出&x is 100&: if (x == 100) cout && &x is 100&; 如果我们需要在条件 condition 为真 true 的时候执行一条以上的语句,我们可以花括号 {}将语句括起来组成一个语句块: if (x == 100) { cout && &x is &; cout && } 我们可以用关键字 else 来指定当条件不能被满足时需要执行的语句,它需要和 if 一起 使用,形式是: if (condition) statement1 else statement2 例如: if (x == 100) cout && &x is 100&; else41 / 178 cout && &x is not 100&; 以上程序如果 x 的值为 100,则在屏幕上打出 x is 100,如果 x 不是 100,而且也只有 在 x 不是 100 的时候,屏幕上将打出 x is not 100。 多个 if + else 的结构被连接起来使用来判断数值的范围。以下例子显示了如何用它来 判断变量 x 中当前存储的数值是正值,负值还是既不正也不负,即等于 0 。 if (x & 0) cout && &x is positive&; else if (x & 0) cout && &x is negative&; else cout && &x is 0&; 记住当我们需要执行多条语句时,必须使用花括号{}将它们括起来以组成一个语句块 block of instructions。重复结构 Iteration structures 或循环 loops 循环 Loops 的目的是重复执行一组语句一定的次数或直到满足某种条件。 while 循环 格式是: while (表达式 expression) 语句 statement 它的功能是当 expression 的值为真 true 时重复执行 statement。 例如,下面我们将用 while 循环来写一个倒计数程序: // custom countdown using while #include &iostream.h& int main () { cout && &Enter the starting number & &; cin &&42 / 178 while (n&0) { cout && n && &, &; --n; } cout && &FIRE!&; return 0; } Enter the starting number & 88, 7, 6, 5, 4, 3, 2, 1, FIRE! 程序开始时提示用户输入一个倒计数的初始值。然后 while 循环开始,如果用户输入 的数值满足条件 n&0 (即 n 比 0 大),后面跟的语句块将会被执行一定的次数,直到条 件 (n&0) 不再满足(变为 false)。 以上程序的所有处理过程可以用以下的描述来解释: 从 main 开始: 1. 2. o o 3. 用户输入一个数值赋给 n. while 语句检查(n&0)是否成立,这时有两种可能: true: 执行 statement (到第 3 步) false: 跳过 statement. 程序直接执行第 5 步. 执行 statement:cout && n && &, &; --n; (将 n 的值打印在屏幕上,然后将 n 的值减 1). 4. 5. 语句块结束,自动返回第 2 步。 继续执行语句块之后的程序:打印 FIRE! ,程序结束。我们必须考虑到循环必须在某个点结束,因此在语句块之内(loop 的 statement 之内) 我们必须提供一些方法使得条件 condition 可以在某个时刻变为假 false,否则循环将 无限重复下去。在这个例子里,我们用语句--n;使得循环在重复一定的次数后变为 false :当 n 变为 0, 倒计数结束。43 / 178 do-while 循环 格式: do 语句 statement while (条件 condition); 它的功能与 while 循环一抹一样,除了在 do-while 循环中是先执行 statement 然后才 检查条件 condition ,而不想 while 循环中先检查条件然后才执行 statement。这样, 即使条件 condition 从来没有被满足过,statement 仍至少被执行一次。例如,下面的 程序重复输出(echoes)用户输入的任何数值,直到用户输入 0 为止。 // number echoer #include &iostream.h& int main () { do { cout && &Enter number (0 to end): &; cin && cout && &You entered: & && n && &\n&; } while (n != 0); return 0; } Enter number (0 to end): 12345You entered: 12345 Enter number (0 to end): 160277 You entered: 160277 Enter number (0 to end): 0 You entered: 0 do-while 循环通常被用在判断循环结束的条件是在循环语句内部被决定的情况下,比 如以上的例子,在循环的语句块内用户的输入决定了循环是否结束。如果用户永远不 输入 0,则循环永远不会结束。 for 循环 格式是:44 / 178 for ( increase) 它的主要功能是当条件 condition 为真 true 时重复执行语句 statement ,类似 while 循 环。但除此之外,for 还提供了写初始化语句 initialization 和增值语句 increase 的地 方。因此这种循环结构是特别为执行由计数器控制的循环而设计的。 它按以下方式工作: 1. 执行初始化 initialization 。通常它是设置一个计数器变量(counter variable)的初始值,初始化仅被执行一次。 2. 检查条件 condition ,如果条件为真 true,继续循环,否则循环结束循环中语句 statement 被跳过。 3. 执行语句 statement 。像以前一样,它可以是一个单独的语句,也可以是一个由花括号{ }括起来的语句块。 4. 最后增值域(increase field)中的语句被执行,循环返回第 2 步。注意增值域中可能是任何语句,而不一定只是将计数器增加的语句。例如下面的例子中计数器实 际为减 1,而不是加 1。 下面是用 for 循环实现的倒计数的例子: // countdown using a for loop #include &iostream.h& int main () { for (int n=10; n&0; n--) { cout && n && &, &; } cout && &FIRE!&; return 0; } 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FIRE!初始化 initialization 和增值 increase 域是可选的(即可以为空)。但这些域为空的时 候,它们和其他域之间间隔的分号不可以省略。例如我们可以写:for (;n&10;)来表示 没有初始化和增值语句;或 for (;n&10;n++) 来表示有增值语句但没有初始化语句。45 / 178 另外我们也可以在 for 循环初始化或增值域中放一条以上的语句,中间用逗号 coma(,) 隔开。例如假设我们想在循环中初始化一个以上的变量,可以用以下的程序来实现: for ( n=0, i=100 ; n!= n++, i-- ) { // whatever here... } 这个循环将被执行 50 次,如果 n 和 i 在循还内部都不被改变的话:n 初始值为 0,i 初始值为 100,条件是(n!=i)(即 n 不能等于 i)。因为每次循环 n 加 1, 而且 i 减 1,循环的条件将会在第 50 次循环之后变为假 false(n 和 i 都等于 50)。 分支控制和跳转(Bifurcation of control and jumps) break 语句 通过使用 break 语句,即使在结束条件没有满足的情况下,我们也可以跳出一个循 环。它可以被用来结束一个无限循环(infinite loop),或强迫循环在其自然结束之前 结束。例如,我们想要在倒计数自然结束之前强迫它停止(也许因为一个引擎故 障): // break loop example #include &iostream.h& int main () { for (n=10; n&0; n--) { cout && n && &, &; if (n==3) { cout && &countdown aborted!&; } return 0;46 / 178 }10, 9, 8, 7, 6, 5, 4, 3, countdown aborted!continue 语句 continue 语句使得程序跳过当前循环中剩下的部分而直接进入下一次循环,就好像循 环中语句块的结尾已经到了使得循环进入下一次重复。例如,下面例子中倒计数时我 们将跳过数字 5 的输出: // continue loop example #include &iostream.h& int main () { for (int n=10; n&0; n--) { if (n==5) cout && n && &, &; } cout && &FIRE!&; return 0; } 10, 9, 8, 7, 6, 4, 3, 2, 1, FIRE!goto 语句 通过使用 goto 语句可以使程序从一点跳转到另外一点。你必须谨慎只用这条语句,因 为它的执行可以忽略任何嵌套限制。 跳转的目标点可以由一个标示符(label)来标明,该标示符作为 goto 语句的参数。一个 标示符(label)由一个标识名称后面跟一个冒号 colon (:)组成。 通常除了底层程序爱好者使用这条语句,它在结构化或面向对象的编程中并不常用。 下面的例子中我们用 goto 来实现倒计数循环: // goto loop example #include &iostream.h& int main () { int n=10; loop:47 / 178 cout && n && &, &; n--; if (n&0) cout && &FIRE!&; return 0; } 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FIRE!exit 函数 exit 是一个在 cstdlib (stdlib.h)库中定义的函数。 exit 的目的是一个特定的退出代码来结束程序的运行,它的原型(prototype)是: void exit (int exit code); exit code 是由操作系统使用或被调用程序使用。通常 exit code 为 0 表示程序正常结 束,任何其他值表示程序执行过程中出现了错误。选择结构 The selective Structure: switch switch 语句的语法比较特殊。它的目标是对一个表达式检查多个可能常量值,有些像 我们在本节开头学习的把几个 if 和 else if 语句连接起来的结构。它的形式是: switch (expression) { case constant1: block of instructions 1 case constant2: block of instructions 2 . . . default: default block of instructions48 / 178 } 它按以下方式执行: switch 计算表达式 expression 的值,并检查它是否与第一个常量 constant1 相等,如 果相等,程序执行常量 1 后面的语句块 block of instructions 1 直到碰到关键字 break ,程序跳转到 switch 选择结构的结尾处。 如果 expression 不等于 constant1,程序检查表达式 expression 的值是否等于第二个 常量 constant2, 如果相等,程序将执行常量 2 后面的语句块 block of instructions 2 直到碰到关键字 break。 依此类推,直到最后如果表达式 expression 的值不等于任何前面的常量(你可以用 case 语句指明任意数量的常量值来要求检查),程序将执行默认区 default: 后面的语 句,如果它存在的话。default: 选项是可以省略的。 下面的两段代码段功能相同: switch example switch (x) { case 1: cout && &x is 1&; case 2: cout && &x is 2&; default: cout && &value of x unknown&; } if (x == 1) { if-else equivalentcout && &x is 1&; } else if (x == 2) { cout && &x is 2&; } else {49 / 178 cout && &value of x unknown&; } 前面已经提到 switch 的语法有点特殊。注意每个语句块结尾包含的 break 语句。这是 必须的,因为如果不这样做,例如在语句块 block of instructions 1 的结尾没有 break,程序执行将不会跳转到 switch 选择的结尾处 (}) ,而是继续执行下面的语句 块,直到第一次遇到 break 语句或到 switch 选择结构的结尾。因此,不需要在每一个 case 域内加花括号{ } 。这个特点同时可以帮助实现对不同的可能值执行相同的语句 块。例如: switch (x) { case 1: case 2: case 3: cout && &x is 1, 2 or 3&; default: cout && &x is not 1, 2 nor 3&; } 注意 switch 只能被用来比较表达式和不同常量的值 constants。因此我们不能够把变量 或范围放在 case 之后,例如 (case (n*2):) 或 (case (1..3):) 都不可以,因为它们不是 有效的常量。 如果你需要检查范围或非常量数值,使用连续的 if 和 else if 语句。 2.2 函数 I(Functions I) 通过使用函数(functions)我们可以把我们的程序以更模块化的形式组织起来,从而利 用 C++所能提供的所有结构化编程的潜力。 一个函数(function)是一个可以从程序其它地方调用执行的语句块。以下是它的格式:type name ( argument1, argument2, ...) statement这里: ? type 是函数返回的数据的类型50 / 178 ? ?name 是函数被调用时使用的名 argument 是函数调用需要传入的参量(可以声明任意多个参量)。每个参量(argument)由一个数据类型后面跟一个标识名称组成,就像变量声明中一样(例如,int x)。参量仅在函数范围内有效,可以和函数中的其它变量一样使用, 它们使得函数在 被调用时可以传入参数,不同的参数用逗号(comma)隔开. ? statement 是函数的内容。它可以是一句指令,也可以是一组指令组成的语句块。如果是一组指令,则语句块必须用花括号{}括起来,这也是我们最常见到情况。 其实为了使程序的格式更加统一清晰,建议在仅有一条指令的时候也使用花括号,这 是一个良好的编程习惯。 下面看一下第一个函数的例子: // function example #include &iostream.h& int addition (int a, int b) { r=a+b; return (r); }int main () { z = addition (5,3); cout && &The result is & && return 0; } The result is 8记得在我们教程开始时说过:一个 C++程序总是从 main 函数开始执行。 因此我们从 那里开始。 我们可以看到 main 函数以定义一个整型变量 z 开始。紧跟着我们看到调用 addition 函数。我们可以看到函数调用的写法和上面函数定义本身十分相似:51 / 178 参数有明显的对应关系。在 main 函数中我们调用 addition 函数,并传入两个数值: 5 和 3 , 它们对应函数 addition 中定义的参数 int a 和 int b。 当函数在 main 中被调用时,程序执行的控制权从 main 转移到函数 addition。调用传 递的两个参数的数值 (5 和 3) 被复制到函数的本地变量(local variables) int a 和 int b 中。 函数 addition 中定义了新的变量(),通过表达式 r=a+b;, 它把 a 加 b 的结果赋给 r 。因为传过来的参数 a 和 b 的值分别为 5 和 3 ,所以结果是 8。 下面一行代码: return (r); 结束函数 addition,并把控制权交还给调用它的函数(main) ,从调用 addition 的地方 开始继续向下执行。另外,return 在调用的时候后面跟着变量 r (return (r);), 它当时 的值为 8, 这个值被称为函数的返回值。函数返回的数值就是函数的计算结果,因此, z 将存储函数 addition (5, 3)返回的数值, 即 8。用另一种方式解释,你也可以想象成调用函数(addition (5,3)) 被替换成了它的 返回值 (8)。 接下来 main 中的下一行代码是: cout && &The result is & && 它把结果打印在屏幕上。 变量的范围(Scope of variables) 你必须考虑到变量的范围只是在定义该变量的函数或指令块内有效,而不能在它的函 数或指令块之外使用。 例如,在上面的例子里就不可能在 main 中直接使用变量 a, b 或 r ,因为它们是函数 addition 的本地变量(local variable)。在函数 addition 中也不 可能直接使用变量 z,因为它是 main 的本地变量。 因此,本地变量 (local variables)的范围是局限于声明它的嵌套范围之内的。尽管如 此,你还可以定义全局变量(global variables),它们可以在代码的任何位置被访问,不 管在函数以内还是以外。要定义全局变量,你必须在所有函数或代码块之外定义它 们,也就是说,直接在程序体中声明它们。52 / 178 这里是另一个关于函数的例子: // function example #include &iostream.h& int subtraction (int a, int b) { r=a-b; return (r); }int main () { int x=5, y=3, z = subtraction (7,2); cout && &The first result is & && z && '\n'; cout && &The second result is & && subtraction (7,2) && '\n'; cout && &The third result is & && subtraction (x,y) && '\n'; z= 4 + subtraction (x,y); cout && &The fourth result is & && z && '\n'; return 0; } The first result is 5The second result is 5 The third result is 2 The fourth result is 6 在这个例子中,我们定义了函数 subtraction。这个函数的功能是计算传入的两个参数 的差值并将结果返回。 在 main 函数中,函数 subtraction 被调用了多次。我们用了几种不同的调用方法,因 此你可以看到在不同的情况下函数如何被调用。53 / 178 为了更好的理解这些例子,你需要考虑到被调用的函数其实完全可以由它所返回的值 来代替。例如在上面例子中第一种情况下 (这种调用你应该已经知道了,因为我们在前 面的例子中已经用过这种形式的调用): z = subtraction (7,2); cout && &The first result is & && 如果我们把函数调用用它的结果(也就是 5)替换,我们将得到: z = 5; cout && &The first result is & && 同样的 cout && &The second result is & && subtraction (7,2); 与前面的调用有同样的结果,但在这里我们把对函数 subtraction 的调用直接用作 cout 的参数。这可以简单想象成我们写的是: cout && &The second result is & && 5; 因为 5 是 subtraction (7,2)的结果。 在 cout && &The third result is & && subtraction (x,y); 中,与前面的调用唯一的不同之处是这里调用 subtraction 时的参数使用的是变量而不 是常量。这样用时毫无问题的。在这个例子里,传入函数 subtraction 的参数值是变量 x 和 y 中存储的数值,即分别为 5 和 3,结果为 2。 第四种调用也是一样的。只要知道除了 z = 4 + subtraction (x,y); 我们也可以写成: z = subtraction (x,y) + 4; 它们的结果是完全一样的。注意在整个表达式的结尾写上分号 semicolon sign (;)。它 并不需要总是跟在函数调用的后面,因为你可以有一次把它们想象成函数被它的结果 所替代: z = 4 + 2; z = 2 + 4;54 / 178 没有返回值类型的函数,使用 void. 如果你记得函数声明的格式: type name ( argument1, argument2 ...) statement 就会知道函数声明必须以一个数据类型(type)开头,它是函数由 return 语句所返回 数据类型。但是如果我们并不打算返回任何数据那该怎么办呢? 假设我们要写一个函数,它的功能是打印在屏幕上打印一些信息。我们不需要它返回 任何值,而且我们也不需要它接受任何参数。C 语言为这些情况设计了 void 类型。让 我们看一下下面的例子: // void 函数示例 #include &iostream&void printmessage () { cout && &I'm a function!&; }int main () { printmessage (); return 0; } I'm a function!void 还可以被用在函数参数位置,表示我们明确希望这个函数在被调用时不需要任何 参数。例如上面的函数 printmessage 也可以写为以下形式: void printmessage (void) { cout && &I'm a function!&; }55 / 178 虽然在 C++ 中 void 可以被省略,我们还是建议写出 void,以便明确指出函数不需要 参数。 你必须时刻知道的是调用一个函数时要写出它的名字并把参数写在后面的括号内。但 如果函数不需要参数,后面的括号并不能省略。因此调用函数 printmessage 的格式是 printmessage(); 函数名称后面的括号就明确表示了它是一个函数调用,而不是一个变量名称或其它什 么语句。以下调用函数的方式就不对: 2.3 函数 II(Functions II) 参数按数值传递和按地址传递(Arguments passed by value and by reference) 到目前为止,我们看到的所有函数中,传递到函数中的参数全部是按数值传递的(by value)。也就是说,当我们调用一个带有参数的函数时,我们传递到函数中的是变量的 数值而不是变量本身。 例如,假设我们用下面的代码调用我们的第一个函数 addition : int x=5, y=3, z = addition ( x , y ); 在这个例子里我们调用函数 addition 同时将 x 和 y 的值传给它,即分别为 5 和 3,而 不是两个变量:这样,当函数 addition 被调用时,它的变量 a 和 b 的值分别变为 5 和 3,但在函数 addition 内对变量 a 或 b 所做的任何修改不会影响变量他外面的变量 x 和 y 的值,因 为变量 x 和 y 并没有把它们自己传递给函数,而只是传递了他们的数值。 但在某些情况下你可能需要在一个函数内控制一个函数以外的变量。要实现这种操 作,我们必须使用按地址传递的参数(arguments passed by reference),就象下面 例子中的函数 duplicate: // passing parameters by reference #include &iostream.h&void duplicate (int& a, int& b, int& c)56 / 178 { a*=2; b*=2; c*=2; }int main () { int x=1, y=3, z=7; duplicate (x, y, z); cout && &x=& && x && &, y=& && y && &, z=& && return 0; } x=2, y=6, z=14第一个应该注意的事项是在函数 duplicate 的声明(declaration)中,每一个变量的类型 后面跟了一个地址符 ampersand sign (&),它的作用是指明变量是按地址传递的(by reference),而不是像通常一样按数值传递的(by value)。 当按地址传递(pass by reference)一个变量的时候,我们是在传递这个变量本身, 我们在函数中对变量所做的任何修改将会影响到函数外面被传递的变量。用另一种方式来说,我们已经把变量 a, b,c 和调用函数时使用的参数(x, y 和 z)联系 起来了,因此如果我们在函数内对 a 进行操作,函数外面的 x 值也会改变。同样,任 何对 b 的改变也会影响 y,对 c 的改变也会影响 z&。 这就是为什么上面的程序中,主程序 main 中的三个变量 x, y 和 z 在调用函数 duplicate 后打印结果显示他们的值增加了一倍。 如果在声明下面的函数: void duplicate (int& a, int& b, int& c) 时,我们是按这样声明的: void duplicate (int a, int b, int c)57 / 178 也就是不写地址符 ampersand (&),我们也就没有将参数的地址传递给函数,而是传 递了它们的值,因此,屏幕上显示的输出结果 x, y ,z 的值将不会改变,仍是 1,3, 7。 这种用地址符 ampersand (&)来声明按地址&by reference&传递参数的方式只是在 C++ 中适用。在 C 语言中,我们必须用指针(pointers)来做相同的操作。 按地址传递(Passing by reference)是一个使函数返回多个值的有效方法。例如,下面 是一个函数,它可以返回第一个输入参数的前一个和后一个数值。 // more than one returning value #include &iostream.h& void prevnext (int x, int& prev, int& next) { prev = x-1; next = x+1; }int main () { int x=100, y, prevnext (x, y, z); cout && &Previous=& && y && &, Next=& && return 0; } Previous=99, Next=101参数的默认值(Default values in arguments) 当声明一个函数的时候我们可以给每一个}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信