怕忘记,放一下,c语言基础教程

时间:2019-05-14 02:12:10下载本文作者:会员上传
简介:写写帮文库小编为你整理了多篇相关的《怕忘记,放一下,c语言基础教程》,但愿对你工作学习有帮助,当然你在写写帮文库还可以找到更多《怕忘记,放一下,c语言基础教程》。

第一篇:怕忘记,放一下,c语言基础教程

32***2***2132

1.3.2 Turbo C 2.0基本配置要求*Turbo C 2.0可运行于IBM-PC系列微机,包括XT, AT及IBM 兼容机。此时要求DOS 2.0或更高版本支持, 并至少需要448K的RAM, 可在任何彩、单*80列监视器上运行。支持数学协处理器芯片, 也可进行浮点仿真,这将加快程序的执行。

*1.3.3 Turbo C 2.0内容简介*Turbo C 2.0有六张低密软盘(或两张高密软盘)。下面对Turbo C 2.0的主要文件作一简单介绍:*INSTALL.EXE*安装程序文件*TC.EXE*集成编译*TCINST.EXE*集成开发环境的配置设置程序*TCHELP.TCH*帮助文件*THELP.COM*读取TCHELP.TCH的驻留程序*README*关于Turbo C的信息文件*TCCONFIG.EXE*配置文件转换程序*MAKE.EXE*项目管理工具*TCC.EXE*命令行编译*TLINK.EXE*Turbo C系列连接器*TLIB.EXE*Turbo C系列库管理工具*C0?.OBJ*不同模式启动代码*C?.LIB*不同模式运行库*GRAPHICS.LIB*图形库*EMU.LIB*8087仿真库*FP87.LIB*8087库**.H*Turbo C头文件**.BGI*不同显示器图形驱动程序**.C*Turbo C例行程序(源文件)*其中: 上面的?分别为:*T*Tiny(微型模式)*S*Small(小模式)*C*Compact(紧凑模式)*M*Medium(中型模式)*L*Large(大模式)*H*Huge(巨大模式)1.4 Turbo C 2.0的安装和启动*Turbo C 2.0的安装非常简单, 只要将1#盘*入A驱动器中, 在DOS的“A>” 下键入:A>INSTALL即可, 此时屏幕上显示三种选择:*1.在硬盘上创造一个新目录来安装整个Turbo C 2.0系统。*2.对Turbo C 1.5更新版本。*这样的安装将保留原来对选择项、颜*和编辑功能键的设置。*3.为只有两个软盘而无硬盘的系统安装Turbo C 2.0。*这里假定按第一种选择进行安装, 只要在安装过程中按对盘号的提示, 顺序*入各个软盘, 就可以顺利地进行安装, 安装完毕将在C盘根目录下建立一个TC 子目录, TC下还建立了两个了目录LIB和INCLUDE, LIB子目录中存放库文件,INCLUDE子目录中存放所有头文件。*运行Turbo C 2.0时, 只要在TC 子目录下键入TC并回车即可进入Turbo C 2.0集成开发环境。*1.5 Turbo C 2.0集成开发环境的使用*进入Turbo C 2.0集成开发环境中后, 屏幕上显示:*──────────────────────────────*File Edit Run Compile Project Options Debug Break/watch*┌────────────Edit──────────────┐*│ Line 1 Col 1 Insert Indent Tab File Unindent c:NONAME.C│*│*│*│*│*│*│*│*│*│*│*│*│*│*│*│─────────Message─────────────── │*│*│*│*│*└────────────────────────────┘*F1-Help*F5-Zoom F6-Switch F7-Trace F8-Step F9-Make F10-Menu*───────────────────────────────*其中顶上一行为Turbo C 2.0 主菜单,中间窗口为编辑区,接下来是信息窗口, 最底下一行为参考行。这四个窗口构成了Turbo C 2.0的主屏幕, 以后的编程、编译、调试以及运行都将在这个主屏幕中进行。下面详细介绍主菜单的内容。

1.5.1 主菜单*主菜单 在Turbo C 2.0主屏幕顶上一行, 显示下列内容:*File Edit Run Compile Project Options Debug Break/watch*除Edit外, 其它各项均有子菜单, 只要用Alt加上某项中第一个字母(即大写字母), 就可进入该项的子菜单中。*

一、File(文件)菜单*按Alt F可进入File菜单, 该菜单包括以下内容:*.Load(加载)*装入一个文件, 可用类似DOS的通配符(如*.C)来进行列表选择。也可装入其它扩展名的文件, 只要给出文件名(或只给路径)即可。该项的热键为F3, 即只要在主菜单中按F3即可进入该项, 而不需要先进入File菜单再选此项。*.Pick(选择)*将最近装入编辑窗口的8个文件列成一个表让用户选择,*选择后将该程序装入编辑区, 并将光标置在上次修改过的地方。其热健为Alt-F3。*.New(新文件)*说明文件是新的, 缺省文件名为NONAME.C, 存盘时可改名。*.Save(存盘)*将编辑区中的文件存盘, 若文件名是NONAME.C时, 将询问是否更改文件名,其热键为F2。*.Write to(存盘)*可由用户给出文件名将编辑区中的文件存盘, 若该文件已存在, 则询问要不要覆盖。*.Directory(目录)*显示目录及目录中的文件,并可由用户选择。*.Change dir(改变目录)*显示当前目录, 用户可以改变显示的目录。*.Os shell(暂时退出)*暂时退出Turbo C 2.0到DOS提示符下,此时可以运行DOS 命令,若想回到Turbo C 2.0中, 只要在DOS状态下键入EXIT即可。*.Quit(退出)*退出Turbo C 2.0,返回到DOS*作系统中, 其热键为Alt X。*说明:*以上各项可用光标键移动*棒进行选择,回车则执行。也可用每一项的第一个大写字母直接选择。若要退到主菜单或从它的下一级菜单列表框退回均可用Esc键,Turbo C 2.0所有菜单均采用这种方法进行*作, 以下不再说明。*

二、Edit(编辑)菜单*按Alt E可进入编辑菜单, 若再回车, 则光标出现在编辑窗口,*此时用户可以进行文本编辑。编辑方法基本与wordstar相同, 可用F1键获得有关编辑方法的帮助信息。*与编辑有关的功能键如下:*F1*获得Turbo C 2.0编辑命令的帮助信息*F5*扩大编辑窗口到整个屏幕*F6*在编辑窗口与信息窗口之间进行切换*F10*从编辑窗口转到主菜单*编辑命令简介:*PageUp*向前翻页*PageDn*向后翻页*Home*将光标移到所在行的开始*End*将光标移到所在行的结尾*Ctrl Y*删除光标所在的一行*Ctrl T*删除光标所在处的一个词*Ctrl KB*设置块开始*Ctrl KK*设置块结尾*Ctrl KV*块移动*Ctrl KC*块拷贝*Ctrl KY*块删除*Ctrl KR*读文件*Ctrl KW*存文件*Ctrl KP*块文件打印*Ctrl F1*如果光标所在处为Turbo C 2.0库函数, 则获得有关该函数的帮助*信息*Ctrl Q[*查找Turbo C 2.0双界符的后匹配符*Ctrl Q]*查找Turbo C 2.0双界符的前匹配符

说明:*1.Turbo C 2.0的双界符包括以下几种符号:*花括符*{和}*尖括符*<和>*圆括符*(和)*方括符*[和]*注释符*/*和*/*双引号*“*单引号*'*2.Turbo C 2.0在编辑文件时还有一种功能, 就是能够自动缩进, 即光标定位和上一个非空字符对齐。在编辑窗口中, Ctrl OL为自动缩进开关的控制键。*

三、Run(运行)菜单*按Alt R可进入Run菜单, 该菜单有以下各项:*.Run(运行程序)*运行由Project/Project name项指定的文件名或当前编辑区的文件。如果对上次编译后的源代码未做过修改, 则直接运行到下一个断点(没有断点则运行到结束)。否则先进行编译、连接后才运行, 其热键为Ctrl F9。*.Program reset(程序重启)*中止当前的调试, 释放分给程序的空间, 其热键为Ctrl F2。*.Go to cursor(运行到光标处)*调试程序时使用, 选择该项可使程序运行到光标所在行。光标所在行必须为一条可执行语句, 否则提示错误。其热键为F4。*.Trace into(跟踪进入)*在执行一条调用其它用户定义的子函数时, 若用Trace into项, 则执行长条将跟踪到该子函数内部去执行, 其热键为F7。*.Step over(单步执行)*执行当前函数的下一条语句, 即使用户函数调用, 执行长条也不会跟踪进函数内部, 其热键为F8。*.User screen(用户屏幕)*显示程序运行时在屏幕上显示的结果。其热键为Alt F5。*

四、Compile(编译)菜单*按Alt C可进入Compile菜单, 该菜单有以下几个内容:*.Compile to OBJ(编译生成目标码)*将一个C源文件编译生成.OBJ目标文件,*同时显示生成的文件名。其热键为Alt F9。*.Make EXE file(生成执行文件)*此命令生成一个.EXE的文件, 并显示生成的.EXE文件名。其中.EXE文件名是下面几项之一。*1.由Project/Project name说明的项目文件名。*2.若没有项目文件名, 则由Primary C file说明的源文件。*3.若以上两项都没有文件名, 则为当前窗口的文件名。*.Link EXE file(连接生成执行文件)*把当前.OBJ文件及库文件连接在一起生成.EXE文件。*.Build all(建立所有文件)*重新编译项目里的所有文件, 并进行装配生成.EXE文件。该命令不作过时检查(上面的几条命令要作过时检查,即如果目前项目里源文件的日期和时间与目标文件相同或更早, 则拒绝对源文件进行编译)。*.Primary C file(主C文件)*当在该项中指定了主文件后, 在以后的编译中, 如没有项目文件名则编译此项中规定的主C文件, 如果编译中有错误, 则将此文件调入编辑窗口,不管目前窗口中是不是主C文件。*.Get info(获得有关当前路径、源文件名、源文件字节大小、编译中的错误数目、可用空间等信息。

五、Project(项目)菜单*按Alt P可进入Project菜单, 该菜单包括以下内容:*.Project name(项目名)*项目名具有.PRJ的扩展名,其中包括将要编译、连接的文件名。例如有一个程序由file1.c, file2.c, file3.c组成, 要将这3个文件编译装配成一个file.exe的执行文件, 可以先建立一个file.prj的项目文件, 其内容如下:*file1.c*file2.c*file3.c*此时将file.prj放入Project name项中, 以后进行编译时将自动对项目文件中规定的三个源文件分别进行编译。然后连接成file.exe文件。*如果其中有些文件已经编译成.OBJ文件, 而又没有修改过, 可直接写上.OBJ扩展名。此时将不再编译而只进行连接。*例如:file1.obj*file2.c*file3.c*将不对file1.c进行编译,而直接连接。*说明:*当项目文件中的每个文件无扩展名时,均按源文件对待,另外,其中的文件也可以是库文件,但必须写上扩展名.LIB。*.Break make on(中止编译)*由用户选择是否在有Warining(警告)、Errors(错误)、Fatal Errors(致命错误)时或Link(连接)之前退出Make编译。*.Auto dependencies(自动依赖)*当开关置为on, 编译时将检查源文件与对应的.OBJ文件日期和时间,否则不进行检查。*.Clear project(清除项目文件)*清除Project/Project name中的项目文件名。*.Remove messages(删除信息)*把错误信息从信息窗口中清除掉。

五、Project(项目)菜单*按Alt P可进入Project菜单, 该菜单包括以下内容:*.Project name(项目名)*项目名具有.PRJ的扩展名,其中包括将要编译、连接的文件名。例如有一个程序由file1.c, file2.c, file3.c组成, 要将这3个文件编译装配成一个file.exe的执行文件, 可以先建立一个file.prj的项目文件, 其内容如下:*file1.c*file2.c*file3.c*此时将file.prj放入Project name项中, 以后进行编译时将自动对项目文件中规定的三个源文件分别进行编译。然后连接成file.exe文件。*如果其中有些文件已经编译成.OBJ文件, 而又没有修改过, 可直接写上.OBJ扩展名。此时将不再编译而只进行连接。*例如:file1.obj*file2.c*file3.c*将不对file1.c进行编译,而直接连接。*说明:*当项目文件中的每个文件无扩展名时,均按源文件对待,另外,其中的文件也可以是库文件,但必须写上扩展名.LIB。*.Break make on(中止编译)*由用户选择是否在有Warining(警告)、Errors(错误)、Fatal Errors(致命错误)时或Link(连接)之前退出Make编译。*.Auto dependencies(自动依赖)*当开关置为on, 编译时将检查源文件与对应的.OBJ文件日期和时间,否则不进行检查。*.Clear project(清除项目文件)*清除Project/Project name中的项目文件名。*.Remove messages(删除信息)*把错误信息从信息窗口中清除掉。

六、Options(选择菜单)*按Alt O可进入Options菜单, 该菜单对初学者来说要谨慎使用。*.Compiler(编译器)*本项选择又有许多子菜单,可以让用户选择硬件配置、存储模型、调试技术、代码优化、对话信息控制和宏定义。这些子菜单如下:*Model*共有Tiny, small, medium,compact, large, huge 六种不同模式可由同户选择。*Define*打开一个宏定义框, 同户可输入宏定义。多重定义可同分号, 赋值可用等号。*Code generation*它又有许多任选项, 这些任选项告诉编译器产生什么样的目标代码。*Calling convention*可选择C或Pascal方式传递参数。*Instruction set*可选择8088/8086或80186/80286指令系列。*Floating point*可选择仿真浮点、数学协处理器浮点或无浮点运算。*Default char type*规定char的类型。*Alignonent*规定地址对准原则。*Merge duplicate strings 作优化用, 将重复的字符串合并在一起。*Standard stack frame 产生一个标准的栈结构。*Test stack overflow 产生一段程序运行时检测堆栈溢出的代码。*Line number*在.OBJ文件中放进行号以供调试时用。*OBJ debug information 在.OBJ文件中产生调试信息。*Optimization*Optimize for*选择是对程序小型化还是对程序速度进行优*化处理。*Use register variable*用来选择是否允许使用寄存器变量。*Register optimization*尽可能使用寄存器变量以减少过多的取数**作。*Jump optimization 通过去除多余的跳转和调整循环与开关语句*的办法, 压缩代码。*Source*Indentifier length*说明标识符有效字符的个数, 默认为32个。*Nested comments*是否允许嵌套注释。*ANSI keywords only 是只允许ANSI关键字还是也允许Turbo C*2.0关键字*Error*Error stop after*多少个错误时停止编译, 默认为25个。*Warning stop after 多少个警告错误时停止编译, 默认为100个。*Display warning*Portability warning*移植性警告错误。*ANSI Violations*侵犯了ANSI关键字的警告错误。*Common error 常见的警告错误。*Less common error*少见的警告错误。*Names*用于改变段(segment)、组(group)和类*(class)的名字, 默认值为CODE,DATA,BSS。*.Linker(连接器)*本菜单设置有关连接的选择项, 它有以下内容:*Map file menu*选择是否产生.MAP文件。*Initialize segments 是否在连接时初始化没有初始化的段。*Devault libraries*是否在连接其它编译程序产生的目标文件时去寻*找其缺省库。*Graphics library*是否连接graphics库中的函数。*Warn duplicate symbols*当有重复符号时产生警告信息。*Stack warinig*是否让连接程序产生No stack的警告信息。*Case-sensitive link*是否区分大、小写字。*.Environment(环境)

本菜单规定是否对某些文件自动存盘及制表键和屏幕大小的设置*Message tracking*Current file*跟踪在编辑窗口中的文件错误。*All files*跟踪所有文件错误。*Off*不跟踪。*Keep message*编译前是否清除Message窗口中的信息。*Config auto save*选on时, 在Run, Shell或退出集成开发环境之前,*如果Turbo C 2.0的配置被改过,*则所做的改动*将存入配置文件中。选off时不存。*Edit auto save*是否在Run或Shell之前, 自动存储编辑的源文件。*Backup file*是否在源文件存盘时产生后备文件(.BAK文件)。*Tab size*设置制表键大小, 默认为8。*Zoomed windows*将现行活动窗口放大到整个屏幕,其热键为F5。*Screen size*设置屏幕文本大小。*.Directories(路径)*规定编译、连接所需文件的路径, 有下列各项:*Include directories*包含文件的路径, 多个子目录用”;“分开。*Library directories*库文件路径, 多个子目录用”;"分开。*Output directoried*输出文件(.OBJ,.EXE,.MAP文件)的目录。*Turbo C directoried*TurboC 所在的目录。*Pick file name*定义加载的pick文件名,*如不定义则从current*pick file中取。*.Arguments(命令行参数)*允许用户使用命令行参数。*.Save options(存储配置)*保存所有选择的编译、连接、调试和项目到配置文件中, 缺省的配置文件为TCCONFIG.TC。*.Retrive options*装入一个配置文件到TC中, TC将使用该文件的选择项。

第二篇:程序员实验室 - C 基础教程

C++ 基础教程Beta 版

原作:Juan Soulié 翻译:Jing Xu(aqua)英文原版

本教程根据Juan Soulie的英文版C++教程翻译并改编。本版为最新校对版,尚未定稿。如有不明或错误之处,请参考英文原版,并敬请在本站留言指正。版权归作者所有,欢迎链接,请勿转载。

本教程对C++语言进行了深入浅出的介绍,从基础知识到ANSI-C++标准的最新功能,内容涵盖了从数组,类等基本概念到多态、模板等高级概念。教程本着实用的原则,每一小节都结合了可以工作的程序实例,以便读者从第一课开始就可以上手实习。

本翻译版本对许多C++概念中的关键词保留了中英文对照,以便读者增强理解,并方便日后阅读英文原版教材 目录

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 Functions 1.控制结构

Control Structures 2.函数I Functions I 3.函数II Functions 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 members 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++语言的读者。如果读者有其他编程语言背景或计算机相关基本知识可以帮助更好的理解教程内容,但这并非必须条件。

对于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程序的编译。要了解更多关于如何编译的说明,请查询你的编译器用户使用手册。C++编译器和开发环境推荐

很多读者询问编译器和开发环境的问题。除了常用的商用收费的MS Visual Studio, VC++,Borland C++等工具外,还有很多免费的工具也是很好用的。这里推荐两种免费的C++开发软件:

1、Eclipse的CDT开发工具,官方网站在http://www.xiexiebang.com/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 console

1.1 C++程序结构(Structure of a program)

下面我们从一个最简单的程序入手看一个C++程序的组成结构。// my first program in C++ #include using namespace std;

int main(){ cout << “Hello World!”;return 0;} Hello World!上面左侧显示了我们的第一个程序的源代码,代码文件名称为hellowworld.cpp。右边显示了程序被编译执行后的输出结果。编辑和编译一个程序的方法取决于你用的是什么编译器,根据它是否有图形化的界面及版本的不同,编译方法也有可能不同,具体请参照你所使用的编译器的使用说明。

以上程序是多数初学者学会写的第一个程序,它的运行结果是在屏幕上打出”Hello World!”这句话。虽然它可能是C++可写出的最简单的程序之一,但其中已经包含了每一个C++程序的基本组成结构。下面我们就逐个分析其组成结构的每一部分: // my first program in C++ 这是注释行。所有以两个斜线符号(//)开始的程序行都被认为是注释行,这些注释行是程序员写在程序源代码内,用来对程序作简单解释或描述的,对程序本身的运行不会产生影响。在本例中,这行注释对本程序是什么做了一个简要的描述。# include < iostream.h > 以#标志开始的句子是预处理器的指示语句。它们不是可执行代码,只是对编译器作出指示。在本例中这个句子# include < iostream.h > 告诉编译器的预处理器将输入输出流的标准头文件(iostream.h)包括在本程序中。这个头文件包括了C++中定义的基本标准输入-输出程序库的声明。此处它被包括进来是因为在本程序的后面部分中将用到它的功能。using namespace std;C++标准函数库的所有元素都被声明在一个名空间中,这就是std名空间。因此为了能够访问它的功能,我们用这条语句来表达我们将使用标准名空间中定义的元素。这条语句在使用标准函数库的C++程序中频繁出现,本教程中大部分代码例子中也将用到它。int main()这一行为主函数(main function)的起始声明。main function是所有C++程序的运行的起始点。不管它是在代码的开头,结尾还是中间 – 此函数中的代码总是在程序开始运行时第一个被执行。并且,由于同样的原因,所有C++程序都必须有一个main function。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;} 以上两段程序是完全相同的。

在C++中,语句的分隔是以分号(;)为分隔符的。分行写代码只是为了更方便人阅读。以下程序包含更多的语句: // my second program in C++ #include

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;} 它的运行结果将和上面的例子完全一样。

这个规则对预处理器指示行(以#号开始的行)并不适用,因为它们并不是真正的语句。它们由预处理器读取并忽略,并不会生成任何代码。因此他们每一个必须单独成行,末尾不需要分号(;)

注释(Comments)注释(comments)是源代码的一部分,但它们会被编译器忽略。它们不会生成任何执行代码。使用注释的目的只是使程序员可以在源程序中插入一些说明解释性的内容。C++ 支持两中插入注释的方法: // line comment /* block comment */ 第一种方法为行注释,它告诉编译器忽略从//开始至本行结束的任何内容。第二种为块注释(段注释),告诉编译器忽略在/*符号和*/符号之间的所有内容,可能包含多行内容。在以下我们的第二个程序中,我们插入了更多的注释。/* my second program in C++ with more comments */

#include

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”程序用处不大。我们写了好几行代码,编译,然后执行生成的程序只是为了在屏幕上看到一句话。的确,我们直接在屏幕上打出这句话会更快。但是编程并不仅限于在屏幕上打出文字这么简单的工作。为了能够进一步写出可以执行更有用的任务的程序,我们需要引入变量(variable)这个的概念。

让我们设想这样一个例子,我要求你在脑子里记住5这个数字,然后再记住2这个数字。你已经存储了两个数值在你的记忆里。现在我要求你在我说的第一个数值上加1,你应该保留6(即5+1)和2在你的记忆里。现在如果我们将两数相减可以得到结果4。

所有这些你在脑子里做的事情与计算机用两个变量可以做的事情非常相似。同样的处理过程用C++来表示可以写成下面一段代码: a = 5;b = 2;a = a + 1;result = a38(7 个数字(7digits))double 8 双精度浮点数(double precision floating point number)1.7e + /308(15 digits)bool 1 布尔Boolean值。它只能是真(true)或假(false)两值之一。true 或 false wchar_t 2 宽字符(Wide character)。这是为存储两字节(2 bytes)长的国际字符而设计的类型。一个宽字符(1 wide characters)

* 字节数一列和范围一列可能根据程序编译和运行的系统不同而有所不同。这里列出的数值是多数32位系统的常用数据。对于其他系统,通常的说法是整型(int)具有根据系统结构建议的自然长度(即一个字one word的长度),而4中整型数据char, short, int, long的长度必须是递增的,也就是说按顺序每一类型必须大于等于其前面一个类型的长度。同样的规则也适用于浮点数类型float, double和 long double,也是按递增顺序。

除以上列出的基本数据类型外,还有指针(pointer)和void 参数表示类型,我们将在后面看到。

变量的声明(Declaration of variables)

在C++中要使用一个变量必须先声明(declare)该变量的数据类型。声明一个新变量的语法是写出数据类型标识符(例如int, short, float...)后面跟一个有效的变量标识名称。例如: int a;float mynumber;以上两个均为有效的变量声明(variable declaration)。第一个声明一个标识为a 的整型变量(int variable),第二个声明一个标识为mynumber 的浮点型变量(float variable)。声明之后,我们就可以在后面的程序中使用变量a和 mynumber 了。

如果你需要声明多个同一类型的变量,你可以将它们缩写在同一行声明中,在标识之间用逗号(comma)分隔。例如: int a, b, c;以上语句同时定义了a、b、c 3个整型变量,它与下面的写法完全等同: int a;int b;int c;整型数据类型(char, short, long 和 int)可以是有符号的(signed)或无符号的(unsigned),这取决于我们需要表示的数据范围。有符号类型(signed)可以表示正数和负数,而无符号类型(unsigned)只能表示正数和0。在定义一个整型数据变量时可以在数据类型前面加关键字 signed 或 unsigned 来声明数据的符号类型。例如: unsigned short NumberOfSons;signed int MyAccountBalance;如果我们没有特别写出signed或 unsigned,变量默认为signed,因此以上第二个声明我们也可以写成:

int MyAccountBalance;因为以上两种表示方式意义完全一样,因此我们在源程序通常省略关键字signed。

唯一的例外是字符型(char)变量,这种变量独立存在,与signed char 和 unsigned char型均不相同。

short 和 long 可以被单独用来表示整型基本数据类型,short 相当于 short int,long 相当于 long int。也就是说 short year;和 short int year;两种声明是等价的。

最后,signed 和 unsigned 也可以被单独用来表示简单类型,意思分别同signed int 和 unsigned int 相同,即以下两种声明互相等同: unsigned MyBirthYear;unsigned int MyBirthYear;下面我们就用C++代码来解决在这一节开头提到的记忆问题,来看一下变量定义是如何在程序中起作用的。

// operating with variables

#include using namespace std;

int main(){ // declaring variables: int a, b;int result;

// process: a = 5;b = 2;a = a + 1;result = ab;cout << result;

return 0;} 6

字符串(strings)字符串是用来存储一个以上字符的非数字值的变量。

C++提供一个string类来支持字符串的操作,它不是一个基本的数据类型,但是在一般的使用中与基本数据类型非常相似。

与普通数据类型不同的一点是,要想声明和使用字符串类型的变量,需要引用头文件,并且使用using namespace语句来使用标准名空间(std),如下面例子所示: // C++字符串例题 #include #include using namespace std;

int main(){ string mystring = “This is a string”;cout << mystring;return 0;} This is a string 如上面例子所示,字符串变量可以被初始化为任何字符串值,就像数字类型变量可以被初始化为任何数字值一样。

以下两种初始化格式对字符串变量都是可以使用的: string mystring = “This is a string”;string mystring(“This is a string”);字符串变量还可以进行其他与基本数据类型变量一样的操作,比如声明的时候不指定初始值,和在运行过程中被重新赋值。// C++字符串例题2 #include #include using namespace std;

int main(){ string mystring;mystring = “This is the initial string content”;cout << mystring << endl;mystring = “This is a different string content”;cout << mystring << endl;return 0;} This is the initial string content This 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)1776 707-273 他们是整型常数,表示十进制整数值。注意表示整型常数时我们不需要些引号(quotes(“))或任何特殊字符。毫无疑问它是个常量:任何时候当我们在程序中写1776,我们指的就是1776这个数值。

除十进制整数另外,C++还允许使用八进制(octal numbers)和十六进制(hexadecimal numbers)的字常量(literal constants)。如果我们想要表示一个八进制数,我们必须在它前面加上一个0字符(zero character),而表示十六进制数我们需要在它前面加字符0x(zero, x)。例如以下字常量(literal constants)互相等值: 75 // 十进制 decimal 0113 // 八进制 octal 0x4b // 十六进制 hexadecimal 所有这些都表示同一个整数: 75(seventy five),分别以十进制数,八进制数和十六进制数表示。

像变量一样,常量也是有数据类型的。默认的整数字常量的类型为int型。我们可以通过在后面加字母u或l来迫使它为无符号(unsigned)的类型或长整型(long)。75 // int 75u // unsigned int 75l // long 75ul // unsigned long

这里后缀u和l可以是大写,也可以是小写。

浮点数(Floating Point Numbers)浮点数以小数(decimals)和/或指数幂(exponents)的形式表示。它们可以包括一个小数点,一个e字符(表示”by ten at the Xth height“,这里X是后面跟的整数值),或两者都包括。

3.14159 // 3.14159 6.02e23 // 6.02 x 10^1023 1.6e-19 // 1.6 x 10^-19 3.0 // 3.0 以上是包含小数的以C++表示的4个有效数值。第一个是PI,第二个是Avogadro数之一,第三个是一个电子(electron)的电量(electric charge)(一个极小的数值)– 所有这些都是近似值。最后一个是浮点数字常量表示数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 换行符newline r 回车carriage return t 跳跃符tabulation v 垂直跳跃vertical tabulation b backspace f page feed a 警告alert(beep)' 单引号single quotes(')“ 双引号double quotes(”)? 问号question(?)反斜杠inverted slash()例如: 'n' 't' “Left t Right” “onentwonthree” 另外你可以数字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” 宽字符通常用来存储非英语字符,比如中文字符,一个字符占两个字节。布尔型常量(Boolean Literals)布尔型只有两个有效的值:true和false,其数据类型为bool。

定义常量Defined constants(#define)使用预处理器指令#define,你可以将那些你经常使用的常量定义为你自己取的名字而不需要借助于变量。它的格式是: #define identifier value 例如:

#define PI 3.14159265 #define NEWLINE 'n' #define WIDTH 100 以上定义了三个常量。一旦做了这些声明,你可以在后面的程序中使用这些常量,就像使用其它任何常量一样,例如: circle = 2 * PI * r;cout << NEWLINE;实际上编译器在遇到#define指令的时候做的只是把任何出现这些 常量名(在前面的例子中为PI, NEWLINE或WIDTH)的地方替换成他们被定义为的代码(分别为3.14159265, 'n'和100)。因此,由#define定义的常量被称为宏常量macro constants。

#define 指令不是代码语句,它是预处理器指令,因此指令行末尾不需要加分号semicolon(;)。如果你在宏定义行末尾加了分号(;),当预处理器在程序中做常量替换的时候,分号也会被加到被替换的行中,这样可能导致错误。

声明常量declared constants(const)通过使用const前缀,你可以定义指定类型的常量,就像定义一个变量一样: const int width = 100;const char tab = 't';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;将变量b(rvalue)的值赋给变量a(lvalue),不论a当时存储的是什么值。同时考虑到我们只是将b的数值赋给a,以后如果b的值改变了并不会影响到a的值.例如:如果我们使用以下代码(变量值的变化显示在绿色注释部分): // 赋值符号例子

#include using namespace std;

int main(){ int a, b;// a:?, b:? a = 10;// a:10, b:? b = 4;// a:10, b:4 a = b;// a:4, b:4 b = 7;// a:4, b:7

cout << “a:”;cout << a;cout << “ b:”;cout << b;

return 0;} a:4 b:7 以上代码结果是a的值为4,b的值为7。最后一行中b的值被改变并不会影响到a,虽然在此之前我们声明了a = b;(从右到左规则right-to-left rule)。

C++拥有而其他语言没有的一个特性是赋值符(=)可以被用作另一个赋值符的rvalue(或rvalue的一部分)。例如: a = 2 +(b = 5);等同于: b = 5;a = 2 + b;它的意思是:先将5赋给变量b,然后把前面对b的赋值运算的结果(即5)加上2再赋给变量a,这样最后a中的值为7。因此,下面的表达式在C++中也是正确的: a = b = c = 5;//将5同时赋给3个变量a, b和c。

数学运算符Arithmetic operators(+,-, *, /, %)C++语言支持的5种数学运算符为: ? + 加addition ?5;a /= b;等同于 a = a / b;price *= units + 1;等同于 price = price *(units + 1);其他运算符以此类推。例如: // 组合运算符例子

#include using namespace std;

int main(){ int a, b=3;a = b;a+=2;// 相当于 a=a+2 cout << a;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 例 2 B=3;A=++B;// A 的值为 4, B 的值为 4 B=3;A=B++;// A 的值为 3, B 的值为 4 在第一个例子中,B在它的值被赋给A之前增加1。而在第二个例子中B原来的值3被赋给 A然后B的值才加1变为4。

关系运算符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)将返回true.(6 >= 6)将返回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)

((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)返回false,因为它右边的表达式(5 == 5)为真true.!(6 <= 4)返回true因为(6 <= 4)为假false.!true 返回假false.!false 返回真true.逻辑运算符&&和||是用来计算两个表达式而获得一个结果值。它们分别对应逻辑运算中的与运算AND 和或运算OR。它们的运算结果取决于两个操作数(operand)的关系: 第一个操作数 a 第二个操作数 b 结果 a && b 结果 a || b true true true true true false false true false true false true false false false 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 返回4,因为7等于5+2.5>3 ? a : b 返回a,因为5大于3.a>b ? a : b 返回较大值,a 或b.// 条件运算符例子

#include using namespace std;int main(){ int a,b,c;

a=2;b=7;c =(a>b)? a : b;

cout << c;

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 Description & AND 逻辑与 Logic AND | OR 逻辑或Logic OR ^ XOR 逻辑异或Logical exclusive OR ~ NOT 对1取补(位反转)Complement to one(bit inversion)<< SHL 左移Shift Left >> SHR 右移Shift Right

变量类型转换运算符Explicit type casting operators 变量类型转换运算符可以将一种类型的数据转换为另一种类型的数据。在写C++中有几种方法可以实现这种操作,最常用的一种,也是与C兼容的一种,是在原转换的表达式前面加用括号()括起的新数据类型: int i;float f = 3.14;i =(int)f;以上代码将浮点型数字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 operators 当多个操作数组成复杂的表达式时,我们可能会疑惑哪个运算先被计算,哪个后被计算。例如以下表达式: a = 5 + 7 % 2 我们可以怀疑它实际上表示:

a = 5 +(7 % 2)结果为6,还是 a =(5 + 7)% 2 结果为0? 正确答案为第一个,结果为6。每一个运算符有一个固定的优先级,不仅对数学运算符(我们可能在学习数学的时候已经很了解它们的优先顺序了),所有在C++中出现的运算符都有优先级。从最从最高级到最低级,运算的优先级按下表排列: 优先级

Level 操作符 Operator 说明 Description 结合方向 Grouping 1 :: 范围 从左到右()[].-> ++--dynamic_cast static_cast reinterpret_cast const_cast typeid 后缀 从左到右 ++--~!sizeof new delete 一元(前缀)从右到左

* & 指针和取地址

+加减 从左到右 8 << >> 位移 从左到右 < > <= >= 关系操作符 从左到右 10 ==!= 等于、不等于 从左到右 11 & 按位与运算 从左到右 12 ^ 按位异或运算 从左到右 13 | 按位或运算 从左到右 14 && 逻辑与运算 从左到右 15 || 逻辑或运算 从左到右 16 ?: 条件运算 从右到左 = *= /= %= +=-= >>= <<= &= ^= |= 赋值运算 从右到左 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也已经被实现――它们是两种特殊设计的数据流专门用来显示出错信息。它们可以被重新定向到标准输出设备或到一个日志文件(log file)。因此cout(标准输出流)通常被定向到屏幕,而cin(标准输入流)通常被定向到键盘。通过控制这两种数据流,你可以在程序中与用户交互,因为你可以在屏幕上显示输出并从键盘接收用户的输入。

输出Output(cout)输出流cout与重载(overloaded)运算符<<一起使用:

cout << “Output sentence”;// 打印Output sentence到屏幕上 cout << 120;// 打印数字 120 到屏幕上 cout << x;// 打印变量 x 的值到屏幕上

运算符<<又叫插入运算符(insertion operator)因为它将后面所跟的数据插入到它前面的数据流中。在以上的例子中,字符串常量Output sentence,数字常量120和变量x先后被插入输出流cout中。注意第一句中字符串常量是被双引号引起来的。每当我们使用字符串常量的时候,必须用引号把字符串引起来,以便将它和变量名明显的区分开来。例如,下面两个语句是不同的:

cout << “Hello”;// 打印字符串Hello到屏幕上

cout << Hello;// 把变量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 ” << zipcode;如果我们假设变量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.虽然我们分别调用了两次cout,两个句子还是被输出在同一行。所以,为了在输出中换行,我们必须插入一个换行符来明确表达这一要求。在C++中换行符可以写作n: cout << “First sentence.n ”;cout << “Second sentence.nThird sentence.”;将会产生如下输出: First sentence.Second sentence.Third sentence.另外,你也可以用操作符endl来换行,例如: cout << “First sentence.” << endl;cout << “Second sentence.” << endl;将会输出:

First sentence.Second sentence.当操作符endl被用在buffered streams中时有一点特殊:它们被flushed。不过cout 默认为unbuffered,所以不会被影响。你可以暂时不管这一点。

你可以使用n或endl来指定cout输出换行,请注意前面所讲的两者的不同用法。

输入Input(cin)C++中的标准输入是通过在cin数据流上重载运算符extraction(>>)来实现的。它后面必须跟一个变量以便存储读入的数据。例如: int age;cin >> age;声明一个整型变量age然后等待用户从键盘输入到cin并将输入值存储在这个变量中。cin 只能在键盘输入回车键(RETURN)后才能处理前面输入的内容。因此即使你只要求输入一个单独的字符,在用户按下回车键(RETURN)之前cin将不会处理用户的输入的字符。在使用cin输入的时候必须考虑后面的变量类型。如果你要求输入一个整数,extraction(>>)后面必须跟一个整型变量,如果要求一个字符,后面必须跟一个字符型变量,如果要求一个字符串,后面必须跟一个字符串型变量。// i/o example #include int main(){ int i;cout << “Please enter an integer value: ”;cin >> i;cout << “The value you entered is ” << i;cout << “ and its double is ” << i*2 << “.n”;return 0;} Please enter an integer value: 702 The value you entered is 702 and its double is 1404.使用程序的用户可以使引起错误的原因之一,即使是在最简单的需要用cin做输入的程序中(就像我们上面看到的这个程序)。因为如果你要求输入一个整数数值,而用户输入了一个名字(一个字符串),其结果可能导致程序产生错误操作,因为它不是我们期望从用户处获得的数据。当你使用由cin 输入的数据的时候,你不得不假设程序的用户将会完全合作而不会在程序要求输入整数的时候输入他的名字。后面当我们看到怎样使用字符串的时候,我们将会同时看到一些解决这一类出错问题的办法。你也可以利用cin 要求用户输入多个数据 : cin >> a >> b;等同于: cin >> a;cin >> b;在以上两种情况下用户都必须输入两个数据,一个给变量a,一个给变量b。输入时两个变量之间可以以任何有效的空白符号间隔,包括空格,跳跃符tab或换行。

cin和字符串

我们可以像读取基本类型数据一样,使用cin和>>操作符来读取字符串,例如: cin >> mystring;但是,cin >> 只能读取一个单词,一旦碰到任何空格,读取操作就会停止。在很多时候这并不是我们想要的操作,比如我们希望用户输入一个英文句子,那么这种方法就无法读取完整的句子,因为一定会遇到空格。

要一次读取一整行输入,需要使用C++的函数 getline,相对于是用cin,我们更建议使用getline来读取用户输入。例如:

// 读取字符串例子 #include #include using namespace std;

int main(){ string mystr;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? Aqua Hello Aqua.What is your favorite color? blue I like blue too!你可能注意到在上面的例子中,两次调用 getline 函数我们都是用了同一个字符串变量(mystr)。在第二次调用的时候,程序会自动用第二次输入的内容取代以前的内容。

字符串流(stringstream)

标准头文件 定义了一个叫做 stringstream 的类,使用这个类可以对基于字符串的对象进行像流(stream)一样的操作。这样,我们可以对字符串进行抽取和插入操作,这对将字符串与数值互相转换非常有用。例如,如果我们想将一个字符串转换为一个整数,可以这样写: string mystr(“1204”);int myint;stringstream(mystr)>> myint;这个例子中先定义了一个字符串类型的对象mystr,初始值为“1204”,又定义了一个整数变量myint。然后我们使用 stringstream 类的构造函数定义了这个类的对象,并以字符串变量mystr为参数。因为我们可以像使用流一样使用stringstream 的对象,所以我们可以像使用cin那样使用操作符 >> 后面跟一个整数变量来进行提取整数数据。这段代码执行之后变量 myint 存储的是数值 1204。// 字符串流的使用示例 #include #include #include using namespace std;

int main(){ string mystr;float price=0;int quantity=0;

cout << “Enter price: ”;getline(cin,mystr);stringstream(mystr)>> price;cout << “Enter quantity: ”;getline(cin,mystr);stringstream(mystr)>> quantity;cout << “Total price: ” << price*quantity << endl;return 0;} Enter price: 22.25 Enter quantity: 7 Total price: 155.75 在这个例子中,我们要求用户输入数值,但不同于从标准输入中直接读取数值,我们使用函数getline从标注输入流cin中读取字符串对象(mystr),然后再从这个字符串对象中提取数值price和quantity。

通过使用这种方法,我们可以对用户的输入有更多的控制,因为它将用户输入与对输入的解释分离,只要求用户输入整行的内容,然后再对用户输入的内容进行检验操作。这种做法在用户输入比较集中的程序中是非常推荐使用的。第二章 控制结构和函数

(Control structures and Functions)1.控制结构

Control Structures 2.函数I Functions I 3.函数II Functions II 2.1 控制结构(Control Structures)

一个程序的语句往往并不仅限于线性顺序结构。在程序的执行过程中它可能被分成两支执行,可能重复某些语句,也可能根据一些判断结果而执行不同的语句。因此C++ 提供一些控制结构语句(control structures)来实现这些执行顺序。

为了介绍程序的执行顺序,我们需要先介绍一个新概念:语句块(block of instructions)。一个语句块(A block of instructions)是一组互相之间由分号semicolons(;)分隔开但整体被花括号curly bracket signs: { and }括起来的语句。

本节中我们将看到的大多数控制结构允许一个通用的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 << x;} 我们可以用关键字else 来指定当条件不能被满足时需要执行的语句,它需要和if 一起使用,形式是:

if(condition)statement1 else statement2 例如: if(x == 100)cout << “x is 100”;else 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 int main(){ int n;cout << “Enter the starting number > ”;cin >> n;while(n>0){ cout << n << “, ”;--n;} cout << “FIRE!”;return 0;} Enter the starting number > 8 8, 7, 6, 5, 4, 3, 2, 1, FIRE!程序开始时提示用户输入一个倒计数的初始值。然后while 循环开始,如果用户输入的数值满足条件n>0(即 n 比0 大),后面跟的语句块将会被执行一定的次数,直到条件(n>0)不再满足(变为false)。

以上程序的所有处理过程可以用以下的描述来解释: 从main开始: 1.用户输入一个数值赋给n.2.while语句检查(n>0)是否成立,这时有两种可能: o true: 执行statement(到第3步)o false: 跳过statement.程序直接执行第5步.3.执行statement: cout << n << “, ”;--n;(将n 的值打印在屏幕上,然后将n 的值减1).4.语句块结束,自动返回第2步。

5.继续执行语句块之后的程序:打印 FIRE!,程序结束。

我们必须考虑到循环必须在某个点结束,因此在语句块之内(loop的statement之内)我们必须提供一些方法使得条件condition 可以在某个时刻变为假 false,否则循环将无限重复下去。在这个例子里,我们用语句--n;使得循环在重复一定的次数后变为false :当 n 变为0,倒计数结束。do-while 循环 格式:

do 语句statement while(条件condition);它的功能与while 循环一抹一样,除了在do-while循环中是先执行statement 然后才检查条件condition,而不想while循环中先检查条件然后才执行statement。这样,即使条件condition从来没有被满足过,statement 仍至少被执行一次。例如,下面的程序重复输出(echoes)用户输入的任何数值,直到用户输入0为止。// number echoer #include int main(){ unsigned long n;do { cout << “Enter number(0 to end): ”;cin >> n;cout << “You entered: ” << n << “n”;} while(n!= 0);return 0;} Enter number(0 to end): 12345 You entered: 12345 Enter number(0 to end): 160277 You entered: 160277 Enter number(0 to end): 0 You entered: 0 do-while 循环通常被用在判断循环结束的条件是在循环语句内部被决定的情况下,比如以上的例子,在循环的语句块内用户的输入决定了循环是否结束。如果用户永远不输入0,则循环永远不会结束。for 循环 格式是:

for(initialization;condition;increase)statement;它的主要功能是当条件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 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++)来表示有增值语句但没有初始化语句。另外我们也可以在for循环初始化或增值域中放一条以上的语句,中间用逗号 coma(,)隔开。例如假设我们想在循环中初始化一个以上的变量,可以用以下的程序来实现: for(n=0, i=100;n!=i;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 int main(){ int n;for(n=10;n>0;n--){ cout << n << “, ”;if(n==3){ cout << “countdown aborted!”;break;} return 0;} 10, 9, 8, 7, 6, 5, 4, 3, countdown aborted!continue 语句

continue语句使得程序跳过当前循环中剩下的部分而直接进入下一次循环,就好像循环中语句块的结尾已经到了使得循环进入下一次重复。例如,下面例子中倒计数时我们将跳过数字5的输出:

// continue loop example #include int main(){ for(int n=10;n>0;n--){ if(n==5)continue;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 int main(){ int n=10;loop: cout << n << “, ”;n--;if(n>0)goto loop;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 break;case constant2: block of instructions 2 break;...default: default block of instructions } 它按以下方式执行:

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 if-else equivalent switch(x){ case 1: cout << “x is 1”;break;case 2: cout << “x is 2”;break;default: cout << “value of x unknown”;} if(x == 1){ cout << “x is 1”;} else if(x == 2){ cout << “x is 2”;} else { 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”;break;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 是函数返回的数据的类型 ? name 是函数被调用时使用的名

? argument 是函数调用需要传入的参量(可以声明任意多个参量)。每个参量(argument)由一个数据类型后面跟一个标识名称组成,就像变量声明中一样(例如,int x)。参量仅在函数范围内有效,可以和函数中的其它变量一样使用,它们使得函数在被调用时可以传入参数,不同的参数用逗号(comma)隔开.? statement 是函数的内容。它可以是一句指令,也可以是一组指令组成的语句块。如果是一组指令,则语句块必须用花括号{}括起来,这也是我们最常见到情况。其实为了使程序的格式更加统一清晰,建议在仅有一条指令的时候也使用花括号,这是一个良好的编程习惯。下面看一下第一个函数的例子: // function example #include int addition(int a, int b){ int r;r=a+b;return(r);}

int main(){ int z;z = addition(5,3);cout << “The result is ” << z;return 0;} The result is 8 记得在我们教程开始时说过:一个C++程序总是从main函数开始执行。因此我们从那里开始。

我们可以看到 main 函数以定义一个整型变量z 开始。紧跟着我们看到调用addition 函数。我们可以看到函数调用的写法和上面函数定义本身十分相似:

参数有明显的对应关系。在main 函数中我们调用addition 函数,并传入两个数值: 5 和3,它们对应函数addition 中定义的参数int a 和int b。当函数在main 中被调用时,程序执行的控制权从main转移到函数addition。调用传递的两个参数的数值(5 和3)被复制到函数的本地变量(local variables)int a 和int b 中。函数addition 中定义了新的变量(int r;),通过表达式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 ” << z;它把结果打印在屏幕上。

变量的范围(Scope of variables)你必须考虑到变量的范围只是在定义该变量的函数或指令块内有效,而不能在它的函数或指令块之外使用。例如,在上面的例子里就不可能在main 中直接使用变量a, b 或 r,因为它们是函数addition的本地变量(local variable)。在函数addition中也不可能直接使用变量z,因为它是main的本地变量。

因此,本地变量(local variables)的范围是局限于声明它的嵌套范围之内的。尽管如此,你还可以定义全局变量(global variables),它们可以在代码的任何位置被访问,不管在函数以内还是以外。要定义全局变量,你必须在所有函数或代码块之外定义它们,也就是说,直接在程序体中声明它们。这里是另一个关于函数的例子: // function example #include int subtraction(int a, int b){ int r;r=a-b;return(r);}

int main(){ int x=5, y=3, z;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 5 The second result is 5 The third result is 2 The fourth result is 6 在这个例子中,我们定义了函数subtraction。这个函数的功能是计算传入的两个参数的差值并将结果返回。

在 main 函数中,函数subtraction被调用了多次。我们用了几种不同的调用方法,因此你可以看到在不同的情况下函数如何被调用。为了更好的理解这些例子,你需要考虑到被调用的函数其实完全可以由它所返回的值来代替。例如在上面例子中第一种情况下(这种调用你应该已经知道了,因为我们在前面的例子中已经用过这种形式的调用): z = subtraction(7,2);cout << “The first result is ” << z;如果我们把函数调用用它的结果(也就是5)替换,我们将得到: z = 5;cout << “The first result is ” << z;同样的

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;没有返回值类型的函数,使用void.如果你记得函数声明的格式:

type name(argument1, argument2...)statement 就会知道函数声明必须以一个数据类型(type)开头,它是函数由return 语句所返回数据类型。但是如果我们并不打算返回任何数据那该怎么办呢? 假设我们要写一个函数,它的功能是打印在屏幕上打印一些信息。我们不需要它返回任何值,而且我们也不需要它接受任何参数。C语言为这些情况设计了void 类型。让我们看一下下面的例子:

// void 函数示例 #include using namespace std;

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!”;} 虽然在C++ 中void可以被省略,我们还是建议写出void,以便明确指出函数不需要参数。你必须时刻知道的是调用一个函数时要写出它的名字并把参数写在后面的括号内。但如果函数不需要参数,后面的括号并不能省略。因此调用函数 printmessage 的格式是 printmessage();函数名称后面的括号就明确表示了它是一个函数调用,而不是一个变量名称或其它什么语句。以下调用函数的方式就不对: printmessage;2.3 函数II(Functions II)

参数按数值传递和按地址传递(Arguments passed by value and by reference)到目前为止,我们看到的所有函数中,传递到函数中的参数全部是按数值传递的(by value)。也就是说,当我们调用一个带有参数的函数时,我们传递到函数中的是变量的数值而不是变量本身。例如,假设我们用下面的代码调用我们的第一个函数addition : int x=5, y=3, z;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

void duplicate(int& a, int& b, int& c){ 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=” << 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)也就是不写地址符 ampersand(&),我们也就没有将参数的地址传递给函数,而是传递了它们的值,因此,屏幕上显示的输出结果x, y,z 的值将不会改变,仍是1,3,7。

这种用地址符 ampersand(&)来声明按地址“by reference”传递参数的方式只是在C++中适用。在C 语言中,我们必须用指针(pointers)来做相同的操作。

按地址传递(Passing by reference)是一个使函数返回多个值的有效方法。例如,下面是一个函数,它可以返回第一个输入参数的前一个和后一个数值。// more than one returning value #include void prevnext(int x, int& prev, int& next){ prev = x-1;next = x+1;}

int main(){ int x=100, y, z;prevnext(x, y, z);cout << “Previous=” << y << “, Next=” << z;return 0;} Previous=99, Next=101

参数的默认值(Default values in arguments)当声明一个函数的时候我们可以给每一个参数指定一个默认值。如果当函数被调用时没有给出该参数的值,那么这个默认值将被使用。指定参数默认值只需要在函数声明时把一个数值赋给参数。如果函数被调用时没有数值传递给该参数,那么默认值将被使用。但如果有指定的数值传递给参数,那么默认值将被指定的数值取代。例如: // default values in functions #include int divide(int a, int b=2){ int r;r=a/b;return(r);}

int main(){ cout << divide(12);cout << endl;cout << divide(20,4);return 0;} 6 5 我们可以看到在程序中有两次调用函数divide。第一次调用: divide(12)只有一个参数被指明,但函数divide允许有两个参数。因此函数divide 假设第二个参数的值为2,因为我们已经定义了它为该参数缺省的默认值(注意函数声明中的int b=2)。因此这次函数调用的结果是 6(12/2)。在第二次调用中: divide(20,4)这里有两个参数,所以默认值(int b=2)被传入的参数值4所取代,使得最后结果为 5(20/4).函数重载(Overloaded functions)两个不同的函数可以用同样的名字,只要它们的参量(arguments)的原型(prototype)不同,也就是说你可以把同一个名字给多个函数,如果它们用不同数量的参数,或不同类型的参数。例如:

// overloaded function #include

int divide(int a, int b){ return(a/b);}

float divide(float a, float b){ return(a/b);}

int main(){ int x=5,y=2;float n=5.0,m=2.0;cout << divide(x,y);cout << “n”;cout << divide(n,m);cout << “n”;return 0;} 2 2.5 在这个例子里,我们用同一个名字定义了两个不同函数,当它们其中一个接受两个整型(int)参数,另一个则接受两个浮点型(float)参数。编译器(compiler)通过检查传入的参数的类型来确定是哪一个函数被调用。如果调用传入的是两个整数参数,那么是原型定义中有两个整型(int)参量的函数被调用,如果传入的是两个浮点数,那么是原型定义中有两个浮点型(float)参量的函数被调用。

为了简单起见,这里我们用的两个函数的代码相同,但这并不是必须的。你可以让两个函数用同一个名字同时完成完全不同的操作。

Inline 函数(inline functions)

inline 指令可以被放在函数声明之前,要求该函数必须在被调用的地方以代码形式被编译。这相当于一个宏定义(macro)。它的好处只对短小的函数有效,这种情况下因为避免了调用函数的一些常规操作的时间(overhead),如参数堆栈操作的时间,所以编译结果的运行代码会更快一些。

它的声明形式是:

inline type name(arguments...){ instructions...} 它的调用和其他的函数调用一样。调用函数的时候并不需要写关键字inline,只有在函数声明前需要写。

递归(Recursivity)

递归(recursivity)指函数将被自己调用的特点。它对排序(sorting)和阶乘(factorial)运算很有用。例如要获得一个数字n的阶乘,它的数学公式是: n!= n *(n-1)*(n-2)*(n-3)...* 1 更具体一些,5!(factorial of 5)是: 5!= 5 * 4 * 3 * 2 * 1 = 120 而用一个递归函数来实现这个运算将如以下代码: // factorial calculator #include

long factorial(long a){ if(a > 1)return(a * factorial(a-1));else return(1);}

int main(){ long l;cout << “Type a number: ”;cin >> l;cout << “!” << l << “ = ” << factorial(l);return 0;} Type a number: 9!9 = 362880 注意我们在函数factorial中是怎样调用它自己的,但只是在参数值大于1的时候才做调用,因为否则函数会进入死循环(an infinite recursive loop),当参数到达0的时候,函数不继续用负数乘下去(最终可能导致运行时的堆栈溢出错误(stack overflow error)。

这个函数有一定的局限性,为简单起见,函数设计中使用的数据类型为长整型(long)。在实际的标准系统中,长整型long无法存储12!以上的阶乘值。

函数的声明(Declaring functions)

到目前为止,我们定义的所有函数都是在它们第一次被调用(通常是在main中)之前,而把main 函数放在最后。如果重复以上几个例子,但把main 函数放在其它被它调用的函数之前,你就会遇到编译错误。原因是在调用一个函数之前,函数必须已经被定义了,就像我们前面例子中所做的。

但实际上还有一种方法来避免在main 或其它函数之前写出所有被他们调用的函数的代码,那就是在使用前先声明函数的原型定义。声明函数就是对函数在的完整定义之前做一个短小重要的声明,以便让编译器知道函数的参数和返回值类型。它的形式是:

type name(argument_type1, argument_type2,...);它与一个函数的头定义(header definition)一样,除了:

? 它不包括函数的内容,也就是它不包括函数后面花括号{}内的所有语句。? 它以一个分号semicolon sign(;)结束。

? 在参数列举中只需要写出各个参数的数据类型就够了,至于每个参数的名字可以写,也可以不写,但是我们建议写上。例如:

// 声明函数原型

#include

void odd(int a);void even(int a);

int main(){ int i;do { cout << “Type a number:(0 to exit)”;cin >> i;odd(i);} while(i!=0);return 0;}

void odd(int a){ if((a%2)!=0)cout << “Number is odd.n”;else even(a);}

void even(int a){ if((a%2)==0)cout << “Number is even.n”;else odd(a);} Type a number(0 to exit): 9 Number is odd.Type a number(0 to exit): 6 Number is even.Type a number(0 to exit): 1030 Number is even.Type a number(0 to exit): 0 Number is even.这个例子的确不是很有效率,我相信现在你已经可以只用一半行数的代码来完成同样的功能。但这个例子显示了函数原型(prototyping functions)是怎样工作的。并且在这个具体的例子中,两个函数中至少有一个是必须定义原型的。这里我们首先看到的是函数odd 和even的原型: void odd(int a);void even(int a);这样使得这两个函数可以在它们被完整定义之前就被使用,例如在main中被调用,这样main就可以被放在逻辑上更合理的位置:即程序代码的开头部分。

尽管如此,这个程序需要至少一个函数原型定义的特殊原因是因为在odd 函数里需要调用even 函数,而在even 函数里也同样需要调用odd函数。如果两个函数任何一个都没被提前定义原型的话,就会出现编译错误,因为或者odd 在even 函数中是不可见的(因为它还没有被定义),或者even 函数在odd函数中是不可见的。

很多程序员建议给所有的函数定义原型。这也是我的建议,特别是在有很多函数或函数很长的情况下。把所有函数的原型定义放在一个地方,可以使我们在决定怎样调用这些函数的时候轻松一些,同时也有助于生成头文件。

第三章 高级数据类型(Advanced Data)1.数组 Arrays 2.字符序列

Characters Sequences 3.指针 Pointers 4.动态内存分配 Dynamic memory 5.数据结构 Data Structures 6.自定义数据类型

User defined data types 3.1 数组(Arrays)

数组(Arrays)是在内存中连续存储的一组同种数据类型的元素(变量),每一数组有一个唯一名称,通过在名称后面加索引(index)的方式可以引用它的每一个元素。

也就是说,例如我们有5个整型数值需要存储,但我们不需要定义5个不同的变量名称,而是用一个数组(array)来存储这5个不同的数值。注意数组中的元素必须是同一数据类型的,在这个例子中为整型(int)。

例如一个存储5个整数叫做billy的数组可以用下图来表示:

这里每一个空白框代表数组的一个元素,在这个例子中为一个整数值。白框上面的数字0 到4 代表元素的索引(index)。注意无论数组的长度如何,它的第一个元素的索引总是从0开始的。

同其它的变量一样,数组必须先被声明然后才能被使用。一种典型的数组声明显示如下: type name [elements];这里type 是可以使任何一种有效的对象数据类型(object type),如 int, float...等,name 是一个有效地变量标识(identifier),而由中括号[]引起来的elements 域指明数组的大小,即可以存储多少个元素。

因此,要定义上面图中显示的 billy 数组,用一下语句就可以了: int billy [5];备注:在定义一个数组的时候,中括号[]中的elements 域必须是一个常量数值,因为数组是内存中一块有固定大小的静态空间,编译器必须在编译所有相关指令之前先能够确定要给该数组分配多少内存空间。

初始化数组(Initializing arrays)当声明一个本地范围内(在一个函数内)的数组时,除非我们特别指定,否则数组将不会被初始化,因此它的内容在我们将数值存储进去之前是不定的。如果我们声明一个全局数组(在所有函数之外),则它的内容将被初始化为所有元素均为0。因此,如果全局范围内我们声明: int billy [5];那么billy 中的每一个元素将会被初始化为0:

另外,我们还可以在声明一个变量的同时把初始值付给数组中的每一个元素,这个赋值用花括号{ }来完成。例如:

int billy [5] = { 16, 2, 77, 40, 12071 };这个声明将生成如下数组:

花括号中我们要初始化的元素数值个数必须和数组声明时方括号[ ]中指定的数组长度相符。例如,在上面例子中数组billy 声明中的长度为5,因此在后面花括号中的初始值也有5个,每个元素一个数值。

因为这是一种信息的重复,因此C++允许在这种情况下数组[ ]中为空白,而数组的长度将有后面花括号{}中数值的个数来决定,如下例所示。int billy [] = { 16, 2, 77, 40, 12071 };存取数组中数值(Access to the values of an Array)在程序中我们可以读取和修改数组任一元素的数值,就像操作其他普通变量一样。格式如下: name[index] 继续上面的例子,数组billy 有5个元素,其中每一元素都是整型int,我们引用其中每一个元素的名字分别为如下所示:

例如,要把数值75存入数组billy 中第3个元素的语句可以是: billy[2] = 75;又例如,要把数组billy 中第3个元素的值赋给变量a,我们可以这样写: a = billy[2];因此,在所有使用中,表达式billy[2]就像任何其他整型变量一样。

注意数组billy 的第3个元素为billy[2],因为索引(index)从0开始,第1个元素是billy[0],第2个元素是billy[1],因此第3个是 billy[2]。同样的原因,最后一个元素是billy[4]。如果我们写billy[5],那么是在使用billy的第6个元素,因此会超出数组的长度。

在C++ 中对数组使用超出范围的index是合法的,这就会产生问题,因为它不会产生编译错误而不易被察觉,但是在运行时会产生意想不到的结果,甚至导致严重运行错误。超出范围的index 之所以合法的原因我们在后面学习指针(pointer)的时候会了解。学到这里,我们必须能够清楚的了解方括号[ ]在对数组操作中的两种不同用法。它们完成两种任务:一种是在声明数组的时候定义数组的长度;另一种是在引用具体的数组元素的时候指明一个索引号(index)。我们要注意不要把这两种用法混淆。int billy[5];// 声明新数组(以数据类型名称开头)billy[2] = 75;// 存储数组的一个元素 其它合法的数组操作:

billy[0] = a;// a为一个整型变量 billy[a] = 75;b = billy [a+2];billy[billy[a]] = billy[2] + 5;

// arrays example #include

int billy [ ] = {16, 2, 77, 40, 12071};int n, result=0;

int main(){ for(n=0;n<5;n++){ result += billy[n];}

cout << result;return 0;} 12206

多维数组(Multidimensional Arrays)

多维数组(Multidimensional Arrays)可以被描述为数组的数组。例如,一个2维数组(bidimensional array)可以被想象成一个有同一数据类型的2维表格。

jimmy 显示了一个整型(int)的3x5二维数组,声明这一数组的的方式是: int jimmy [3][5];而引用这一数组中第2列第4排元素的表达式为:jimmy[1][3]

(记住数组的索引总是从0开始)。多维数组(Multidimensional arrays)并不局限于2维。如果需要,它可以有任意多维,虽然需要3维以上的时候并不多。但是考虑一下一个有很多维的数组所需要的内存空间,例如: char century [100][365][24][60][60];给一个世纪中的每一秒赋一个字符(char),那么就是多于30亿的字符!如果我们定义这样一个数组,需要消耗3000M的内存。

多维数组只是一个抽象的概念,因为我们只需要把各个索引的乘积放入一个简单的数组中就可以获得同样的结果。例如:

int jimmy [3][5];效果上等价于 int jimmy [15];(3 * 5 = 15)唯一的区别是编译器帮我们记住每一个想象中的维度的深度。下面的例子中我们就可以看到,两段代码一个使用2维数组,另一个使用简单数组,都获得同样的结果,即都在内存中开辟了一块叫做jimmy的空间,这个空间有15个连续地址位置,程序结束后都在相同的位置上存储了相同的数值,如后面图中所示: // multidimensional array #include #define WIDTH 5 #define HEIGHT 3

int jimmy [HEIGHT][WIDTH];int n,m;

int main(){ for(n=0;n

return 0;} // pseudo-multidimensional array #include #define WIDTH 5 #define HEIGHT 3

int jimmy [HEIGHT * WIDTH];int n,m;

int main(){ for(n=0;n

#define HEIGHT 4 而不需要对程序的其他部分作任何修改。

数组参数(Arrays as parameters)

有时候我们需要将数组作为参数传给函数。在C++ 中将一整块内存中的数值作为参数完整的传递给一个函数是不可能的,即使是一个规整的数组也不可能,但是允许传递它的地址。它们的实际作用是一样的,但传递地址更快速有效。

要定义数组为参数,我们只需要在声明函数的时候指明参数数组的基本数据类型,一个标识后面再跟一对空括号[]就可以了。例如以下的函数: void procedure(int arg[])接受一个叫做arg的整型数组为参数。为了给这个函数传递一个按如下定义的数组: int myarray [40];其调用方式可写为: procedure(myarray);下面我们来看一个完整的例子: // arrays as parameters #include

void printarray(int arg[ ], int length){ for(int n=0;n

int main(){ int firstarray[ ] = {5, 10, 15};int secondarray[ ] = {2, 4, 6, 8, 10};printarray(firstarray,3);printarray(secondarray,5);return 0;} 5 10 15 2 4 6 8 10 可以看到,函数的第一个参数(int arg[ ])接受任何整型数组为参数,不管其长度如何。因此,我们用了第2个参数来告知函数我们传给它的第一个参数数组的长度。这样函数中打印数组内容的for 循环才能知道需要检查的数组范围。

在函数的声明中也包含多维数组参数。定义一个3维数组(tridimensional array)的形式是:

base_type[ ][depth][depth] 例如,一个函数包含多维数组参数的函数可以定义为: void procedure(int myarray[ ][3][4])注意第一对括号[ ]中为空,而后面两对不为空。这是必须的,因为编译器必须能够在函数中确定每一个增加的维度的深度。

数组作为函数的参数,不管是多维数组还是简单数组,都是初级程序员容易出错的地方。建议阅读章节3.3, 指针(Pointers),以便更好的理解数组(arrays)是如何操作的。

3.2 字符序列(Character Sequences)

前面基础知识部分讲C++变量类型的时候,我们已经提到过C++的标准函数库提供了一个string类来支持对字符串的操作。然而,字符串实际就是一串连续的字符序列,所以我们也可以用简单的字符数组来表示它。例如,下面这个数组: char jenny [20];是一个可以存储最多20个字符类型数据的数组。你可以把它想象成:

理论上这数组可以存储长度为20的字符序列,但是它也可以存储比这短的字符序列,而且实际中常常如此。例如,jenny 在程序的某一点可以只存储字符串“Hello” 或者“Merry christmas”。因此,既然字符数组经常被用于存储短于其总长的字符串,就形成了一种习惯在字符串的有效内容的结尾处加一个空字符(null character)来表示字符结束,它的常量表示可写为0 或''。

我们可以用下图表示jenny(一个长度为20的字符数组)存储字符串“Hello” 和“Merry Christmas” :

注意在有效内容结尾是如何用空字符null character('')来表示字符串结束的。后面灰色的空格表示不确定数值。

初始化以空字符结束的字符序列(Initialization of null-terminated character sequences)因为字符数组其实就是普通数组,它与数组遵守同样的规则。例如,如果我们想将数组初始化为指定数值,我们可以像初始化其它数组一样用:

char mystring[] = { 'H', 'e', 'l', 'l', 'o', '' };在这里我们定义了一个有6个元素的字符数组,并将它初始化为字符串Hello 加一个空字符(null character '')。

除此之外,字符串还有另一个方法来进行初始化:用字符串常量。

在前几章的例子中,字符串常量已经出现过多次,它们是由双引号引起来的一组字符来表示的,例如:

“the result is: ” 是一个字符串常量,我们在前面的例子中已经使用过。与表示单个字符常量的单引号(')不同,双引号(“)是表示一串连续字符的常量。由双引号引起来的字符串末尾总是会被自动加上一个空字符('')。

因此,我们可以用下面两种方法的任何一种来初始化字符串mystring: char mystring [ ] = { 'H', 'e', 'l', 'l', 'o', '' };char mystring [ ] = ”Hello“;在两种情况下字符串或数组mystring都被定义为6个字符长(元素类型为字符char):组成Hello的5个字符加上最后的空字符('')。在第二种用双引号的情况下,空字符('')是被自动加上的。

注意:同时给数组赋多个值只有在数组初始化时,也就是在声明数组时,才是合法的。象下面代码现实的表达式都是错误的: mystring = ”Hello“;mystring[ ] = ”Hello“;mystring = { 'H', 'e', 'l', 'l', 'o', '' };因此记住:我们只有在数组初始化时才能够同时赋多个值给它。其原因在学习了指针(pointer)之后会比较容易理解,因为那时你会看到一个数组其实只是一个指向被分配的内存块的常量指针(constant pointer),数组自己不能够被赋予任何数值,但我们可以给数组中的每一个元素赋值。

在数组初始化的时候是特殊情况,因为它不是一个赋值,虽然同样使用了等号(=)。不管怎样,牢记前面标下画线的规则。

给字符序列的赋值

因为赋值运算的lvalue 只能是数组的一个元素,而不能使整个数组,所以,用以下方式将一个字符串赋给一个字符数组是合法的: mystring[0] = 'H';mystring[1] = 'e';mystring[2] = 'l';mystring[3] = 'l';mystring[4] = 'o';mystring[5] = '';但正如你可能想到的,这并不是一个实用的方法。通常给数组赋值,或更具体些,给字符序列赋值的方法是使用一些函数,例如strcpy。strcpy(string copy)在函数库cstring(string.h)中被定义,可以用以下方式被调用: strcpy(string1, string2);这个函数将string2 中的内容拷贝给string1。string2 可以是一个数组,一个指针,或一个字符串常量constant string。因此用下面的代码可以将字符串常量”Hello“赋给mystring: strcpy(mystring, ”Hello“);例如:

// setting value to string #include #include

int main(){ char szMyName [20];strcpy(szMyName,”J.Soulie“);cout << szMyName;return 0;} J.Soulie 注意:我们需要包括头文件才能够使用函数strcpy。

虽然我们通常可以写一个像下面setstring一样的简单程序来完成与cstring 中strcpy同样的操作:

// setting value to string #include

void setstring(char szOut [ ], char szIn [ ]){ int n=0;do { szOut[n] = szIn[n];} while(szIn[n++]!= '');}

int main(){ char szMyName [20];setstring(szMyName,”J.Soulie“);cout << szMyName;return 0;} J.Soulie 另一个给数组赋值的常用方法是直接使用输入流(cin)。在这种情况下,字符序列的值是在程序运行时由用户输入的。

当cin 被用来输入字符序列值时,它通常与函数getline 一起使用,方法如下: cin.getline(char buffer[], int length, char delimiter = ' n');这里buffer 是用来存储输入的地址(例如一个数组名),length 是一个缓存buffer 的最大容量,而delimiter 是用来判断用户输入结束的字符,它的默认值(如果我们不写这个参数时)是换行符newline character('n')。

下面的例子重复输出用户在键盘上的任何输入。这个例子简单的显示了如何使用cin.getline来输入字符串: // cin with strings #include

int main(){ char mybuffer [100];cout << ”What's your name? “;cin.getline(mybuffer,100);cout << ”Hello “ << mybuffer << ”.n“;cout << ”Which is your favourite team? “;cin.getline(mybuffer,100);cout << ”I like “ << mybuffer << ” too.n“;return 0;} What's your name? Juan Hello Juan.Which is your favourite team? Inter Milan I like Inter Milan too.注意上面例子中两次调用cin.getline 时我们都使用了同一个字符串标识(mybuffer)。程序在第二次调用时将新输入的内容直接覆盖到第一次输入到buffer 中的内容。你可能还记得,在以前与控制台(console)交互的程序中,我们使用extraction operator(>>)来直接从标准输入设备接收数据。这个方法也同样可以被用来输入字符串,例如,在上面的例子中我们也可以用以下代码来读取用户输入: cin >> mybuffer;这种方法也可以工作,但它有以下局限性是cin.getline所没有的:

? 它只能接收单独的词(而不能是完整的句子),因为这种方法以任何空白符为分隔符,包括空格spaces,跳跃符tabulators,换行符newlines和回车符arriage returns。

? 它不能给buffer指定容量,这使得程序不稳定,如果用户输入超出数组长度,输入信息会被丢失。

因此,建议在需要用cin来输入字符串时,使用cin.getline来代替cin >>。

字符串和其它数据类型的转换(Converting strings to other types)鉴于字符串可能包含其他数据类型的内容,例如数字,将字符串内容转换成数字型变量的功能会有用处。例如一个字符串的内容可能是”1977“,但这一个5个字符组成序列,并不容易转换为一个单独的整数。因此,函数库cstdlib(stdlib.h)提供了3个有用的函数: ? atoi: 将字符串string 转换为整型int ? atol: 将字符串string 转换为长整型long ? atof: 将字符串string 转换为浮点型float 所有这些函数接受一个参数,返回一个指定类型的数据(int, long 或 float)。这三个函数与cin.getline 一起使用来获得用户输入的数值,比传统的cin>> 方法更可靠: // cin and ato* functions #include #include

int main(){ char mybuffer [100];float price;int quantity;cout << ”Enter price: “;cin.getline(mybuffer,100);price = atof(mybuffer);cout << ”Enter quantity: “;cin.getline(mybuffer,100);quantity = atoi(mybuffer);cout << ”Total price: “ << price*quantity;return 0;} Enter price: 2.75 Enter quantity: 21 Total price: 57.75

字符串操作函数(Functions to manipulate strings)函数库cstring(string.h)定义了许多可以像C语言类似的处理字符串的函数(如前面已经解释过的函数strcpy)。这里再简单列举一些最常用的:

? strcat: char* strcat(char* dest, const char* src);//将字符串src 附加到字符串dest 的末尾,返回dest。

? strcmp: int strcmp(const char* string1, const char* string2);//比较两个字符串string1 和string2。如果两个字符串相等,返回0。

? strcpy: char* strcpy(char* dest, const char* src);//将字符串src 的内容拷贝给dest,返回dest。

? strlen: size_t strlen(const char* string);//返回字符串的长度。注意:char* 与char[] 相同。

关于这个函数库的更多信息,参阅 C++ Reference。

3.3 指针(Pointers)

我们已经明白变量其实是可以由标识来存取的内存单元。但这些变量实际上是存储在内存中具体的位置上的。对我们的程序来说,计算机内存只是一串连续的单字节单元(1byte cell),即最小数据单位,每一个单元有一个唯一地址。

计算机内存就好像城市中的街道。在一条街上,所有的房子被顺序编号,每所房子有唯一编号。因此如果我们说芝麻街27号,我们很容易找到它,因为只有一所房子会是这个编号,而且我们知道它会在26号和28号之间。同房屋按街道地址编号一样,操作系统(operating system)也按照唯一顺序编号来组织内存。因此,当我们说内存中的位置1776,我们知道内存中只有一个位置是这个地址,而且它在地址1775和1777之间。

地址操作符/去引操作符 Address/dereference operator(&)当我们声明一个变量的同时,它必须被存储到内存中一个具体的单元中。通常我们并不会指定变量被存储到哪个具体的单元中—幸亏这通常是由编译器和操作系统自动完成的,但一旦操作系统指定了一个地址,有些时候我们可能会想知道变量被存储在哪里了。

这可以通过在变量标识前面加与符号ampersand sign(&)来实现,它表示”...的地址“(”address of“),因此称为地址操作符(adress operator),又称去引操作符(dereference operator)。例如: ted = &andy;将变量andy的地址赋给变量ted,因为当在变量名称andy 前面加ampersand(&)符号,我们指的将不再是该变量的内容,而是它在内存中的地址。

假设andy 被放在了内存中地址1776的单元中,然后我们有下列代码: andy = 25;fred = andy;ted = &andy;其结果显示在下面的图片中:

我们将变量andy 的值赋给变量fred,这与以前我们看到很多例子都相同,但对于ted,我们把操作系统存储andy的内存地址赋给它,我们想像该地址为1776(它可以是任何地址,这里只是一个假设的地址),原因是当给ted 赋值的时候,我们在andy 前面加了ampersand(&)符号。

存储其它变量地址的变量(如上面例子中的ted),我们称之为指针(pointer)。在C++ 中,指针pointers 有其特定的优点,因此经常被使用。在后面我们将会看到这种变量如何被声明。

引用操作符Reference operator(*)使用指针的时候,我们可以通过在指针标识的前面加星号asterisk(*)来存储该指针指向的变量所存储的数值,它可以被翻译为“所指向的数值”(”value pointed by“)。因此,仍用前面例子中的数值,如果我们写: beth = *ted;(我们可以读作:”beth 等与ted所指向的数值“)beth 将会获得数值25,因为ted 是1776,而1776 所指向的数值为25。

你必须清楚的区分ted 存储的是1776,但*ted(前面加asterisk *)指的是地址1776中存储的数值,即25。注意加或不加星号*的不同(下面代码中注释显示了如何读这两个不同的表达式): beth = ted;// beth 等于 ted(1776)beth = *ted;// beth 等于 ted 所指向的数值(25)

地址或反引用操作符Operator of address or dereference(&)它被用作一个变量前缀,可以被翻译为“„的地址”(”address of“),因此:&variable1 可以被读作 variable1的地址(”address of variable1“)。引用操作符Operator of reference(*)它表示要取的是表达式所表示的地址指向的内容。它可以被翻译为“„指向的数值”(”value pointed by“)。

* mypointer 可以被读作 ”mypointer指向的数值"。继续使用上面开始的例子,看下面的代码: andy = 25;ted = &andy;现在你应该可以清楚的看到以下等式全部成立: andy == 25 &andy == 1776 ted == 1776 *ted == 25 第一个表达式很容易理解,因为我们有赋值语句andy=25。第二个表达式使用了地址(或反引用)操作符(&)来返回变量andy的地址,即 1776。第三个表达式很明显成立,因为第二个表达式为真,而我们给ted赋值的语句为ted = &andy。第四个表达式使用了引用操作符(*),相当于ted指向的地址中存储的数值,即25。

由此你也可以推断出,只要ted 所指向的地址中存储的数值不变,以下表达式也为真: *ted == andy 声明指针型变量Declaring variables of type pointer 由于指针可以直接引用它所指向的数值,因此有必要在声明指针的时候指明它所指向的数据类型。指向一个整型int或浮点型float数据的指针与指向一个字符型char数据的指针并不相同。

因此,声明指针的格式如下: type * pointer_name;这里,type 是指针所指向的数据的类型,而不是指针自己的类型。例如: int * number;char * character;float * greatnumber;它们是3个指针的声明,每一个指针指向一种不同数据类型。这三个指针本身其实在内存中占用同样大小的内存空间(指针的大小取决于不同的操作系统),但它们所指向的数据是不同的类型,并占用不同大小的内存空间,一个是整型int,一个是字符型char,还有一个是浮

第三篇:C语言基础教程(二)数据类型、变量和运算符

本节首先介绍Turbo C程序的基本组成部分;然后介绍Turbo C的数据类型、变量类型、变量的初始化和赋值;最后介绍Turbo C的有关操作。通过本节的学习, 可以对Turbo C语言有一个初步认识。1.Turbo C程序的一般组成部分

Turbo C 2.0 象其它语言一样按其规定的格式和提供的语句由用户编写应用 程序。请看下面一段Turbo C源程序。

例1: /*Example program of Turbo C*/ #include /*包含文件说明*/ void lgc(void);/*子函数说明*/ char answer;/*定义全程变量*/ int main()/*主函数定义*/ { char a;/*定义局部变量*/ clrscr();gotoxy(12,3);puts(“Welcome to use Turbo C2.0!”);gotoxy(15, 13);printf(“--Exit”);gotoxy(15, 15);printf(“--Continue”);while(1){ a=getch();if(a==27)break;if(a==13){ lgc();if(answer=='y'||answer=='Y'){ gotoxy(23,14);puts(“Please Write to the Company”);getch();break;} } } return(0);} void lgc(void){ clrscr();gotoxy(12,8);printf(“The Excellent Selection!”);gotoxy(21,12);printf(“Do you have any question?(Y/N)”);answer=getche();} 由例子程序可以看出, Turbo C源程序主要有以下几个特点: 1.程序一般用小写字母书写;2.大多数语句结尾必须要用“;”作为终止符, 否则Turbo C 不认为该语句结 束;3.每个程序必须有一个而且只能有一个称作主函数的main()函数;4.每个程序体(主函数和每个子函数, 如上例中的main()函数和sub()函数)必须用一对花括号“{”和“}”括起来;5.一个较完整的程序大致包括:包含文件(一组#include<*.h>语句)、用户 函数说明部分、全程变量定义、主函数和若干子函数组成。在主函数和子函数中 又包括局部变量定义、若干个Turbo C库函数、控制流程语句、用户函数的调用 语句等;6.注释部分包含在“/*”和“*/”之间, 在编译时它被Turbo C编译器忽略。说明: 1.象其它一些语言一样, Turbo C的变量在使用之前必须先定义其数据类型, 未经定义的变量不能使用。定义变量类型应在可执行语句前面, 如上例main()函 数中的第一条语句就是变量定义语句, 它必须放在第一各执行语句clrscr()前面。2.在Turbo C中, 大、小写字母是有区别的, 相同字母的大、小写代表不同 的变量。

3.Turbo C程序的书写格式非常灵活, 没有严格限制。

例1的主函数可写成: main(){char c;clrscr();gotoxy(12,3);puts(“Welcome to use Turbo C2.0!”);gotoxy(15,13);printf(“--Continue”);gotoxy(15,15);...} 这样写语法上没有错误, 但阅读起来不方便, 同时也使得程序层次不明确。作者建议用Turbo C编程时, 一行一条语句, 遇到嵌套语句向后缩进, 必要时对 程序加上注释行。这样可以便程序结构清楚、易于阅读、维护和修改。

通过以上介绍, 可以得出Turbo C源程序的一般形式为: 包含文件

子函数类型说明

全程变量定义 main(){ 局部变量定义 <程序体> } sub1(){ 局部变量定义 <程序体> } sub2(){ 局部变量定义 <程序体> }...subN(){ 局部变量定义 <程序体> } 其中sub1(),..., subN()代表用户定义的子函数, 程序体指Turbo C 2.0 提供的任何库函数调用语句、控制流程语句或其它用子函数调用语句等。

1.数据类型

在Turbo C语言中, 每个变量在使用之前必须定义其数据类型。Turbo C有以 下几种类型: 整型(int)、浮点型(float)、字符型(char)、指针型(*)、无值型(void)以及结构(struct)和联合(union)。其中前五种是Turbo C的基本数据类型、后两种数据类型(结构和联合)将在第五章介绍。2.1 整型(int)

一、整型数说明

加上不同的修饰符, 整型数有以下几种类型;signed short int 有符号短整型数说明。简写为short或int, 字长为2 字节共16位二进制数, 数的范围是-32768~32767。signed long int 有符号长整型数说明。简写为long, 字长为4字节共 32位二进制数, 数的范围是-2147483648~2147483647。unsigned short int 无符号短整型数说明。简写为unsigned int, 字长

为2字节共16位二进制数, 数的范围是0~65535。unsigned long int 无符号长整型数说明。简写为unsigned long, 字长

为4字节共32位二进制数, 数的范围是0~4294967295。

二、整型变量定义

可以用下列语句定义整型变量

int a, b;/*a、b被定义为有符号短整型变量*/ unsigned long c;/*c被定义为无符号长整型变量*/

三、整型常数表示

按不同的进制区分, 整型常数有三种表示方法: 十进制数: 以非0开始的数

如:220,-560, 45900 八进制数: 以0开始的数

如:06;0106, 05788 十六进制数:以0X或0x开始的数 如:0X0D, 0XFF, 0x4e 另外, 可在整型常数后添加一个“L”或“l”字母表示该数为长整型数, 如22L, 0773L, 0Xae4l。2.2 浮点型(float)

一、浮点数说明

Turbo C中有以下两种类型的浮点数: float 单浮点数。字长为4 个字节共32 位二进制数, 数的范围是 3.4x10-38E~3.4x10+38E。

double 双浮点数。字长为 8个字节共 64 位二进制数, 数的范围是 1.7x10-308E~1.7x10+308E。

说明: 浮点数均为有符号浮点数, 没有无符号浮点数。

二、浮点型变量定义

可以用下列语句定义浮点型变量: float a, f;/*a, f被定义为单浮点型变量*/ double b;/*b被定义为双浮点型变量*/

三、浮点常数表示

例如: +29.56,-56.33,-6.8e-18, 6.365 说明: 1.浮点常数只有一种进制(十进制)。2.所有浮点常数都被默认为double。

3.绝对值小于1的浮点数, 其小数点前面的零可以省略。如:0.22可写为.22,-0.0015E-3可写为-.0015E-3。

4.Turbo C默认格式输出浮点数时, 最多只保留小数点后六位。

2.3 字符型(char)加上不同的修饰符, 可以定义有符号和无符号两种类型的字符型变量, 例如: char a: /*a被定义为有符号字符变量*/ unsigned char l;/*l被定义为无符号字符变量*/ 字符在计算机中以其ASCII码方式表示, 其长度为1个字节, 有符号字符型数 取值范围为-128~127, 无符号字符型数到值范围是0~255。因此在Turbo C语言中, 字符型数据在操作时将按整型数处理, 如果某个变量定义成char, 则表明该变量 是有符号的, 即它将转换成有符号的整型数。

Turbo C中规定对ASCII码值大于0x80的字符将被认为是负数。例如ASCII 值 为0x8c的字符, 定义成char时, 被转换成十六进制的整数0xff8c。这是因当 ASCII码值大于0x80时, 该字节的最高位为1, 计算机会认为该数为负数, 对于 0x8c表示的数实际上是-74(8c的各位取反再加1), 而-74 转换成两字节整型数并 在计算机中表示时就是0xff8c(对0074 各位取反再加1)。因此只有定义为 unsigned char 0x8c转换成整型数时才是8c。这一点在处理大于0x80的ASCII码 字符时(例如汉字码)要特别注意。一般汉字均定义为unsigned char(在以后的程 序中会经常碰到)。

另外, 也可以定义一个字符型数组(关于数组后面再作详细介绍), 此时该数 组表示一个字符串。

例如: char str[10];计算机在编译时, 将留出连续10个字符的空间, 即str[0]到str[9]共10个变 量, 但只有前9个供用户使用。第10个str[9]用来存放字符串终止符NULL即“”, 但终止符是编编译程序自动加上的, 这一点应特别注意。

二、字符常数表示

能用符号表示的字符可直接用单引号括起来表示, 如'a', '9', 'Z', 也可用 该字符的ASCII码值表示, 例如十进制数85表示大写字母'U', 十六进制数0x5d表示 ']', 八进制数0102表示大写字母'B'。

一些不能用符号表示的控制符, 只能用ASCII码值来表示, 如十进制数10 表示 换行, 下六进制数0x0d表示回车, 八进制数033表示Esc。Turbo C2.0中也有另外一 种表示表示方法, 如'33'表示Esc, 这里' 0' 符号后面的数字表示十六进制的 ASCII值当然这种表示方法也适用于可睦接用符号表示的字符。

另外, Turbo C2.0中有些常用的字符用以下特殊规定来表示: 规定符 等价于 含义 'f' 'X0C' 换页 'r' 'X0D' 回车 't' 'X09' 制表键 'n' 'X0A' 换行 '' 'X5C' 符 ''' 'X27' '符 '“' 'X22' ”符

对于字符串常量, 一般用双引号括起来表示, 如“Hello Turbo C2.0”。2.4 指针型(*)指针是一种特殊的数据类型, 在其它语言中一般没有。指针是指向变量的地址, 实质上指针就是存贮单元的地址。根据所指的变量类型不同, 可以是整型指针(int *)、浮点型指针(float *)、字符型指针(char *)、结构指针(struct *)和联 合指针(union *)(结构指针和联合指针将在第4节中介绍)。

2.5 无值型(void)无值型字节长度为0, 主要有两个用途: 一是明确地表示一个函数不返回任何 值;一是产生一个同一类型指针(可根据需要动态分配给其内存)。

例如: void *buffer;/*buffer被定义为无值型指针*/ 2 关键字和标识符

3.1 关键字

所谓关键字就是已被Turbo C2.0本身使用, 不能作其它用途使用的字。例如关 键字不能用作变量名、函数名等。Turbo C2.0有以下关键字: Turbo C2.0扩展的共11个

asm _cs _ds _es _ss cdecl far near huge interrupt pascal 由ANSI标准定义的共32个

auto double int struct break else long switch case enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof volatile do if while static 3.2 标识符

所谓标识符是指常量、变量、语句标号以及用户自定义函数的名称。Turbo C 2.0标识符的定义十分灵活。作为标识符必须满足以下规则: 1.所有标识符必须由一个字母(a~z, A~Z)或下划线(_)开头;2.标识符的其它部分可以用字母、下划线或数字(0~9)组成;3.大小写字母表示不同意义, 即代表不同的标识符;4.标识符只有前32个字符有效;5.标识符不能使用Turbo C2.0的关键字。

下面举出几个正确和不正确的标识符: 正确 不正确 smart 5smart _decision bomb? key_board key.board FLOAT float 3.变量

4.1 变量说明

Turbo C2.0规定所有变量在使用前都必须中以说明。一条变量说明语句由数据 类型和其后的一个或多个变量名组成。变量说明的形式如下: 类型 <变量表>;这里类型是指Turbo C2.0的有效数据类型。变量表是一个或多个标识符名, 每 个标识符之间用“,”分隔。

例如: int i, j, k;unsigned char c, str[5], *p;4.2 变量种类

变量可以在程序中三个地方说明: 函数内部、函数的参数定义中或所有的函数 外部。根据所定义位置的不同, 变量可分为局部变量、形式参数和全程变量。

一、局部变量

局部变量是指在函数内部说明的变量(有时也称为自动变量)。用关键字auto进 行说明, 当auto省略时, 所有的非全程变量都被认为是局部变量, 所以auto实际上 从来不用。

局部变量在函数调用时自动产生, 但不会自动初始化, 随函数调用的结束, 这 个变量也就自动消失了, 下次调用此函数时再自动产生, 还要再赋值, 退出时又自 动消失。

二、形式参数

形式参数是指在函数名后面的小括号里定义的变量, 用于接受来自调用函数的 参数。形式参数在函数内部可以象其它局部变量那样来作用。例如: puthz(int x, int y, int color, char *p){ int i, j, k;/*定义局部变量*/ <程序体> } 其中x, y, color, *p为函数的形式参数, 不需要再进行说明就可在该函数内 直使用。

三、全程变量

全程变量是指在所有函数之外说明的变量, 它在整个程序内部者是“可见的”, 可以被任何一个函数使用, 并且在整个程序的运行中都保留其值。全程变量只要满 足在使用它以前和函数以外这两个条件, 可在程序的任何位置进行说明,习惯上通 常在程序的主函数前说明。

例如: #include int test;/*定义全程变量*/ void f1(int x, float y);/*子函数说明*/ void f2(void);/*子函数说明*/ main(){ test=5;/*给全程变量赋值*/ f1(20, 5.5);/*调用有形式参数的子函数f1()*/ /*test的值变成115*/ f2();/*调用f2(), test的值变为1150*/ } void f1(int x, float y){ float z;/*z定义为局部变量*/ z=x*y;/*计算*/ test=test+z;} void f2(void){ int count=10;/*定义局部变量并初始化*/ test=test*count;} 由于全程变量可被整个程序内的任何一个函数使用, 所以可作为函数之间传递 参数的手段, 但全程变量太多时, 内存开销变大。4.3 变量存储类型

Turbo C2.0支持四种变量存储类型。说明符如下: auto static extern register 下面分别来介绍。

一、auto auto称为自动变量, 已在前面作了介绍, 这里不再重复。

二、static static称为静态变量。根据变量的类型可以分为静态局部变量和静态全程变量。1.静态局部变量

它与局部变量的区别在于: 在函数退出时, 这个变量始终存在, 但不能被其它 函数使用, 当再次进入该函数时, 将保存上次的结果。其它与局部变量一样。2.静态全程变量

Turbo C2.0允许将大型程序分成若干独立模块文件分别编译, 然后将所有模块 的目标文件连接在一起, 从而提高编译速度, 同时也便于软件的管理和维护。静态 全程变量就是指只在定义它的源文件中可见而在其它源文件中不可见的变量。它与 全程变量的区别是: 全程变量可以再说明为外部变量(extern), 被其它源文件使用, 而静态全程变量却不能再被说明为外部的, 即只能被所在的源文件使用。

三、extern extern称为外部变量。为了使变量除了在定义它的源文件中可以使用外, 还要 被其它文件使用。因此, 必须将全程变量通知每一个程序模块文件, 此时可用 extern来说明。例如: 文件1为file1.c 文件2为file2.c int i, j;/*定义全程变量*/ extern int i, j;/*说明将i, j从

文件1中复制过来*/ char c;extern char c;/*将c复制过来*/ void func1(int k);func2()/*用户定义函数*/ { main()static float k;/*定义静态变量*/ { i=j*5/100;func1(20);/*调用函数*/ k=i/1.5;func2();......} } func1(int k)/*用户定义函数*/ { j=k*100;} 对于以上两个文件file1.c和file2.c, 用Turbo C2.0的集成开发环境进行编译 连接时, 首先应建立一个.prj的文件。例如file.prj, 该文件内容如下: file1.c file2.c 然后将file.prj的文件名写入主菜单Project中的Project Name项中。再用F9 编译连接, 就可产生一个文件名为fioe.exe的可执行文件。

外部变量和FORTRAN语言中的COMMOM定义的公共变量一样。

四、register register称为寄存器变量。它只能用于整型和字符型变量。定义符register说 明的变量被Turbo C2.0存储在CPU的寄存器中, 而不是象普通的变量那样存储在内 存中, 这样可以提高运算速度。但是Turbo C2.0只允许同时定义两个寄存器变量, 一旦超过两个, 编译程序会自动地将超过限制数目的寄存器变量当作非寄存器变量 来处理。因此, 寄存器变量常用在同一变量名频繁出现的地方。

另外, 寄存器变量只适用于局部变量和函数的形式参数, 它属于auto型变量, 因此, 不能用作全程变量。定义一个整型寄存器变量可写成: register int a;对于以上所介绍的变量类型和变量存储类型将会在以后的学习中, 通过例行程 序中的定义、使用来逐渐加深理解。4.4 数组变量

所谓数组就是指具有相同数据类型的变量集, 并拥有共同的名字。数组中的每 个特定元素都使用下标来访问。数组由一段连续的存贮地址构成, 最低的地址对应 于第一个数组元素, 最高的地址对应最后一个数组元素。数组可以是一维的、也可 以是多维的。Turbo C2.0象它高级语方一样也使用数组变量。

一、一维数组

一维数组的说明格式是: 类型 变量名[长度];类型是指数据类型, 即每一个数组元素的数据类型, 包括整数型、浮点型、字 符型、指针型以及结构和联合。

例如: int a[10];unsigned long a[20];char *s[5];char *f[];说明: 1.数组都是以0作为第一个元素的下标, 因此, 当说明一个int a[16] 的整型 数组时, 表明该数组有16个元素, a[0]~a[15], 一个元素为一个整型变量。2.大多数字符串用一维数组表示。数组元素的多少表示字符串长度, 数组名 表示字符串中第一个字符的地址, 例如在语句char str[ 8] 说明的数组中存入 “hello”字符串后, str表示第一个字母“h”所在的内存单元地址。str[0] 存放的是 字母“h”的ASCII码值, 以此类推, str[4]存入的是字母“o”的ASCII码值, str[5]则 应存放字符串终止符''。

3.Turbo C2.0对数组不作边界检查。例如用下面语句说明两个数组 char str1[5], str2[6];当赋给str1一个字符串“ABCDEFG”时, 只有“ABCDE”被赋给, “E” 将会自动的赋 给str2, 这点应特别注意。

三、多维数组

多维数组的一般说明格式是: 类型 数组名[第n维长度][第n-1维长度]......[第1维长度];这种说明方式与BASIC、FORTRAN等语言中多维数组的说明不一样。

例如: int m[3][2];/*定义一个整数型的二维数组*/ char c[2][2][3];/*定义一个字符型的三维数组*/ 数组m[3][2]共有3*2=6个元素, 顺序为: m[0][0], m[0][1], m[1][0], m[1][1], m[2][0], m[2][1];数组c[2][2][3]共有2*2*3=12个元素, 顺序为: c[0][0][0], c[0][0][1], c[0][0][2], c[0][1][0], c[0][1][1], c[0][1][2], c[1][0][0], c[1][0][1], c[1][0][2], c[1][1][0], c[1][1][1], c[1][1][2], 数组占用的内存空间(即字节数)的计算式为: 字节数=第1维长度*第2维长度*...*第n维长度*该数组数据类型占用的字节数 4.5 变量的初始化和赋值

一、变量的初始化

变量的初始化是指变量在被说明的同时赋给一个初值。Turbo C2.0中外部变量 和静态全程变量在程序开始处被初始化, 局部变量包括静态局部变量是在进入定义 它们的函数或复合语句时才作初始化。所有全程变量在没有明确的初始化时将被自 动清零, 而局部变量和寄存器变量在未赋值前其值是不确定的。

对于外部变量和静态变量, 初值必须是常数表达式, 而自动变量和寄存器变量 可以是任意的表达式, 这个表达式可以包括常数和前面说明过的变量和函数。1.单个变量的初始化

例如: float f0, f1=0.2;/*定义全程变量, 在初始化时f0被清零, f1被赋0.2*/ main(){ static int i=10, j;/*定义静态局部变量, 初始化时i被赋10, j不确 定*/ int k=i*5;/*定义局部变量, 初始化时k被赋10*5=50*/ char c='y';/*定义字符型指什变量并初始化*/...} 2.数组变量的初始化

例如: main(){ int p[2][3]={{2,-9, 0}, {8, 2,-5}};/*定义数组p并初始化/* int m[2][4]={{27,-5, 19, 3}, {1, 8,-14,-2}};/*定义数组m并初

始化*/ char *f[]={'A', 'B', 'C'};/*定义数组f并初始化*/...} 从上例可以看出: Turbo C2.0中数组进行初始化有下述规则:(1)数组的每一行初始化赋值用“{}”并用“,”分开, 总的再加一对“{}”括起来, 最后以“;”表示结束。

(2)多维数组的存储是按最右维数的变量变化最快的原则。

(3)多维数组存储是连续的, 因此可以用一维数组初始化的办法来初始化多维 数组。

例如: int x[2][3]={1, 2, 3, 4, 5, 6};/*用一维数组来初始化二维数组*/(4)对数组初始化时, 如果初值表中的数据个数比数组元素少, 则不足的数组 元素用0来填补。

(5)对指针型变量数组可以不规定维数, 在初始化赋值时, 数组维数从0 开始 被连续赋值。

例如: char *f[]={'a', 'b', 'c'};初始化时将会给3个字符指针赋值, 即: *f[0]='a', *f[1]='b', *f[2]='c'。3.指针型变量的初始化

例如: main(){ int *i=7899;/*定义整型数指针变量并初始化*/ float *f=3.1415926;/*定义浮点数指针变量并初始化*/ char *s=“Good”;/*定义字符型指针变量并初始化*/...}

二、变量的赋值

变量赋值是给已说明的变量赋给一个特定值。1.单个变量的赋值(1)整型变量和浮点变量

这两种变量采用下列格式赋值 变量名=表达式;例如: main(){ int a, m;/*定义局部整型变量a, m*/ float n;/*定义局部浮点变量f*/ a=100, m=20;/*给变量赋值*/ n=a*m*0.1;...} 说明: Turbo C2.0中允许给多个变量赋同一值时可用连等的方式。

例如: main(){ int a, b, c;a=b=c=0;/*同时给a,b,c赋值*/...}(2)字符型变量

字符型变量可以用三种方法赋值。

例如: main(){ char a0, a1, a2;/*定义局部字符型变量a0, a1, a2*/ a0='b';/*将字母b赋给a0*/ a1=50;/*将数字2(十进制ASCII值为50赋给a1*/ a2='x0d';/*将回车符赋给a2*/...}(3)指针型变量

例如: main(){ int *i;char *str;*i=100;str=“Good”;...} *i表示i是一个指向整型数的指针, 即*i是一个整型变量, i是一个指向该整型 变量的地址。

*str表示str是一个字符型指针, 即保留某个字符地址。在初始化时, str没有 什么特殊的值, 而在执行str=“Good”时, 编译器先在目标文件的某处保留一个空间 存放“Good”的字符串, 然后把这个字符串的第一个字母“G”的地址赋给str, 其中 字符串结尾符“”是编译程序自动加上的。

对于指针变量的使用要特别注意。上例中两个指针在说明前没有初始化, 因此

这两指针为随机地址, 在小存储模式下使用将会有破坏机器的危险。正确的使用办

法如下:

例如: main()

{

int *i;

char *str;

i=(int*)malloc(sizeof(int));

i=420;

str=(char*)malloc(20);

str=“Good, Answer!”;

...}

上例中, 函数(int*)malloc(sizeof(int))表示分配连续的sizeof(int)=2个字

节的整型数存储空间并返回其首地址。同样(char*)malloc(20)表示分配连续20 个

字节的字符存储空间并返回首地址(有关该函数以后再详述)。由动态内存分配函数

malloc()分配了内存空间后, 这部分内存将专供指针变量使用。

如果要使i指向三个整型数, 则用下述方法。

例如:

#include

main()

{

int *a;

a=(int*)malloc(3*sizeof(int));

*a=1234;

*(a+1)=4567;

*(a+2)=234;

...}

*i=1234表示把1234存放到i指向的地址中去, 但对于*(i+1)=4567, 如果认为

将4567存放到i指向的下一个字节中就错了。Turbo C2.0中只要说明i为整型指针, 则(i+1)等价于 i+1*sizeof(int)同样(i+2)等价于 i+2*sizeof(int)2.数组变量的赋值

(1)整型数组和浮点数组的赋值

例如: main(){ int m[2][2];float n[3];m[0][0]=0, m[0][1]=17, m[1][0]=21;/*数组元素赋值*/ n[0]=109.5, n[1]=-8.29, n[2]=0.7;...}(2)字符串数组的赋值

例如: main(){ char s[30];strcpy(s, “Good News!”);/*给数组赋字符串*/...} 上面程序在编译时, 遇到char s[30]这条语句时, 编译程序会在内存的某处留 出连续30个字节的区域, 并将第一个字节的地址赋给s。当遇到strcpy(strcpy 为 Turbo C2.0的函数)时, 首先在目标文件的某处建立一个“Good News!” 的字符串。其中表示字符串终止, 终止符是编译时自动加上的, 然后一个字符一个字符地复 制到s所指的内存区域。因此定义字符串数组时, 其元素个数至少应该比字符串的 长度多1。

注意: 1.字符串数组不能用“=”直接赋值, 即s=“Good News!”是不合法的。所以应分 清字符串数组和字符串指针的不同赋值方法。

2.对于长字符串, Turbo C2.0允许使用下述方法: 例如: main(){ char s[100];strcpy(s, “The writer would like to thank you for” “your interest in his book.He hopes you” “can get some helps from the book.”);...}(3)指针数组赋值

例如: main(){ char *f[2];int *a[2];f[0]=“thank you”;/*给字符型数组指针变量赋值*/ f[1]=“Good Morning”;*a[0]=1, *a[1]=-11;/*给整型数数组指针变量赋值*/...}

三、数组与指针

数组与指针有密切的联系。数组名本身就是该数组的指针, 反过来, 也可以把 指针看成一个数组, 数组名和指针实质上都是地址, 但是指针是变量, 可以作运算。而数组名是常量, 不能进行运算。

例如: main(){ char s[30], *p;/*定义字符型数组和指针变量*/ p=s;/*指针p指向数组s的第一个元素s[0]的地址*/...*(p+8);/*指针p指向数组s的第9个元素s[8]的地址*/...} 由上例可以看出数组和指针有如下关系:(p+i)=&(s[i])*(p+i)=s[i] 因此, 利用上述表达式可以对数组和指针进行互换。两者的区别仅在于: 数组 s是程序自动为它分配了所需的存储空间;而指针p则是利用动态分想函数为它分配 存储空间或赋给它一个已分配的空间地址。

5.运算符

Turbo C的运算符非常丰富, 主要分为三大类: 算术运算符, 关系运算符与 逻辑运算符, 按位运算符。除此之外, 还有一些用于完成特殊任务的运算符。下 面分别进行介绍。5.1 算术运算符

Turbo C的算术运算符如下: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 操作符 作用

──────────────────────────── + 加, 一目取正 位逻辑反

>> 右移

<< 左移

━━━━━━━━━━━━━━━━━━━━━━━━━━━━

按位运算是对字节或字中的实际位进行检测、设置或移位, 它只适用于字符

型和整数型变量以及它们的变体, 对其它数据类型不适用。

关系运算和逻辑运算表达式的结果只能是1或0。而按位运算的结果可以取0 或1以外的值。

要注意区别按位运算符和逻辑运算符的不同, 例如, 若x=7, 则x&&8 的值为

真(两个非零值相与仍为非零), 而x&8的值为0。

移位运算符“>>”和“<<”是指将变量中的每一位向右或向左移动, 其通常形式 为:

右移: 变量名>>移位的位数

左移: 变量名<<移位的位数

经过移位后, 一端的位被“挤掉”, 而另一端空出的位以0 填补, 所以, Turbo C中的移位不是循环移动的。

5.4 Turbo C的特殊运算符

一、“?”运算符

“?”运算符是一个三目运算符, 其一般形式是: <表达式1>?<表达式2>:<表达式3>;“?”运算符的含义是: 先求表达式1的值, 如果为真, 则求表达式2 的值并把 它作为整个表达式的值;如果表达式1 的值为假, 则求表达式3 的值并把它作为 整个表达式的值。

例如: main(){ int x, y;x=50;y=x>70?100:0;} 本例中, y将被赋值0。如果x=80, y将被赋值100。

因此, “?”运算符可以代替某些if-then-else形式的语句。

二、“&”和“*”运算符

“&”运算符是一个返回操作数地址的单目操作符。

“*”运算符是对“&”运算符的一个补充, 它返回位于这个地址内的变量值, 也 是单目操作符。

例如: main(){ int i, j, *m;i=10;m=&i;/*将变量i的地址赋给m*/ j=*m;/*地址m所指的单元的值赋给j*/ } 上面程序运行后, i=10, m为其对应的内存地址, j的值也为10。

三、“,”运算符

“,”运算符用于将多个表达式串在一起, “,”运算符的左边总不返回, 右边表 达式的值才是整个表达式的值。

例如: main(){ int x, y;x=50;y=(x=x-5, x/5);} 上面程序执行后y值为9, 因为x的初始值为50, 减5后变为45, 45除5为9赋给 y。

四、sizeof运算符

sizeof运算符是一个单目运算符, 它返回变量或类型的字节长度。

例如: sizeof(double)为8 sizeof(int)为2 也可以求已定义的变量, 例如: float f;int i;i=sizeof(f);则i的值将为4。

五、联合操作

Turbo C中有一特殊的简写方式, 它用来简化一种赋值语句, 适用于所有的 双目运算符。其一般形式为: <变量>=<变量><操作数><表达式> 相当于

<变量><操作数>=<表达式> 例如: a=a+b 可写成 a+=b a=a&b 可写成 a&=b a=a/(b-c)可写成 a/=b-c 5.5 Turbo C运算符的优先级

Turbo C规定了运算符的优先次序即优先级。当一个表达式中有多个运算符 参加运算时, 将按下表所规定的优先级进行运算。表中优先级从上往下逐渐降低, 同一行优先级相同。

例如: 表达式 10>4&&!(100<99)||3<=5 的值为1 表达式 10>4&&!(100<99)&&3<=5 的值为0 Turbo C运算符的优先次序

━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━

表达式 ┃优先级 ────────────────────────────╂────()(小括号)[](数组下标).(结构成员)->(指针型结构成员)┃ 最高 ────────────────────────────┃ ↑!(逻辑非).(位取反)-(负号)++(加1)--(减1)&(变量地址)┃ │ ────────────────────────────┃ │ *(指针所指内容)type(函数说明)sizeof(长度计算)┃ │ ────────────────────────────┃ │ *(乘)/(除)%(取模)┃ │ ────────────────────────────┃ │ +(加)-(减)┃ │ ────────────────────────────┃ │ <<(位左移)>>(位右移)┃ │ ────────────────────────────┃ │ <(小于)<=(小于等于)>(大于)>=(大于等于)┃ │ ────────────────────────────┃ │ ==(等于)!=(不等于)┃ │ ────────────────────────────┃ │ &(位与)┃ │ ────────────────────────────┃ │ ^(位异或)┃ │ ────────────────────────────┃ │ |(位或)┃ │ ────────────────────────────┃ │ &&(逻辑与)┃ │ ────────────────────────────┃ │ ||(逻辑或)┃ │ ────────────────────────────┃ │ ?:(?表达式)┃ │ ────────────────────────────┃ │ = +=-=(联合操作)┃ │ ────────────────────────────┃ │ ,(逗号运算符)┃ 最低 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

第四篇:c语言

学C语言有感

姓 名: 李文丽 学 号:034108048 班 级:083411 指导老师:张印

2009年12月

学C语言有感

第1页

学C语言有感

摘要:C语言既有高级语言的特点,又具有汇编语言的特点;既能用来编写不依赖计算机硬件的应用程序,又能用来编写各种系统程序;是一种受欢迎、应用广泛的程序设计语言C语言版本。首先按照学习C语言的顺序分别介绍了我在学习C语言过程中所遇到的问题,叙述了在C语言学习过程,学习C语言的重点,难点,以及易出错的地方,并且用具体的案例做解释。然后阐述了学习C语言的体会:C语言的语法部分是学好C语言的基础,学习c语言不能停留在学习它的语法规则,只有通过上机才能检验自己是否掌握c语言、自己编写的程序是否能够正确地解题。最后总结学习c语言,既是件有趣的事情,又是件艰苦的事情。静下心来学习,我们会有所收获,更会其乐无穷的。

关键词:运算符 表达式 优先级 语句 变量

一、C语言的学习中的问题

在这个学期里,我们工商管理专业的学生在专业老师张印的带领下进行了实用c语言简明教程的学习。经过这一个学期的学习,我们已经对c语言这门课程有了一定的了解。C语言是一门最基础的语言,也是一门广泛使用的语言。所以学习C语言义不容辞

首先,在学习的最初几节课,老是主要向我们讲述了C语言的特点,学习C语言的意义,以及学习C语言能给我们所带来的方便优越之处。

C语言是一种结构化语言。它层次清晰,简洁紧凑、灵活方便,便于按模块化方式组织程序,易于调试和维护。C语言的表现能力和处理能力极强,语法限制不太严格、程序设计自由度大。它不仅具有丰富的运算符和数据类型,便于实现各类复杂的数据结构。它还可以直接访问内存的物理地址,进行位(bit)一级的操作,适用范围大,可移植性好。总之,C语言既有高级语言的特点,又具有汇编语言的特点;既是一个成功的系统设计语言,有是一个使用的程序设计语言;既能用来编写不依赖计算机硬件的应用程序,又能用来编写各种系统程序;是一种受欢迎、应用广泛的程序设计语言C语言版本。

当然,C语言也有自身的不足,比如:C语言的语法限制不太严格,对变量的类型约束不严格,影响程序的安全性,对数族下标越界不作检查等。从应用的角度,C语言比其他高级语

学C语言有感

第2页

言较难掌握。

下面我给大家说一说我在学习C语言过程中所遇到的问题。

在第二章,我们学习的是数据描述与基本操作。在这一章,我们主要讲了数据类型,运算符与表达式,和不同类型数据间的混合运算。其中比较难以理解和掌握的是自加、自减运算符。

自加、自减运算符作用是使变量的值增1或减1;当符号在前,变量在后,++i/--i 变量的值先加1或先减1,然后再参与其它运算。当符号在后,变量在前,++i/--i 变量的值先参与其它运算,然后再加1或先减1。例如: # include int main(){ int i,j;i=3;j=++i;printf(“i=%d j=%dn”,i,j);return 0;} 运行结果:i=4 j=4 在进行自加、自减运算中我们应该注意一下几点:

1.自加运算符(++)和自减运算符(--)只能用于变量,而不能用于常量或表达式,如6++或(a+b)++都是不合法的。因为5是常量,常量的值是不能改变的。(a+b)++也不可能实现,假如a+b的值为5,那么自加后得到的6放在什么地方?

2.++和--的结合方向是“自右向左”。负号运算符和++运算符同优先级,而结合方向为“自右向左”,即它相当于-(i++),如果有printf(“%d”,-i++),则先取出i的值3,输出-i的值-3,然后i增值为4。注意-(i++)是先用i的原值3加上负号输出-3,再对i加1,不要认为加完1后再加负号,输出-4,这是不对的。

例如,x=a*b+c%d 无所谓;

例如,a=3;y=a*++a;不同的编译系统有两种处理方式,结果不同:

A)按从左到右的顺序处理为:先取a的值3,再计算++a,a的值 自增为4,子表达式++a的值也为4,所以相乘的结果为12;

学C语言有感

第3页

B)按从右到左的顺序处理为:先计算++a,a的值自增为4,子表达式++a的值也为4,再取a的值为4,所以相乘的结果为16。

在第三章我们讲的是顺序结构程序设计,其中所涉及的主要问题说优先级。

说到优先级什么叫优先级?比方说,我们在公交车终点站排座队时总会遇到70岁以上的老人不需要排队就能上车的情景,这就是优先级的涵义。C程序在运行时也象排队坐车一样,首先照顾那些优先级高的运算符,若是优先级相同,那么就象遇到两位(或两位以上)70岁以上的老人那样,让他们依次上车。

下面我们通过几个例子来说明:

(1)3*20/4%10 这个表达式中出现3种运算符,是同级运算符,运算顺序按从左至右结合,因此先计算3 * 20=60,然后被4除,结果为15,最后是%(求余数)运算,所以表达式的最终结果为15%10 = 5(2)a = 3;b = 5;c =++ a* b ;d =a + +* b;

例子中的“;”是C语言的语句分隔符,执行顺序为从左到右,第1条语句执行后a的值为3,第2条语句执行后b的值为5,第3条语句中有两个运算符前置+ +和*,按表中所列顺序,+ +先执行,*后执行,所以+ + a执行后,a的值为4,由于+ +为前置运算,所以a的值4参与运算,C的值为20,最后执行第4条语句,由于a + +为后置运算,所以a值为4参与运算,使得d的值仍为20,而a参与运算后其值加1,值为5。这个例子执行后,a的值为5,b的值为5,c的值为20,d的值也是20。(3)a = 3,b = 5,b+ = a,c = b* 5

例子中的“,”是逗号结合运算,上式称为逗号表达式,自左向右结合,最后一个表达式的结果值就是逗号表达式的结果,所以上面的逗号表达式结果为40,a的值为3,b的值为8,c的值为40。

但是C语言中的优先级的运算并不是千篇一律的,只能说是在大多数情况下,有些运算符的优先级有其自己的特点,因此这点大家要注意。例如条件表达式:条件?结果1:结果2,这种表达式很多朋友都知道,它的作用与IF…ELSE…条件判断语句很雷同,它运算时的优先级就不是按照C语言的规则来完成的。所以说对于优先级各位编程爱好者一定灵活掌握,不要死记硬背。

第三四章的选择结构程序设计和循环结构设计说我们这学期所学内容的重点。在这里,学者结构程序设计比较简单,我们就不多说了,主要谈一下循结构环程序设计。

学C语言有感

第4页

循环结构可以减少源程序重复书写的工作量,用来描述重复执行某段算法的问题,这是程序设计中最能发挥计算机特长的程序结构,C语言中提供四种循环,即goto循环、while循环、do –while循环和for循环。四种循环可以用来处理同一问题,一般情况下它们可以互相代替换,但一般不提昌用goto循环,所以下面我们重点讲解另外的三种循环。

用while和do—while循环时,循环变量的初始化的操作应在循环体之前,而for循环是在语句1中进行的;while 循环和for循环都是先判断表达式,后执行循环体,而do—while循环是先执行循环体后判断表达式,也就是说do—while的循环体最少被执行一次,而while 循环和for就不一定了。这三种循环都可以用break语句跳出循环,用continue语句结束本次循环,而goto语句与if构成的循环,不能用break和 continue语句进行控制。这三种结构并不是彼此孤立的,在循环中可能出现分支、顺序结构,分支中也可能出现循环、顺序结构而把循环、分支看成一个语句,它又是构成顺序结构的一个元素,因此这三种结构相互结合,就能实现各种算法,设计出解题程序,但若是很大的题目,这样编出的程序往往很长,重复结构多,并且可阅读性差,因此我们常将C程序设计成模块化结构。

二、C语言学习的重点、难点

针对我个人而言,在C语言学习过程,学习C语言的重点,难点,以及易出错的地方主要有以下几个方面: 如果对几个变量赋予同一个初值,应写成: int a=3,b=3,c=3;表示a、b、c的初值都是3。不能写成: int a=b=c=3;2 强制类型转换其一般形式为(类型名)(表达式)表达式应该用括号括起来。如(int)(x+y)表示将x+y的值转换成整形如果写成(int)x+y则表示将x转换成整形,然后与y相加。使用scanf函数注意的问题: ①“格式控制”后面应当是变量地址,而不应是变量名。如 scanf(“%d”,a)是不对的,应改为scanf(“%d”,&a);②scanf函数格式控制最后面不能有n否则将没有结果输出如scanf(“%dn”,&a);是不对的。③输入数据时不能规定精度,如scanf(“%7.2f”),&a);是不合法的 ④如果在%后有一个“*”附加说明符,表示跳过它指定的列数。

学C语言有感

第5页

三、学习c语言的体会

在经过了一个学期的学习之后,对于学习c语言心得体会也总结了一下:

1、既然是一门语言,他就汉语,英语一样,都有自己的语法规则,学习一门语言,就是要按照它的语法来编程。C语言的语法部分是学好C语言的基础,只有学好了这些语法,才会写程序,看程序。所以对一个初学者来说,加深对课堂讲授内容的理解,要扎实地熟悉每一个语法,并能根据这些语法来编程。

2、课堂上要讲授许多关于c语言的语法规则,听起来十分枯燥无味,也不容易记住死记硬背是不可取的。然而要使用c语言这个工具解决实际问题,又必须掌握它。通过多次上机练习,对于语法知识有了感性的认识,加深对它的理解,在理解的基础上就会自然而然地掌握c语言的语法规定。对于一些内容自己认为在课堂上听懂了,但上机实践中会发现原来理解的偏差,这是由于大部分学生是初次接触程序设计,缺乏程序设计的实践所致。

3、学习c语言不能停留在学习它的语法规则,而是利用学到的知识编写c语言程序,解决实际问题。即把c语言作为工具,描述解决实际问题的步骤,由计算机帮助我们解题。只有通过上机才能检验自己是否掌握c语言、自己编写的程序是否能够正确地解题。学习C语言是没有什么捷径的,打好基础,做好每章的练习才是关键。尤其是书本里的习题,不能因为简单就不去实践,学习C语言,乃至于学习所有的电脑知识都是一样的,实践练习永远处于最为重要的地位,须知电脑是要实际操作的,对于C语言,更是要是把这个程序自己编出来并且运行成功,知识点才记得最为深刻。

通过上机实验来验证自己编制的程序是否正确,恐怕是大多数同学在完成老师作业时的心态。但是在程序设计领域里这是一定要克服的传统的、错误的想法。因为在这种思想支配下,可能你会想办法去“掩盖”程序中的错误,而不是尽可能多地发现程序中存在的问题。自己编好程序上机调试运行时,可能有很多你想不到的情况发生,通过解决这些问题,可以逐步提高自己对c语言的理解和程序开发能力。学习c语言更为重要的是掌握编程的思想,如何用简捷的方法解决一个问题。同样做一个循环问题,可能有人要做300次循环,而有的人要做100次,这就是差距。平时,我们学习的时候要注意掌握每个概念,当然理论的学习是离不开实践的,尤其是c语言,需要你编写大量的程序,最初可以学着别人的程序打,慢慢就应该独立出来,把自己的想法用c语言描述出来,这是一件十分快乐的事情。建议初学者不要看高级编程,先勤写代码、多看代码、培

学C语言有感

第6页

养风格、熟悉语法、最关键的还是把握思想。当你能够信手拈来的时候,你的c语言才可以说学会了。一定要养成自己独立写完一个程序的能力,这样可以有一种成就感。不断培养这种成就感,循序渐进,进步是自然的事情。

四、总结

学习c语言,既是件有趣的事情,又是件艰苦的事情。说它有趣,是因为从中你能得到快乐,能使你的计算机整体水平上升一大步。说它艰苦,是因为学习它的过程比起学习其他计算机知识,要难得多

C语言只是一门计算机语言,说到底就是一种工具。它的用处就是可以让你用它编出能够运行的程序来,而这些程序可以实现某些人需要的功能。人通过学习c语言也可以更加深入的了解计算机,所以很多人都把c语言作为计算机入门的第一门语言来学习,因为他学习起来相对简单一些。至于实际的意义,无非是让你多学会一门技能,让你更加深入对计算机的了解,为学习其他计算机语言打下好的基础。

学习最好抱着一种踏踏实实的心态,老是想着有什么实际的好处并不会促进我们的学习,因为知识对人的影响是潜移默化的,静下心来学习吧,我相信我们会有收获的!而且如果你真的用心学习,会发现学起来越来越有意思,也会给你带来无穷的乐趣的!

学C语言有感

第7页

参考文献:

[1] 3 沈其益等编著,棉花病害——基础理论与防治,北京:科学出版社,1992.7 [2] 3 沈其益、张三等编著,棉花病害——基础理论与防治,北京:科学出版社,1992.7。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。参考文献(不少于10篇,中文参考文献不少于7篇,英文不少于3篇)

学C语言有感

第8页

学C语言有感

第9页

第五篇:如何学C语言

如何学C语言

(一)“项目驱动”式教学

目前最著名、最有影响、应用最广泛的windows、linux和UNIX三个操作系统都是用C语言编写的。0S是计算机系统(由软硬件两个子系统构成)的核心和灵魂,它是软件中最庞大最复杂的系统软件。既然如此庞大复杂的0S都可以用c语言编写,从狭义而言,还有什么系统软件和应用软件不能用c语言编写呢?由此可以肯定的说,c语言是一门十分优秀而又重要的语言。

c语言程序设计是过程性程序设计语言,它的发展贯穿了计算机发展的历程,它蕴含了程序设计的基本思想,囊括了程序设计的基本概念,所以它是理工科高等院校的一门基础课程。从市面上有关c语言的书籍和高等院校采用的教材来看,它们有一个共性,那就是:脱离了实际应用(全是小打小闹的小例子),纯粹的过程性程序设计,没有软件工程思想的体现,没有一定程序设计风格,仅仅是为了让大家明白什么是c语言而已。

高等院校开设c语言程序设计的目的是让学生对程序设计有个入门,有个直观的理解,同时为其他后续课程作铺垫。但是如果教学仅仅以此为目的,那么教学本身就效果而言是个大大的失败。

大家知道,在商业上讲究唯利是图,“利”是商业追求的目标,离开了“利”经商,则商无动力,其结果是必败无疑。在c语言程序设计教学当中,教师应该把“唯用是图”作为教学的首要目标。如果抛开了实际应用进行程序设计教学,就是纸上谈兵,就是“说明书”式的教学。印度的程序设计课程采用“事件驱动式”教学,我认为在中国的c语言程序设计教学中应该采用“项目驱动式”教学。“项目驱动式”教学就是以项目为目的,以c语言理论教学为过程,最终能用c语言设计项目,实现项目的要求。“项目驱动式”教学的关键在于培养学生“如何做什么”和“可以干什么”。一个项目就是一个工程,在“项目驱动式”教学中,首先应该让学生简单了解什么是软件工程思想,其次在c语言理论教学过程中,让学生懂得面向对象的程序设计的风格,最后引导他们来设计项目。

(二)“项目驱动”式教学应注意的问题

1.c语言程序设计教学要帮助学生树立面向工程的观点

在计算机行业中,软件是通过人们的智力活动、把知识与技术转化成信息的一种产品。软件的设计已经用工程的观念来进行管理。软件设计工作被当作一项系统工程来对待。软件的的生存周期一般可分为以下阶段:问题定义、可行性研究、需求分析、概要设计、详细设计、编码、测试、运行与维护。我们不难看出软件工程的复杂程度是很大的。理工科高等院校把c语言作为一门基础课程,也是为了给社会培养信息技术人才。众所周知,养成一个好的习惯是非常重要的,所以c语言程序设计作为大多数工科院校学生接触的第一门程序设计语言(有的院校讲pascal),就应该让学生树立正确的观点。那么当前的程序设计教学也必须以切合将来软件工程开发的实际需要为第一目标,使学生在学习程序设计的初级阶段就树立正确的软件工程观点。这样做不仅可以为学生将来从事计算机应用设计打下良好的基础,而且有利于培养学生分析问题的完备性,以及统筹全局,协调关系的基本素质。

2.理论教学应从单一的“结构化程序设计”向“结构化与面向对象并举”转变

“结构化程序设计”方法是程序设计的基础,必须让学生掌握得坚实可靠。结构化程序设计的过程是培养学生思维能力的过程,在教学中经常发现有些学生的思维混乱。这些都是缺乏思维训练的结果。结构化程序设计的训练不仅可以让学生养成良好的程序设计习惯,而且可以有效地培养学生思维的条理性和逻辑性。所以在授课过程中要注意讲解结构化程序设计的思想时应突出两点:(1)程序的质量首先取决于它的结构。(2)程序设计的基本方法是自顶向下地逐步求精和模块化。

在c程序教学过程中,越到后面的章节,学生越会产生设计程序逐渐变难的感觉,这是不符

合逻辑的一种怪现象。按照常理,C语言学的越多,说明你的程序设计知识越多,设计起程序来应该更加得心应手,那么出现这种现象的原因何在呢?当然该问题的出现的原因是多方面的,但是其中最重要的一点就是长期以来程序设计的观念不是以如何处理好对象为出发点,而是以如何使用好语言为基本点。受这种思想的影响,我们的程序设计教学大多数不是以如何解决好问题为重点,而是以讲解语法规则和语句格式为重点,是“说明书”式的教学。这样做造成的结果就是见到一个程序后学生首先想到是该用哪条语句,而不是思考怎样合理的解析。要切实解决这个问题,首先应该改变程序设计的观念。“面向对象程序设计”思想是目前最为流行、极为实用的一种程序设计方法,但是让学生直接接触“面向对象程序设计”,肯定不能对程序设计打下牢固的基础。“结构化与面向对象并举”是现代计算机程序设计的发展趋势,应该认真探索研究,让学生有一个较为轻松的学习过程。程序设计的实质就是编写处理对象的过程,所以将c与c++有机的融为一体的教材应该是首选教材,在教学过程中,我们应该从社会发展的角度进行探索研究,将目前最为流行又极为实用“面向对象程序设计”思想融合到c语言教学中。

3.c语言教学应培养学生良好的程序设计风格

具有良好的设计风格应该是程序员所具备的基本素质,在实际的项目中程序员往往都有自己的一些编程风格。目前95%以上的程序设计书籍不注重程序设计风格问题,这导致了很多学生没有良好的程序设计风格,在他们刚刚毕业踏入社会时,如果周围的同事没有良好的编程风格,那么很难通过环境来使自己提高这方面的素质,即使有提高也不容易比较全面的提高。因此在学生接触的第一门程序设计语言教学中,就应该培养学生良好的程序设计风格,使他们一进工作环境就具备这个素质。

Pascal设计者N.Writh教授十分重视程序设计风格的养成,他坚信“教给学生们以表达他们思维的语言会深深地影响他们思维和创造发明的习惯,而正是这些语言本身的混乱直接影响着学生们的程序设计的风格”,他这里所指的“这些运用”是当时那些主要用于程序设计教学的计算机语言。对学生来讲,一开始就强调程序设计风格很有必要,良好的程序设计风格不仅有助于提高程序的可靠性、可理解性、可测试性、可维护性和可重用性,而且也能够促进技术的交流,改善软件的质量。所以培养良好的程序设计风格对于初学者来说非常重要。程序设计风格,实际上是指的是编码风格。在教学过程中应从源程序文档化,数据说明的原则,输入/输出方法这三个方面培养学生的编码风格,进而从编码原则探讨提高程序的可读性、改善程序质量的方法。

(1)源程序文档化。编码的目的是产生程序,但是为了提高程序的可维护性。源代码是需要实现文档化的。源程序文档化包括选择标识符(变量和标号)的名字、安排注释以及标准的书写格式等。

①选择标识符的命名规则。标识符包括模块名、变量名、常量名、标号名、子程序名等。这些名字应能反映它所代表的实际东西,应有一定实际意义,使其能顾名思义。另外在模块名、变量名、常量名、标号名、子程序名中使用下划线是一种风格。使用这一技术的一种广为人知的命名规则就是匈牙利命名法(变量类型由一个或两个字符表示,并且这些字符将作为变量名的前缀)。当然使用匈牙利命名法与否都没有错误,重要的是要保持一致性——在整个程序中使用相同的命名规则。这就是说,如果你在一个小组环境中编程,你和其他小组成员应该制定一种命名规则。并自始至终使用这种规则。如果有人使用了别的命名规则,那么集成的程序读起来将是很费劲的。此外,你还要与程序中用到的第三方库(如果有的话)所使用的风格保持一致。如果可能的话,你应该尽量使用与第三方库相同的命名规则,这将加强你的程序的可读性和一致性。

②注释。程序中的注释是程序设计者与程序阅读者之间通信的重要手段。注释能够帮助读者理解程序,并为后续测试维护提供明确的指导信息。因此,注释是十分重要的,大多数程序

设计语言提供了使用自然语言来写注释的环境,为程序阅读者带来很大的方便。注释分为功能性注释和序言性注释。

a.功能性注释。功能性注释在源程序中,用以描述其后的语句或程序段是在做什么工作,也就是解释下面要“做什么”,而不是解释下面怎么做。对于书写功能性注释,要注意以下几点:第一描述一段程序,而不是每一个语句。第二利用缩进和空行,使程序与注释容易区别。第三注释要准确无误。

b.序言性注释。序言性注释通常位于每个程序模块的开头部分,它给出程序的整体说明,对于理解程序具有引导作用。有些软件开发部门对序言性注释做了明确而严格的规定,要求程序编制者逐项列出。有关内容包括:程序标题;有关该模块功能和目的的说明;主要算法;接口说明:包括调用形式,参数描述,子程序清单;有关数据描述;模块位置(在哪一个源文件中,或隶属于哪一个软件包);开发简历:模块设计者、复审考、复审日期。③用标准的书写格式。源程序清单的书写建议采用以下几点:

a.每行只写一条语句;

b.用分层缩进的写法显示嵌套结构层次,这样可使程序的逻辑结构更加清晰,层次更加分明。c.书写表达式时适当使用空格或圆括号作隔离符。

d.在注释段周围加上边框;

e.注释段与程序段、以及不同的程序段之间插入字行;

(2)数据说明采用的原则。在编写程序时,要注意数据说明的风格。

数据说明的次序如果规范,将有利于测试,排错和维护。首先说明的先后次序要固定,例如,按常量说明、简单变量类型说明、数组说明用数据块说明、所有的文件说明的顺序说明。当然在类型说明中还可进一步要求,例如按如下顺序排列:整型量说明、实型量说明、字符量说明、逻辑说明。

其次当用一个语句说明多个变量名时,应当对这些变量按字母的顺序排列。

最后对于复杂数据结构,应利用注释说明实现这个数据结构的特点。

(3)输入/输出方法。输入/输出的方式和格式应当尽量避免因设计不当给用户带来的麻烦。这就要求,源程序的输入/输出风格必须满足能否为用户接受这一原则。所以在设计程序时,应考虑以下原则:输入数据时,要使输入的步骤和操作尽可能简单,应允许使用自由格式输入;应允许缺省值;对输入的数据要进行检验,以保证每个数据的有效性。

(三)结束语

在教学过程中,我们让学生设计一个程序模拟体育彩票的销售与对奖的过程,取得了良好的效果。他不仅启发和诱导了学生独立思考、积极思维的主动性,而且充分调动了学生学习的自觉性和积极性,使学生融会贯通地掌握了所学知识,提高了分析问题和解决实际问题的能力。

搞好c程序设计的教学工作涉及的因素很多,如果以项目来驱动教学,首先让学生树立面向工程的思想,其次把教学从单一的“结构化程序设计”向“结构化与面向对象并举”转变,最后特别要培养学生养成良好的编码风格,从而使他们学会能够“干什么”,那么我们认为教学目的就达到了。

下载怕忘记,放一下,c语言基础教程word格式文档
下载怕忘记,放一下,c语言基础教程.doc
将本文档下载到自己电脑,方便修改和收藏,请勿使用迅雷等下载。
点此处下载文档

文档为doc格式


声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:645879355@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。

相关范文推荐

    C语言

    1. 算法(Algorithm)是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决 问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。 2. 算法具有......

    C语言

    整形 字符型 单精度型基本类型双精度型枚举类型数组类型构造类型结构体类型 数据类型 共同体类型指针类型(C语言的精华)空类型整形:int 字符型 char 单精度实型 float双精度实......

    C语言

    Home Exam List Notification Problem Ranklist Message User Information HJP-2013学期作业 程序设计题1. (10分) 一秒钟以后题目描述 输入某时刻的时、分......

    C语言

    第十章 结构体与共用体 10.1 选择题 【题10. 1】已知学生记录描述为 struct student {int no; char name[20]; char set; struct {int year; int month; int day; }bi......

    C语言

    Description 编写程序,输入三个整数变量hour(小时)、minute(分钟)、second(秒)代表一个时间, 输出该时间20秒以后的时间。 输入格式 一行三个整数,分别代表小时、分钟、秒,中间使用冒......

    c语言

    1.编写一程序P111.C实现以下功能 x(x只考虑整数int且必须定义为int、但F(x)完全可能超过int的表示范围)通过键盘输入(输入前给出提示Please input x:),然后计算并在屏幕上输......

    C语言

    第1章 C语言程序设计初步 本章是C语言程序设计的入门部分, 从整体上介绍C语言的起源和发展,讲述C语言的特点、结构和基础语法要点。 1.1 C语言概述 1.1.1 C语言的发展 C语言是界上......

    c语言

    个 人 简 历 个人信息 姓 电 Email 毕业院校 学 历 名 话 许松 *** 395458593@qq.com 中南财经政法大学 本 科 性 年 专 籍 别 龄 业 贯 男 22 计算机信息管理 四......