| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 7666 人关注过本帖, 4 人收藏
标题:[推荐]从Turbo C学习C语言基础
只看楼主 加入收藏
unicorn
Rank: 4
等 级:贵宾
威 望:14
帖 子:1066
专家分:0
注 册:2005-10-25
收藏(4)
 问题点数:0 回复次数:27 
[推荐]从Turbo C学习C语言基础

ps:文章转自网络,力求分享大家一起学习C语言,如有侵权行为请与偶联系 unicorn.h@hotmail.com,谢谢

--------------------------------------------------------------------------------------------------------------------------------------------------

第一章 Turbo C语言概述



1.1 C 语言的产生与发展

C 语言是1972年由美国的Dennis Ritchie设计发明的, 并首次在UNIX操作系统
的 DEC PDP-11 计算机上使用。 它由早期的编程语言 BCPL ( Basic Combind
Programming Language) 发展演变而来。 在1970年, AT&T 贝尔实验室的 Ken
Thompson根据BCPL语言设计出较先进的并取名为 B的语言,最后导了C 语言的问世。
随着微型计算机的曰益普及,出现了许多C 语言版本。由于没有统一的标准,使
得这些C 语言之间出现了一些不一致的地方。为了改变这种情况, 美国国家标准研
究所(ANSI)为C 语言制定了一套ANSI标准,成为现行的C语言标准。


1.2 C 语言的特点

C 语言发展如此迅速,而且成为最受欢迎的语言之一,主要因为它具有强大的功
能。许多著名的系统软件,如DBASE Ⅲ PLUS、DBASE Ⅳ 都是由C 语言编写的。用C
语言加上一些汇编语言子程序,就更能显示C 语言的优势了,象PC- DOS 、WORDSTAR
等就是用这种方法编写的。归纳起来C 语言具有下列特点:
1. C是中级语言
它把高级语言的基本结构和语句与低级语言的实用性结合起来。C 语言可以象
汇编语言一样对位、字节和地址进行操作,而这三者是计算机最基本的工作单元。
2. C是结构式语言
结构式语言的显著特点是代码及数据的分隔化, 即程序的各个部分除了必要的
信息交流外彼此独立。这种结构化方式可使程序层次清晰, 便于使用、维护以及调
试。C 语言是以函数形式提供给用户的,这些函数可方便的调用,并具有多种循环、
条件语句控制程序流向,从而使程序完全结构化。
3. C语言功能齐全
C 语言具有各种各样的数据类型,并引入了指针概念,可使程序效率更高。另外
C 语言也具有强大的图形功能, 支持多种显示器和驱动器。而且计算功能、逻辑判
断功能也比较强大,可以实现决策目的。
4. C语言适用范围大
C 语言还有一个突出的优点就是适合于多种操作系统, 如DOS、UNIX,也适用于
多种机型。


1.3 Turbo C 概述

1.3.1 Turbo C 的产生与发展

Turbo C 是美国Borland 公司的产品,Borland公司是一家专门从事软件开发、
研制的大公司。 该公司相继推出了一套 Turbo系列软件, 如Turbo BASIC, Turbo
Pascal, Turbo Prolog,这些软件很受用户欢迎。该公司在1987年首次推出Turbo C
1.0 产品, 其中使用了全然一新的集成开发环境,即使用了一系列下拉式菜单,将文
本编辑、 程序编译、连接以及程序运行一体化, 大大方便了程序的开发。1988年,
Borland 公司又推出Turbo C1.5版本, 增加了图形库和文本窗口函数库等,而Turbo
C 2.0 则是该公司1989年出版的。Turbo C2.0在原来集成开发环境的基础上增加了
查错功能,并可以在Tiny模式下直接生成.COM(数据、代码、堆栈处在同一64K 内存
中)文件。还可对数学协处理器(支持8087/80287/80387等)进行仿真。
Borland 公司后来又推出了面向对象的程序软件包Turbo C+ + , 它继承发展
Turbo C 2.0 的集成开发环境,并包含了面向对象的基本思想和设计方法。
1991年为了适用Microsoft 公司的Windows 3.0 版本,Borland 公司又将Turbo
C++ 作了更新,即Turbo C 的新一代产品Borlandc C++也已经问世了。


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
集成开发环境。

搜索更多相关主题的帖子: C语言 Turbo 基础 学习 推荐 
2006-10-07 16:21
unicorn
Rank: 4
等 级:贵宾
威 望:14
帖 子:1066
专家分:0
注 册:2005-10-25
收藏
得分: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
从编辑窗口转到主菜单编辑命令简介ageUp 向前翻页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(删除信息)
把错误信息从信息窗口中清除掉。

六、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 Turbo C 所在的目录。Pick file name 定义加
载的pick文件名,如不定义则从current
pick file中取。

.Arguments(命令行参数)允许用户使用命令行参数。

. Save options(存储配置)保存所有选择的编译、连接、调试和项目到配置文
件中,缺省的配置文件为TCCONFIG.TC。

. Retrive options装入一个配置文件到TC中,TC将使用该文件的选择项。

七、Debug(调试) 菜单按Alt+D可选择Debug菜单,该菜单主要用于查错,它包括
以下内容:Evaluate
Expression 要计算结果的表达式。
Result 显示表达式的计算结果。
New value 赋给新值。 Call stack 该项不可接触。而在Turbo C debuger 时
用于检
查堆栈情况。Find function 在运行Turbo C debugger时用于显示规定的函数。
Refresh display 如果编辑窗口偶然被用户窗口重写了可用此恢复
编辑窗口的内容。

八、Break/watch(断点及监视表达式)按Alt+B可进入Break/watch菜单,该菜单
有以下内容:Add watch 向监视窗口插入一监视表达式。Delete watch 从监视窗口
中删除当前的监视表达式。 Edit watch 在监视窗口中编辑一个监视表达式。
Remove all watches 从监视窗口中删除所有的监视表达式。Toggle breakpoint对
光标所在的行设置或清除断点。 Clear all breakpoints 清除所有断点。 View
next breakpoint 将光标移动到下一个断点处。


1.5.2 Turbo C 2.0的配置文件

所谓配置文件是包含Turbo C 2.0有关信息的文件,其中存有编译、连接的选择
和路径等信息。可以用下述方法建立Turbo C 2.0的配置: 1. 建立用户自命名的配
置文件可以从Options菜单中选择Options/Save options命令,将当前集成开发环境
的所有配置存入一个由用户命名的配置文件中。下次启动TC时只要在DOS下键入:tc
/c<用户命名的配置文件名>就会按这个配置文件中的内容作为Turbo C 2.0的选择。
2. 若设置Options/Environment/Config auto save 为on,则退出集成开发环境时,
当前的设置会自动存放到Turbo C 2.0配置文件TCCONFIG.TC中。Turbo C 在启动时
会自动寻找这个配置文件。3. 用TCINST设置Turbo C的有关配置,并将结果存入TC.
EXE中。Turbo C 在启动时,若没有找到配置文件,则取TC.EXE中的缺省值。


unicorn-h.spaces. ◇◆ sava-scratch.spaces.  noh enol ! pue pu!w hw u! shemle aq ll!m noh 
2006-10-07 16:22
unicorn
Rank: 4
等 级:贵宾
威 望:14
帖 子:1066
专家分:0
注 册:2005-10-25
收藏
得分:0 

第二章 数据类型、变量和运算符


本章首先介绍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提供的
任何库函数调用语句、控制流程语句或其它用子函数调用语句等。


2. 数据类型

在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即"\0",但终止
符是编编译程序自动加上的,这一点应特别注意。

二、字符常数表示
能用符号表示的字符可直接用单引号括起来表示, 如'a','9','Z',也可用该字
符的ASCII码值表示,例如十进制数85表示大写字母'U',十六进制数0x5d表示']',八
进制数0102表示大写字母'B'。
一些不能用符号表示的控制符,只能用ASCII码值来表示,如十进制数10 表示换
行,下六进制数0x0d表示回车,八进制数033表示Esc。Turbo C2.0中也有另外一种表
示表示方法,如'\033'表示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被定义为无值型指针*/


3 关键字和标识符

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

4. 变量

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为函数的形式参数, 不需要再进行说明就可在该函数内
直使用。


unicorn-h.spaces. ◇◆ sava-scratch.spaces.  noh enol ! pue pu!w hw u! shemle aq ll!m noh 
2006-10-07 16:24
unicorn
Rank: 4
等 级:贵宾
威 望:14
帖 子:1066
专家分:0
注 册:2005-10-25
收藏
得分:0 

三、全程变量
全程变量是指在所有函数之外说明的变量, 它在整个程序内部者是"可见的",
可以被任何一个函数使用, 并且在整个程序的运行中都保留其值。全程变量只要满
足在使用它以前和函数以外这两个条件, 可在程序的任何位置进行说明, 习惯上通
常在程序的主函数前说明。
例如:
#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]则
应存放字符串终止符'\0'。
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\0"的字符串, 然后把这个字符串的第一个字母"G"的地址赋给str, 其中
字符串结尾符"\0"是编译程序自动加上的。
对于指针变量的使用要特别注意。上例中两个指针在说明前没有初始化, 因此
这两指针为随机地址, 在小存储模式下使用将会有破坏机器的危险。正确的使用办
法如下:
例如:
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!\0" 的字符串。
其中\0表示字符串终止, 终止符是编译时自动加上的, 然后一个字符一个字符地复
制到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则是利用动态分想函数为它分配
存储空间或赋给它一个已分配的空间地址。


unicorn-h.spaces. ◇◆ sava-scratch.spaces.  noh enol ! pue pu!w hw u! shemle aq ll!m noh 
2006-10-07 16:26
unicorn
Rank: 4
等 级:贵宾
威 望:14
帖 子:1066
专家分:0
注 册:2005-10-25
收藏
得分:0 

5. 运算符

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

5.1 算术运算符
Turbo C的算术运算符如下:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
操作符 作用
────────────────────────────
+ 加, 一目取正
- 减, 一目取负
* 乘
/ 除
% 取模
-- 减1
++ 加1
━━━━━━━━━━━━━━━━━━━━━━━━━━━━

一、一目和二目操作
一目操作是指对一个操作数进行操作。例如: -a是对a进行一目负操作。
二目操作(或多目操作)是指两个操作数(或多个操作数)进行操作。
在Turbo C中加、减、乘、除、取模的运算与其它高级语言相同。需要注意
的是除法和取模运算。
例如:
15/2 是15除以2商的整数部分7
15%2 是15除以2的余数部分1
对于取模运算符"%", 不能用于浮点数。
另外, 由于Turbo C中字符型数会自动地转换成整型数, 因此字符型数也可
以参加二目运算。
例如:
main()
{
char m, n; /*定义字符型变量*/
m='c'; /*给m赋小写字母'c'*/
n=m+'A'-'a'; /*将c中的小写字母变成大写字母'B'后赋给n*/
...
}
上例中m='c'即m=98, 由于字母A和a的ASCII码值分别为65和97。这样可以将
小写字母变成大写字母, 反之, 如果要将大写字母变成小写字母, 则用c+ 'a'
-'A'进行计算。

二、增量运算
在Turbo C中有两个很有用的运算符, 在其它高级语言中通常没有。这两个
运算符就是增1和减1运算符"++"和"--", 运算符"++"是操作数加1, 而"--" 则是
操作数减1。
例如:
x=x+1 可写成x++, 或++x
x=x-1 可写成x--, 或--x
x++(x--)与++x(--x)在上例中没有什么区别, 但x=m++和x=++m却有很大差别。
x=m++ 表示将m的值赋给x后, m加1。
x=++m 表示m先加1后, 再将新值赋给x。

三、赋值语句中的数据类型转换
类型转换是指不同类型的变量混用时的类型改变。
在赋值语句中, 类型转换规则是:
等号右边的值转换为等号左边变量所属的类型。
例如:
main()
{
int i, j; /*定义整型变量*/
float f, g=2.58; /*定义浮点型变量*/
f=i*j; /*i与j的乘积是整型数, 被转换成为浮点数赋给f*/
i=g; /*g中的浮点型数转换成为整型数赋给i*/
...
}
由于Turbo C按上述数据类型转换规则, 因此在作除法运算时应特别注意。
例如:
main()
{
float f;
int i=15;
f=i/2;
}
上面程序经运行后, f=7并不等于准确值7.5。正确的程序应该是:
main()
{
float f;
int i=15;
f=i/2.0;
}
也可直接将i定义为浮点数。

5.2 关系运算符和逻辑运算符
一、逻辑运算符
逻辑运算符是指用形式逻辑原则来建立数值间关系的符号。
Turbo C的逻辑运算符如下:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
操作符 作用
─────────────────────────────
&& 逻辑与
|| 逻辑或
! 逻辑非
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

二、关系运算符
关系运算符是比较两个操作数大小的符号。
Turbo C的关系运算符如下:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
操作符 作用
─────────────────────────────
> 大于
>= 大于等于
< 小于
<= 小于等于
== 等于
!= 不等于
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
关系运算符和逻辑运算符的关键是真(true)和假(false)的概念。Turbo C中
true可以是不为0的任何值, 而false则为0。 使用关系运算符和逻辑运算符表达
式时, 若表达式为真(即true)则返回1, 否则, 表达式为假(即false), 则返回0。
例如:
100>99 返回1
10>(2+10) 返回0
!1&&0 返加0
对上例中表达式!1&&0, 先求!1和先求1&&0将会等于出不同的结果, 那么何
者优先呢? 这在Turbo C中是有规定的。 有关运算符的优先级本节后面将会讲到。

5.3 按位运算符
Turbo C和其它高级语言不同的是它完全支持按位运算符。这与汇编语言的
位操作有些相似。
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(长度计算) ┃ │
────────────────────────────┃ │
*(乘) /(除) %(取模) ┃ │
────────────────────────────┃ │
+(加) -(减) ┃ │
────────────────────────────┃ │
<<(位左移) >>(位右移) ┃ │
────────────────────────────┃ │
<(小于) <=(小于等于) >(大于) >=(大于等于) ┃ │
────────────────────────────┃ │
==(等于) !=(不等于) ┃ │
────────────────────────────┃ │
&(位与) ┃ │
────────────────────────────┃ │
^(位异或) ┃ │
────────────────────────────┃ │
|(位或) ┃ │
────────────────────────────┃ │
&&(逻辑与) ┃ │
────────────────────────────┃ │
||(逻辑或) ┃ │
────────────────────────────┃ │
?:(?表达式) ┃ │
────────────────────────────┃ │
= += -=(联合操作) ┃ │
────────────────────────────┃ │
,(逗号运算符) ┃ 最低
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


unicorn-h.spaces. ◇◆ sava-scratch.spaces.  noh enol ! pue pu!w hw u! shemle aq ll!m noh 
2006-10-07 16:26
unicorn
Rank: 4
等 级:贵宾
威 望:14
帖 子:1066
专家分:0
注 册:2005-10-25
收藏
得分:0 

第三章 输入输出函数及控制流程语句

本章主要介绍Turbo C2.0标准输入输出函数和文件的输入输出函数。通过本
节的学习可以使读者掌握Turbo C2.0的屏幕输出、键盘输入输出以及磁盘文件的
读写函数, 并能开始进行一些简单的程序的编写。
控制流程语句主要包括: 条件语句、循环语句和开关语句。


1.1 标准输入输出函数

1.1.1 格式化输入输出函数
Turbo C2.0 标准库提供了两个控制台格式化输入、 输出函数printf( ) 和
scanf(), 这两个函数可以在标准输入输出设备上以各种不同的格式读写数据。
printf()函数用来向标准输出设备(屏幕)写数据; scanf() 函数用来从标准输入
设备(键盘)上读数据。下面详细介绍这两个函数的用法。
一、printf()函数
printf()函数是格式化输出函数, 一般用于向标准输出设备按规定格式输出
信息。在编写程序时经常会用到此函数。printf()函数的调用格式为:
printf("<格式化字符串>", <参量表>);
其中格式化字符串包括两部分内容: 一部分是正常字符, 这些字符将按原
样输出; 另一部分是格式化规定字符, 以"%"开始, 后跟一个或几个规定字符,
用来确定输出内容格式。
参量表是需要输出的一系列参数, 其个数必须与格式化字符串所说明的输出
参数个数一样多, 各参数之间用","分开, 且顺序一一对应, 否则将会出现意想
不到的错误。
1. 格式化规定符
Turbo C2.0提供的格式化规定符如下:
━━━━━━━━━━━━━━━━━━━━━━━━━━
符号 作用
──────────────────────────
%d 十进制有符号整数
%u 十进制无符号整数
%f 浮点数
%s 字符串
%c 单个字符
%p 指针的值
%e 指数形式的浮点数
%x, %X 无符号以十六进制表示的整数
%0 无符号以八进制表示的整数
%g 自动选择合适的表示法
━━━━━━━━━━━━━━━━━━━━━━━━━━
说明:
(1). 可以在"%"和字母之间插进数字表示最大场宽。
例如: %3d 表示输出3位整型数, 不够3位右对齐。
%9.2f 表示输出场宽为9的浮点数, 其中小数位为2, 整数位为6,
小数点占一位, 不够9位右对齐。
%8s 表示输出8个字符的字符串, 不够8个字符右对齐。
如果字符串的长度、或整型数位数超过说明的场宽, 将按其实际长度输出。
但对浮点数, 若整数部分位数超过了说明的整数位宽度, 将按实际整数位输出;
若小数部分位数超过了说明的小数位宽度, 则按说明的宽度以四舍五入输出。
另外, 若想在输出值前加一些0, 就应在场宽项前加个0。
例如: %04d 表示在输出一个小于4位的数值时, 将在前面补0使其总宽度
为4位。
如果用浮点数表示字符或整型量的输出格式, 小数点后的数字代表最大宽度,
小数点前的数字代表最小宽度。
例如: %6.9s 表示显示一个长度不小于6且不大于9的字符串。若大于9, 则
第9个字符以后的内容将被删除。
(2). 可以在"%"和字母之间加小写字母l, 表示输出的是长型数。
例如: %ld 表示输出long整数
%lf 表示输出double浮点数
(3). 可以控制输出左对齐或右对齐, 即在"%"和字母之间加入一个"-" 号可
说明输出为左对齐, 否则为右对齐。
例如: %-7d 表示输出7位整数左对齐
%-10s 表示输出10个字符左对齐
2. 一些特殊规定字符
━━━━━━━━━━━━━━━━━━━━━━━━━━
字符 作用
──────────────────────────
\n 换行
\f 清屏并换页
\r 回车
\t Tab符
\xhh 表示一个ASCII码用16进表示,
其中hh是1到2个16进制数
━━━━━━━━━━━━━━━━━━━━━━━━━━
由本节所学的printf()函数, 并结合上一节学习的数据类型, 编制下面的程
序, 以加深对Turbo C2.0数据类型的了解。
例1
#include
#include
int main()
{
char c, s[20], *p;
int a=1234, *i;
float f=3.141592653589;
double x=0.12345678987654321;
p="How do you do";
strcpy(s, "Hello, Comrade");
*i=12;
c='\x41';
printf("a=%d\n", a); /*结果输出十进制整数a=1234*/
printf("a=%6d\n", a); /*结果输出6位十进制数a= 1234*/
printf("a=%06d\n", a); /*结果输出6位十进制数a=001234*/
printf("a=%2d\n", a); /*a超过2位, 按实际值输出a=1234*/
printf("*i=%4d\n", *i); /*输出4位十进制整数*i= 12*/
printf("*i=%-4d\n", *i); /*输出左对齐4位十进制整数*i=12*/
printf("i=%p\n", i); /*输出地址i=06E4*/
printf("f=%f\n", f); /*输出浮点数f=3.141593*/
printf("f=6.4f\n", f); /*输出6位其中小数点后4位的浮点数
f=3.1416*/
printf("x=%lf\n", x); /*输出长浮点数x=0.123457*/
printf("x=%18.16lf\n", x);/*输出18位其中小数点后16位的长浮点
数x=0.1234567898765432*/
printf("c=%c\n", c); /*输出字符c=A*/
printf("c=%x\n", c); /*输出字符的ASCII码值c=41*/
printf("s[]=%s\n", s); /*输出数组字符串s[]=Hello, Comrade*/
printf("s[]=%6.9s\n", s);/*输出最多9个字符的字符串s[]=Hello,
Co*/
printf("s=%p\n", s); /*输出数组字符串首字符地址s=FFBE*/
printf("*p=%s\n", p); /* 输出指针字符串p=How do you do*/
printf("p=%p\n", p); /*输出指针的值p=0194*/
getch();
retunr 0;
}
上面结果中的地址值在不同计算机上可能不同。
例1.中第一条语句#include的含义是调用另一个文件stdio.h, 这
是一个头文件, 其中包括全部标准输入输出库函数的数据类型定义和函数说明。
Turbo C2.0对每个库函数便用的变量及函数类型都已作了定义与说明, 放在相应
头文件"*.h"中, 用户用到这些函数时必须要用#include<*.h>或#include"*. h"
语句调用相应的头文件, 以供连接。若没有用此语句说明, 则连接时将会出现错
误。
二、scanf()函数
scanf()函数是格式化输入函数, 它从标准输入设备(键盘) 读取输入的信息。
其调用格式为:
scanf("<格式化字符串>", <地址表>);
格式化字符串包括以下三类不同的字符;
1. 格式化说明符: 格式化说明符与printf()函数中的格式说明符基本相同。
2. 空白字符: 空白字符会使scanf()函数在读操作中略去输入中的一个或多
个空白字符。
3. 非空白字符: 一个非空白字符会使scanf()函数在读入时剔除掉与这个非
空白字符相同的字符。
地址表是需要读入的所有变量的地址, 而不是变量本身。这与printf()函数
完全不同, 要特别注意。各个变量的地址之间同","分开。
例2:
main()
{
int i, j;
printf("i, j=?\n");
scanf("%d, %d", &i, &j);
}

上例中的scanf()函数先读一个整型数, 然后把接着输入的逗号剔除掉, 最
后读入另一个整型数。如果","这一特定字符没有找到, scanf()函数就终止。若
参数之间的分隔符为空格, 则参数之间必须输入一个或多个空格。
说明:
(1). 对于字符串数组或字符串指针变量, 由于数组名和指针变量名本身就
是地址, 因此使用scanf()函数时, 不需要在它们前面加上"&"操作符。
例3
mian()
{
char *p, str[20];
scanf("%s", p); /*从健盘输入字符串*/
scanf("%s", str);
printf("%s\n", p); /*向屏幕输出字符串*/
printf("%s\n", str);
}

(2). 可以在格式化字符串中的"%"各格式化规定符之间加入一个整数, 表示
任何读操作中的最大位数。
如例3中若规定只能输入10字符给字符串指针p, 则第一条scanf() 函数语句
变为
scanf("%10s", p);
程序运行时一旦输入字符个数大于10, p就不再继续读入, 而后面的一个读
入函数即scanf("%s", str)就会从第11个字符开始读入。
实际使用scanf()函数时存在一个问题, 下面举例进行说明:
当使用多个scanf()函数连续给多个字符变量输入时, 例如:
main()
{
char c1, c2;
scanf("%c", &c1);
scanf("%c", &c2);
printf("c1 is %c, c2 is %c", c2\1, c2);
}

运行该程序, 输入一个字符A后回车 (要完成输入必须回车), 在执行scanf
("%c", &c1)时, 给变量c1赋值"A", 但回车符仍然留在缓冲区内, 执行输入语句
scanf("%c", &c2)时, 变量c2输出的是一空行, 如果输入AB后回车, 那么输出结
果为: c1 is A, c2 is B。
要解决以上问题, 可以在输入函数前加入清除函数fflush()( 这个函数的使
用方法将在本节最后讲述)。修改以上程序变成:
#include
main()
{
char c1, c2;
scanf("%c", &c1);
fflush(stdin);
scanf("%c", &c2);
printf("c1 is %c, c2 is %c", c1, c2);
}

1.1.2 非格式化输入输出函数
非格式化输入输出函数可以由上面讲述的标准格式化输入输出函数代替, 但
这些函数编译后代码少, 相对占用内存也小, 从而提高了速度, 同时使用也比较
方便。下面分别进行介绍。
一、puts()和gets()函数
1. puts()函数
puts()函数用来向标准输出设备(屏幕)写字符串并换行, 其调用格式为:
puts(s);
其中s为字符串变量(字符串数组名或字符串指针)。
puts()函数的作用与语printf("%s\n", s)相同。
例4:
main()
{
char s[20], *f; /*定义字符串数组和指针变量*/
strcpy(s, "Hello! Turbo C2.0"); /*字符串数组变量赋值*/
f="Thank you"; /*字符串指针变量赋值*/
puts(s);
puts(f);
}

说明:
(1). puts()函数只能输出字符串, 不能输出数值或进行格式变换。
(2). 可以将字符串直接写入puts()函数中。如:
puts("Hello, Turbo C2.0");

2. gets()函数
gets()函数用来从标准输入设备(键盘)读取字符串直到回车结束, 但回车符
不属于这个字符串。其调用格式为:
gets(s);
其中s为字符串变量(字符串数组名或字符串指针)。
gets(s)函数与scanf("%s", &s)相似, 但不完全相同, 使用scanf("%s", &s)
函数输入字符串时存在一个问题, 就是如果输入了空格会认为输入字符串结束,
空格后的字符将作为下一个输入项处理, 但gets() 函数将接收输入的整个字符
串直到回车为止。
例5
main()
{
char s[20], *f;
printf("What's your name?\n");
gets(s); /*等待输入字符串直到回车结束*/
puts(s); /*将输入的字符串输出*/
puts("How old are you?");
gets(f);
puts(f);
}
说明:
(1). gets(s)函数中的变量s为一字符串。如果为单个字符, 编译连接不会
有错误, 但运行后会出现"Null pointer asignmemt"的错误。

二、putchar()、getch()、getche()和getchar()函数

1. putchar()函数
putchar()函数是向标准输出设备输出一个字符, 其调用格式为:
putchar(ch);
其中ch为一个字符变量或常量。
putchar()函数的作用等同于printf("%c", ch);
例6:
#include
main()
{
char c: /*定义字符变量*/
c='B'; /*给字符变量赋值*/
putchar(c); /*输出该字符*/
putchar('\x42'); /*输出字母B*/
putchar(0x42); /*直接用ASCII码值输出字母B*/
}
从本例中的连续四个字符输出函数语句可以分清字符变量的不同赋值方法。
2. getch()、getche()和getchar()函数
(1) getch()和getche()函数
这两个函数都是从键盘上读入一个字符。其调用格式为:
getch();
getche();
两者的区别是: getch()函数不将读入的字符回显在显示屏幕上, 而getche()
函数却将读入的字符回显到显示屏幕上。
例7:
#include
main()
{
char c, ch;
c=getch(); /*从键盘上读入一个字符不回显送给字符变量c*/
putchar(c); /*输出该字符*/
ch=getche(); /*从键盘上带回显的读入一个字符送给字符变量ch*/
putchar(ch);
}
利用回显和不回显的特点, 这两个函数经常用于交互输入的过程中完成暂停
等功能。
例8:
#include
main()
{
char c, s[20];
printf("Name:");
gets(s);
printf("Press any key to confinue...");
getch(); /*等待输入任一键*/
}

(2) getchar()函数
getchar()函数也是从键盘上读入一个字符, 并带回显。它与前面两个函数
的区别在于: getchar()函数等待输入直到按回车才结束, 回车前的所有输入字
符都会逐个显示在屏幕上。但只有第一个字符作为函数的返回值。
getchar()函数的调用格式为:
getchar();
例9:
#include
main()
{
char c;
c=getchar(); /*从键盘读入字符直到回车结束*/
putchar(c); /*显示输入的第一个字符*/
getch(); /*等待按任一健*/
}


unicorn-h.spaces. ◇◆ sava-scratch.spaces.  noh enol ! pue pu!w hw u! shemle aq ll!m noh 
2006-10-07 16:28
unicorn
Rank: 4
等 级:贵宾
威 望:14
帖 子:1066
专家分:0
注 册:2005-10-25
收藏
得分:0 

1.2 文件的输入输出函数
键盘、显示器、打印机、磁盘驱动器等逻辑设备, 其输入输出都可以通过文
件管理的方法来完成。而在编程时使用最多的要算是磁盘文件, 因此本节主要以
磁盘文件为主, 详细介绍Turbo C2.0提供的文件操作函数, 当然这些对文件的操
作函数也适合于非磁盘文件的情况。
另外, Turbo C2.0提供了两类关于文件的函数。一类称做标准文件函数也称
缓冲型文件函数, 这是ANSI标准定义的函数; 另一类叫非标准文件函数, 也称非
缓冲型文件函数。这类函数最早公用于UNIX操作系统, 但现在MS-DOS3.0 以上版
本的操作系统也可以使用。下面分别进行介绍。

1.2.1 标准文件函数
标准文件函数主要包括文件的打开、关闭、读和写等函数。不象BASIC 、
FORTRAN语方有顺序文件和随机文件之分, 在打开时就应按不同的方式确定。
Turbo C2.0并不区分这两种文件, 但提供了两组函数, 即顺序读写函数和随机读
写函数。
一、文件的打开和关闭
任何一个文件在使用之前和使用之后, 必须要进行打开和关闭, 这是因为操
作系统对于同时打开的文件数目是有限制的, DOS操作系统中, 可以在DEVICE
.SYS中定义允许同时打开的文件数n(用files=n定义)。其中n 为可同时打开的文
件数, 一般n<=20。因此在使用文件前应打开文件, 才可对其中的信息进行存取。
用完之后需要关闭, 否则将会出现一些意想不到的错误。Turbo C2.0提供了打开
和关闭文件的函数。
1. fopen()函数
fopen函数用于打开文件, 其调用格式为:
FILE *fopen(char *filename, *type);
在介绍这个函数之;前, 先了解一下下面的知识。
(1) 流(stream)和文件(file)
流和文件 在Turbo C2.0中是有区别的, Turbo C2.0 为编程者和被访问的设
备之间提供了一层抽象的东西, 称之为"流", 而将具体的实际设备叫做文件。
流是一个逻辑设备, 具有相同的行为。因此, 用来进行磁盘文件写的函数也同样
可以用来进行打印机的写入。在Turbo C2.0中有两种性质的流: 文字流( text
stream)和二进制(binary stream)。对磁盘来说就是文本文件和二进制文件。本
软件为了便于让读者易理解Turbo C2.0语言而没有对流和文件作特别区分。
(2) 文件指针FILE
实际上FILE是一个新的数据类型。它是Turbo C2.0的基本数据类型的集合,
称之为结构指针。有关结构的概念将在第四节中详细介绍, 这里只要将FILE理解
为一个包括了文件管理有关信息的数据结构, 即在打开文件时必须先定义一个文
件指针。
(3) 以后介绍的函数调用格式将直接写出形式参数的数据类型和函数返回值
的数据类型。例如: 上面打开文件的函数, 返回一个文件指针, 其中形式参数有
两个, 均为字符型变量(字符串数组或字符串指针)。本软件不再对函数的调用格
式作详细说明。
现在再来看打开文件函数的用法。
fopen()函数中第一个形式参数表示文件名, 可以包含路径和文件名两部分。
如:
"B:TEST.DAT"
"C:\\TC\\TEST.DAT"
如果将路径写成"C:\TC\TEST.DAT"是不正确的, 这一点要特别注意。
第二个形式参数表示打开文件的类型。关于文件类型的规定参见下表。
表 文件操作类型
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
字符 含义
────────────────────────────
"r" 打开文字文件只读
"w" 创建文字文件只写
"a" 增补, 如果文件不存在则创建一个
"r+" 打开一个文字文件读/写
"w+" 创建一个文字文件读/写
"a+" 打开或创建一个文件增补
"b" 二进制文件(可以和上面每一项合用)
"t" 文这文件(默认项)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
如果要打开一个CCDOS子目录中, 文件名为CLIB的二进制文件, 可写成:
fopen("c:\\ccdos\\clib", "rb");
如果成功的打开一个文件, fopen()函数返回文件指针, 否则返回空指针
(NULL)。由此可判断文件打开是否成功。

2. fclose()函数
fclose()函数用来关闭一个由fopen()函数打开的文件 , 其调用格式为:
int fclose(FILE *stream);
该函数返回一个整型数。当文件关闭成功时, 返回0, 否则返回一个非零值。
可以根据函数的返回值判断文件是否关闭成功。
例10:
#iclude
main()
{
FILE *fp; /*定义一个文件指针*/
int i;
fp=fopen("CLIB", "rb"); /*打开当前目录名为CLIB的文件只读*/
if(fp==NULL) /*判断文件是否打开成功*/
puts("File open error");/*提示打开不成功*/
i=fclose(fp); /*关闭打开的文件*/
if(i==0) /*判断文件是否关闭成功*/
printf("O,K"); /*提示关闭成功*/
else
puts("File close error");/*提示关闭不成功*/
}

二、有关文件操作的函数
本节所讲的文件读写函数均是指顺序读写, 即读写了一条信息后, 指针自动
加1。下面分别介绍写操作函数和读操作函数。

1. 文件的顺序写函数
fprintf()、fputs()和fputc()函数
函数fprintf()、fputs()和fputc()均为文件的顺序写操作函数, 其调用格
式如下:
int fprintf(FILE *stream, char *format, );
int fputs(char *string, FILE *steam);
int fputc(int ch, FILE *steam);
上述三个函数的返回值均为整型量。fprintf() 函数的返回值为实际写入文
件中的字罕个数(字节数)。如果写错误, 则返回一个负数, fputs()函数返回0时
表明将string指针所指的字符串写入文件中的操作成功, 返回非0时, 表明写操
作失败。fputc()函数返回一个向文件所写字符的值, 此时写操作成功, 否则返
回EOF(文件结束结束其值为-1, 在stdio.h中定义)表示写操作错误。
fprintf( ) 函数中格式化的规定与printf( ) 函数相同, 所不同的只是
fprintf()函数是向文件中写入。而printf()是向屏幕输出。
下面介绍一个例子, 运行后产后一个test.dat的文件。
例11:
#include
main()
{
char *s="That's good news"); /*定义字符串指针并初始化*/
int i=617; /*定义整型变量并初始化*/
FILE *fp; /*定义文件指针*/
fp=fopne("test.dat", "w"); /*建立一个文字文件只写*/
fputs("Your score of TOEFLis", fp);/*向所建文件写入一串字符*/
fputc(':', fp); /*向所建文件写冒号:*/
fprintf(fp, "%d\n", i); /*向所建文件写一整型数*/
fprintf(fp, "%s", s); /*向所建文件写一字符串*/
fclose(fp); /*关闭文件*/
}
用DOS的TYPE命令显示TEST.DAT的内容如下所示:
屏幕显示
Your score of TOEFL is: 617
That's good news

2. 文件的顺序读操作函数
fscanf()、fgets()和fgetc()函数
函数fscanf()、fgets()和fgetc()均为文件的顺序读操作函数, 其调用格式
如下:
int fscanf(FILE *stream, char *format, );
char fgets(char *string, int n, FILE *steam);
int fgetc(FILE *steam);
fscanf()函数的用法与scanf()函数相似, 只是它是从文件中读到信息。
fscanf()函数的返回值为EOF(即-1), 表明读错误, 否则读数据成功。fgets()函
数从文件中读取至多n-1个字符(n用来指定字符数), 并把它们放入string指向的
字符串中, 在读入之后自动向字符串未尾加一个空字符, 读成功返回string指针,
失败返回一个空指针。fgetc()函数返回文件当前位置的一个字符, 读错误时返
回EOF。
下面程序读取例11产生的test.dat文件, 并将读出的结果显示在屏幕上。
例12
#include
main()
{
char *s, m[20];
int i;
FILE *fp;
fp=fopen("test.dat", "r"); /*打开文字文件只读*/
fgets(s, 24, fp); /*从文件中读取23个字符*/
printf("%s", s); /*输出所读的字符串*/
fscanf(fp, "%d", &i); /*读取整型数*/
printf("%d", i); /*输出所读整型数*/
putchar(fgetc(fp)); /*读取一个字符同时输出*/
fgets(m, 17, fp); /*读取16个字符*/
puts(m); /*输出所读字符串*/
fclose(fp); /*关闭文件*/
getch(); /*等待任一键*/
}
运行后屏幕显示:
Your score of TOEFL is: 617
That's good news
如果将上例中fscanf(fp, "%d", &i)改为fscanf(fp, "%s", m), 再将其后
的输出语句改为printf("%s", m), 则可得出同样的结果。由此可见Turbo C2. 0
中只要是读文字文件, 则不论是字符还是数字都将按其ASCII值处理。 另外还要
说明的一点就是fscanf()函数读到空白符时, 便自动结束, 在使用时要特别注意。

3. 文件的随机读写
有时用户想直接读取文件中间某处的信息, 若用文件的顺序读写必须从文件
头开始直到要求的文件位置再读, 这显然不方便。Turbo C2.0提供了一组文件的
随机读写函数, 即可以将文件位置指针定位在所要求读写的地方直接读写。
文件的随机读写函数如下:
int fseek (FILE *stream, long offset, int fromwhere);
int fread(void *buf, int size, int count, FILE *stream);
int fwrite(void *buf, int size, int count, FILE *stream);
long ftell(FILE *stream);
fseek()函数的作用是将文件的位置指针设置到从fromwhere开始的第offset
字节的位置上, 其中fromwhere是下列几个宏定义之一:
文件位置指针起始计算位置fromwhere
━━━━━━━━━━━━━━━━━━━━━━━━━━━
符号常数 数值 含义
───────────────────────────
SEEK_SET 0 从文件开头
SEEK_CUR 1 从文件指针的现行位置
SEEK_END 2 从文件末尾
━━━━━━━━━━━━━━━━━━━━━━━━━━━
offset是指文件位置指针从指定开始位置(fromwhere指出的位置)跳过的字
节数。它是一个长整型量, 以支持大于64K字节的文件。fseek()函数一般用于对
二进制文件进行操作。
当fseek()函数返回0时表明操作成功, 返回非0表示失败。
下面程序从二进制文件test_b.dat中读取第8个字节。
例13:
#include
main()
{
FILE *fp;
if((fp=fopen("test_b.dat", "rb"))==NULL)
{
printf("Can't open file");
exit(1);
}
fseek(fp, 8. 1, SEEK_SET);
fgetc(fp);
fclose(fp);
}
fread()函数是从文件中读count个字段, 每个字段长度为size个字节, 并把
它们存放到buf指针所指的缓冲器中。
fwrite()函数是把buf指针所指的缓冲器中, 长度为size个字节的count个字
段写到stream指向的文件中去。
随着读和写字节数的增大, 文件位置指示器也增大, 读多少个字节, 文件位
置指示器相应也跳过多少个字节。读写完毕函数返回所读和所写的字段个数。
ftell()函数返回文件位置指示器的当前值, 这个值是指示器从文件头开始
算起的字节数, 返回的数为长整型数, 当返回-1时, 表明出现错误。
下面程序把一个浮点数组以二进制方式写入文件test_b.dat中。
例14:
#include
main()
{
float f[6]={3.2, -4.34, 25.04, 0.1, 50.56, 80.5};
/*定义浮点数组并初始化*/
int i;
FILE *fp;
fp=fopen("test_b.dat", "wb"); /*创建一个二进制文件只写*/
fwrite(f, sizeof(float), 6, fp);/*将6个浮点数写入文件中*/
fclose(fp); /*关闭文件*/
}
下面例子从test_b.dat文件中读100个整型数, 并把它们放到dat数组中。
例15:
#include
main()
{
FILE *fp;
int dat[100];
fp=fopen("test_b.dat", "rb");/*打开一个二进制文件只读*/
if(fread(dat, sizeof(int), 100, fp)!=100)
/*判断是否读了100个数*/
{
if(feof(fp))
printf("End of file"); /*不到100个数文件结束*/
else
printf("Read error"); /*读数错误*/
fclose(fp); /*关闭文件*/
}
注意:
当用标准文件函数对文件进行读写操作时, 首先将所读写的内容放进缓冲区,
即写函数只对输出缓冲区进行操作, 读函数只对输入缓冲区进行操作。例如向一
个文件写入内容, 所写的内容将首先放在输出缓冲区中, 直到输出缓冲区存满或
使用fclose()函数关闭文件时, 缓冲区的内容才会写入文件中。若无fclose()
函数, 则不会向文件中存入所写的内容或写入的文件内容不全。有一个对缓冲区
进行刷新的函数, 即fflush(), 其调用格式为:
int fflush(FILE *stream);
该函数将输出缓冲区的内容实际写入文件中, 而将输入缓冲区的内容清除掉。

4. feof()和rewind()函数
这两个函数的调用格式为:
int feof(FILE *stream);
int rewind(FILE *stream);
feof()函数检测文件位置指示器是否到达了文件结尾, 若是则返回一个非0
值, 否则返回0。这个函数对二进制文件操作特别有用, 因为二进制文件中, 文
件结尾标志EOF也是一个合法的二进制数, 只简单的检查读入字符的值来判断文
件是否结束是不行的。如果那样的话, 可能会造成文件未结尾而被认为结尾, 所
以就必须有feof()函数。
下面的这条语句是常用的判断文件是否结束的方法。
while(!feof(fp))
fgetc(fp);
while为循环语句, 将在下面介绍。
rewind()函数用于把文件位置指示器移到文件的起点处, 成功时返回0, 否
则, 返回非0值。


1.2.2 非标准文件函数

这类函数最早用于UNIX操作系统, ANSI标准未定义, 但有时也经常用到,
DOS 3.0以上版本支持这些函数。它们的头文件为io.h。
一、文件的打开和关闭
1. open()函数
open()函数的作用是打开文件, 其调用格式为:
int open(char *filename, int access);
该函数表示按access的要求打开名为filename的文件, 返回值为文件描述字,
其中access有两部分内容: 基本模式和修饰符, 两者用" "("或")方式连接。修
饰符可以有多个, 但基本模式只能有一个。access的规定如表3-2。
表3-2 access的规定
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
基本模式 含义 修饰符 含 义
────────────────────────────
O_RDONLY 只读 O_APPEND 文件指针指向末尾
O_WRONLY 只写 O_CREAT 文件不存在时创建文件,
属性按基本模式属性
O_RDWR 读写 O_TRUNC 若文件存在, 将其长度
缩为0, 属性不变
O_BINARY 打开一个二进制文件
O_TEXT 打开一个文字文件
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
open()函数打开成功, 返回值就是文件描述字的值(非负值), 否则返回-1。

2. close()函数
close()函数的作用是关闭由open()函数打开的文件, 其调用格式为:
int close(int handle);
该函数关闭文件描述字handle相连的文件。

二、读写函数
1. read()函数
read()函数的调用格式为:
int read(int handle, void *buf, int count);
read()函数从handle(文件描述字)相连的文件中, 读取count个字节放到buf
所指的缓冲区中, 返回值为实际所读字节数, 返回-1表示出错。返回0 表示文件
结束。

2. write()函数
write()函数的调用格式为:
int write(int handle, void *buf, int count);
write()函数把count个字节从buf指向的缓冲区写入与handle相连的文件中,
返回值为实际写入的字节数。

三、随机定位函数

1. lseek()函数
lseek()函数的调用格式为:
int lseek(int handle, long offset, int fromwhere);
该函数对与handle相连的文件位置指针进行定位, 功能和用法与fseek() 函
数相同。

2. tell()函数
tell()函数的调用格式为:
long tell(int handle);
该函数返回与handle相连的文件现生位置指针, 功能和用法与ftell()相同。
1.3 控制流程语句
Turbo C2.0提供了丰富、灵活的控制流程语句, 主要有:条件语句、循环语
句和开关语句。下面将对这些语句作详细介绍。



unicorn-h.spaces. ◇◆ sava-scratch.spaces.  noh enol ! pue pu!w hw u! shemle aq ll!m noh 
2006-10-07 16:30
unicorn
Rank: 4
等 级:贵宾
威 望:14
帖 子:1066
专家分:0
注 册:2005-10-25
收藏
得分:0 

1.3.1 条件语句
象其它语言一样Turbo C2.0也提供条件语句。在Turbo C2.0中条件语句的一
般形式为:
if(表达式)
语句1;
else
语句2;
上述结构表示: 如果表达式的值为非0(TURE)即真, 则执行语句1, 执行完语
句1从语句2后开始继续向下执行; 如果表达式的值为0(FALSE)即假, 则跳过语句
1而执行语句2。所谓表达式是指关系表达式和逻辑表达式的结合式, 关于表达式
前面已作过介绍, 这是不再重复。
注意:
1. 条件执行语句中"else 语句2;"部分是选择项, 可以缺省, 此时条件语句
变成:
if(表达式) 语句1;
表示若表达式的值为非0则执行语句1 , 否则跳过语句1继续执行。
2. 如果语句1或语句2有多于一条语句要执行时, 必须使用"{"和"}" 把这些
语句包括在其中, 此时条件语句形式为:
if(表达式)
{
语句体1;
}
else
{
语句体2;
}
3. 条件语句可以嵌套, 这种情况经常碰到, 但条件嵌套语句容易出错, 其
原因主要是不知道哪个if对应哪个else。
例如:
if(x>20||x<-10)
if(y<=100&&y>x)
printf("Good");
else
printf("Bad");
对于上述情况, Turbo C2.0规定: else语句与最近的一个if语句匹配, 上例
中的else与if(y<=100&&y>x)相匹配。为了使else与if(x>20||x<-10)相匹配, 必
须用花括号。如下所示:
if(x>20||x<-10)
{
if(y<=100&&y>x)
printf("Good");
}
else
printf("Bad");
4. 可用阶梯式if-else-if结构。
阶梯式结构的一般形式为:
if(表达式1)
语句1;
else if(表达式2)
语句2;
else if(表达式3)
语句3;
.
.
.
else
语句n;
这种结构是从上到下逐个对条件进行判断, 一旦发现条件满点足就执行与它
有关的语句, 并跳过其它剩余阶梯; 若没有一个条件满足, 则执行最后一个else
语句n。最后这个else常起着"缺省条件"的作用。
同样, 如果每一个条件中有多于一条语句要执行时, 必须使用"{"和"}"把这
些语句包括在其中。


1.3.2 循环语句
Turbo C2.0提供三种基本的循环语句: for语句、while语句和do-while语句。

1.3.2.1 for循环
for循环是开界的。它的一般形式为:
for(<初始化>; <条件表过式>; <增量>)
语句;
初始化总是一个赋值语句, 它用来给循环控制变量赋初值; 条件表达式是一
个关系表达式, 它决定什么时候退出循环; 增量定义循环控制变量每循环一次后
按什么方式变化。这三个部分之间用";"分开。
例如:
for(i=1; i<=10; i++)
语句;
上例中先给i赋初值1, 判断i是否小于等于10, 若是则执行语句, 之后值增
加1。再重新判断, 直到条件为假, 即i>10时, 结束循环。
注意:
1. for循环中语句可以为语句体, 但要用"{"和"}"将参加循环的语句括起来。
2. for循环中的"初始化"、"条件表达式"和"增量"都是选择项, 即可以缺省,
但";"不能缺省。省略了初始化, 表示不对循环控制变量赋初值。 省略了条件
表达式, 则不做其它处理时便成为死循环。省略了增量, 则不对循环控制变量进
行操作, 这时可在语句体中加入修改循环控制变量的语句。
3. for循环可以有多层嵌套。
例16:
main()
{
int i, j, k;
printf("i j k\n");
for (i=0; i<2; i++)
for(j=0; j<2; j++)
for(k=0; k<2; k++)
printf(%d %d %d\n", i, j, k);
}
输出结果为:
i j k
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1

1.3.2.2 while循环
while循环的一般形式为:
while(条件)
语句;
while循环表示当条件为真时, 便执行语句。直到条件为假才结束循环。并
继续执行循环程序外的后续语句。
例17:
#include
main()
{
char c;
c='\0'; /*初始化c*/
while(c!='\X0D') /*回车结束循环*/
c=getche(); /*带回显的从键盘接收字符*/
}
上例中, while循环是以检查c是否为回车符开始, 因其事先被初始化为空,
所以条件为真, 进入循环等待键盘输入字符; 一旦输入回车, 则c='\X0D', 条件
为假, 循环便告结束。
与for循环一样, while循环总是在循环的头部检验条件, 这就意味着循环可
能什么也不执行就退出。
注意:
1. 在while循环体内也允许空语句。
例如:
while((c=getche())!='\X0D');
这个循环直到键入回车为止。
2. 可以有多层循环嵌套。
3. 语句可以是语句体, 此时必须用"{"和"}"括起来。
例18:
#include
main()
{
char c, fname[13];
FILE *fp; /*定义文件指针*/
printf("File name:"); /*提示输入文件名*/
scanf("%s", fname); /*等待输入文件名*/
fp=fopen(fname, "r"); /*打开文件只读*/
while((c=fgetc(fp)!=EOF) /*读取一个字符并判断是否到文件结束*/
putchar(c); /*文件未结束时显示该字符*/

}

1.3.2.3 do-while 循环
do-while 循环的一般格式为:
do
语句;
while(条件);
这个循环与while循环的不同在于: 它先执行循环中的语句, 然后再判断条
件是否为真, 如果为真则继续循环; 如果为假, 则终止循环。因此, do-while循
环至少要执行一次循环语句。
同样当有许多语句参加循环时, 要用"{"和"}"把它们括起来。


1.3.3 开关语句
在编写程序时, 经常会碰到按不同情况分转的多路问题, 这时可用嵌套if
-else-fi语句来实现, 但if-else-if语句使用不方便, 并且容易出错。对这种情
况, Turbo C2.0提供了一个开关语句。开关语句格式为:
switch(变量)
{
case 常量1:
语句1或空;
case 常量2:
语句2或空;
.
.
.
case 常量n;
语句n或空;
default:
语句n+1或空;
}
执行switch开关语句时, 将变量逐个与case后的常量进行比较, 若与其中一
个相等, 则执行该常量下的语句, 若不与任何一个常量相等, 则执行default 后
面的语句。
注意:
1. switch中变量可以是数值, 也可以是字符。
2. 可以省略一些case和default。
3. 每个case或default后的语句可以是语句体, 但不需要使用"{"和"}"括起
来。
下例的switch中变量为整数型。
例19:
main()
{
int test;
for(test=0; test<=10; test++)
{
switch(test) /*变量为整型数的开关语句*/
{
case 1:
printf("%d\n", test);
break; /*退出开关语句*/
case 2:
printf("%d\n", test);
break;
case 3:
printf("%d\n", test);
break;
default:
puts("Error");
break;
}
}
}
下例的switch中变量为字符型。
例20:
#include
main()
{
char c;
while(c!=27) /*循环直到按Esc键结束*/
{
c=getch(); /*从键盘不回显接收一个字符*/
switch(c)
{
case 'A': /*接收的字符为'A'*/
putchar(c);
break; /*退出开关语句*/
case 'B':
putchar(c);
break;
default: /*接收的字符非'A'和'B'*/
puts("Error");
break;
}
}
}

1.3.4 break、continue和goto语句

1.3.4.1 break语句
break语句通常用在循环语句和开关语句中。当break用于开关语句switch中
时, 可使程序跳出switch而执行switch以后的语句; 如果没有break语句, 则将
成为一个死循环而无法退出。break在switch 中的用法已在前面介绍开关语句时
的例子中碰到, 这里不再举例。
当break语句用于do-while、for、while循环语句中时, 可使程序终止循环
而执行循环后面的语句, 通常break语句总是与if语句联在一起。 即满足条件时
便跳出循环。
例19:
main()
{
int i=0;
char c;
while(1) /*设置循环*/
{
c='\0'; /*变量赋初值*/
while(c!=13&&c!=27) /*键盘接收字符直到按回车或Esc键*/
{
c=getch();
printf("%c\n", c);
}
if(c==27)
break; /*判断若按Esc键则退出循环*/
i++;
printf("The No. is %d\n", i);
}
printf("The end");
}
注意:
1. break语句对if-else的条件语句不起作用。
2. 在多层循环中, 一个break语句只向外跳一层。

1.3.4.2 continue 语句
continue语句的作用是跳过循环本中剩余的语句而强行执行下一次循环。
continue语句只用在for、while、do-while等循环体中, 常与if条件语句一
起使用, 用来加速循环。
例20:
main()
{
char c;
while(c!=0X0D) /*不是回车符则循环*/
{
c=getch();
if(c==0X1B)
continue; /*若按Esc键不输出便进行下次循环*/
printf("%c\n", c);
}
}

1.3.4.3 goto 语句
goto语句是一种无条件转移语句, 与BASIC中的goto语句相似。goto 语句的
使用格式为:
goto 标号;
其中标号是Turbo C2.0中一个有效的标识符, 这个标识符加上一个":" 一起
出现在函数内某处, 执行goto语句后, 程序将跳转到该标号处并执行其后的语句。
另外标号必须与goto语句同处于一个函数中, 但可以不在一个循环层中。通常
goto语句与if条件语句连用, 当满足某一条件时, 程序跳到标号处运行。
goto语句通常不用, 主要因为它将使程序层次不清, 且不易读, 但在多层嵌
套退出时, 用goto语句则比较合理。
例19用goto语句时变为:
例21:
main()
{
int i=0;
char c;
while(1)
{
c='\0';
while(c!=13)
{
c=getch();
if(c==27)
goto quit;
printf("%c\n", c);
}
i++;
printf("The No. is %d\n", i);
}
quit:
printf("The end");
}[/


unicorn-h.spaces. ◇◆ sava-scratch.spaces.  noh enol ! pue pu!w hw u! shemle aq ll!m noh 
2006-10-07 16:31
unicorn
Rank: 4
等 级:贵宾
威 望:14
帖 子:1066
专家分:0
注 册:2005-10-25
收藏
得分:0 

第四章 指针、结构、联合和枚举

本章专门对第二节曾讲述过的指针作一详述。并介绍Turbo C新的数据类型:
结构、联合和枚举, 其中结构和联合是以前讲过的五种基本数据类型(整型、浮
点型、字符型、指针型和无值型)的组合。 枚举是一个被命名为整型常数的集合。
最后对类型说明(typedef)和预处理指令作一阐述。

指 针(point)

学习Turbo C语言, 如果你不能用指针编写有效、正确和灵活的程序, 可以
认为你没有学好C语言。指针、地址、数组及其相互关系是C语言中最有特色的部
分。规范地使用指针, 可以使程序达到简单明了, 因此, 我们不但要学会如何正
确地使用指针, 而且要学会在各种情况下正确地使用指针变量。

1. 指针和地址
1.1 指针基本概念及其指针变量的定义
1.1.1 指针变量的定义
我们知道变量在计算机内是占有一块存贮区域的, 变量的值就存放在这块区
域之中, 在计算机内部, 通过访问或修改这块区域的内容来访问或修改相应的变
量。Turbo C语言中, 对于变量的访问形式之一, 就是先求出变量的地址, 然后
再通过地址对它进行访问, 这就是这里所要论述的指针及其指针变量。
所谓变量的指针, 实际上指变量的地址。变量的地址虽然在形式上好象类似
于整数, 但在概念上不同于以前介绍过的整数, 它属于一种新的数据类型, 即指
针类型。Turbo C中, 一般用"指针"来指明这样一个表达式&x的类型, 而用 "地
址"作为它的值, 也就是说, 若x为一整型变量, 则表达式&x的类型是指向整数的
指针, 而它的值是变量x的地址。同样, 若
double d;
则&d的类型是指向以精度数d的指针, 而&d的值是双精度变量d的地址。所以, 指
针和地址是用来叙述一个对象的两个方面。虽然&x、&d的值分别是整型变量x 和
双精度变量d的地址, 但&x、&d的类型是不同的, 一个是指向整型变量x的指针,
而另一个则是指向双精度变量d的指针。在习惯上, 很多情况下指针和地址这两
个术语混用了。
我们可以用下述方法来定义一个指针类型的变量。
int *ip;
首先说明了它是一指针类型的变量, 注意在定义中不要漏写符号"*", 否则它为
一般的整型变量了。另外, 在定义中的int 表示该指针变量为指向整型数的指针
类型的变量, 有时也可称ip为指向整数的指针。ip是一个变量, 它专门存放整型
变量的地址。
指针变量的一般定义为:
类型标识符 *标识符;
其中标识符是指针变量的名字, 标识符前加了"*"号, 表示该变量是指针变
量, 而最前面的"类型标识符"表示该指针变量所指向的变量的类型。一个指针变
量只能指向同一种类型的变量, 也就是讲, 我们不能定义一个指针变量, 既能指
向一整型变量又能指向双精度变量。
指针变量在定义中允许带初始化项。如:
int i, *ip=&i;
注意, 这里是用&i对ip初始化, 而不是对*ip初始化。和一般变量一样, 对于外
部或静态指针变量在定义中若不带初始化项, 指针变量被初始化为NULL, 它的值
为0。Turbo C中规定, 当指针值为零时, 指针不指向任何有效数据, 有时也称指
针为空指针。因此, 当调用一个要返回指针的函数(第五节中介绍)时, 常使用返
回值为NULL来指示函数调用中某些错误情况的发生。
1.1.2 指针变量的引用
既然在指针变量中只能存放地址, 因此, 在使用中不要将一个整数赋给一指
针变量。下面的赋值是不合法的:
int *ip;
ip=100;
假设
int i=200, x;
int *ip;
我们定义了两个整型变量i, x, 还定义了一个指向整型数的指针变量ip。i, x中
可存放整数, 而ip中只能存放整型变量的地址。我们可以把i的地址赋给ip:
ip=&i;
此时指针变量ip指向整型变量i, 假设变量i的地址为1800, 这个赋值可形象理解
为下图所示的联系。
ip i
┏━━━┓ ┏━━━┓
┃ 1800 ╂──→ ┃ 200 ┃
┗━━━┛ ┗━━━┛
图1. 给指针变量赋值
以后我们便可以通过指针变量ip间接访问变量i, 例如:
x=*ip;
运算符*访问以ip为地址的存贮区域, 而ip中存放的是变量i的地址, 因此, *ip
访问的是地址为1800的存贮区域(因为是整数, 实际上是从1800开始的两个字节),
它就是i所占用的存贮区域, 所以上面的赋值表达式等价于
x=i;
另外, 指针变量和一般变量一样, 存放在它们之中的值是可以改变的, 也就
是说可以改变它们的指向, 假设
int i, j, *p1, *p2;
i='a';
j='b';
p1=&i;
p2=&j;
则建立如下图所示的联系:
p1 i
┏━━━┓ ┏━━━┓
┃ ╂──→ ┃ 'a' ┃
┗━━━┛ ┗━━━┛
p2 i
┏━━━┓ ┏━━━┓
┃ ╂──→ ┃ 'b' ┃
┗━━━┛ ┗━━━┛
图2. 赋值运算结果
这时赋值表达式:
p2=p1
就使p2与p1指向同一对象i, 此时*p2就等价于i, 而不是j, 图2.就变成图3.所示:
p1 i
┏━━━┓ ┏━━━┓
┃ ╂──→ ┃ 'a' ┃
┗━━━┛ ┌→ ┗━━━┛
p2 │ j
┏━━━┓ │ ┏━━━┓
┃ ╂─┘ ┃ 'b' ┃
┗━━━┛ ┗━━━┛
图3. p2=p1时的情形
如果执行如下表达式:
*p2=*p1;
则表示把p1指向的内容赋给p2所指的区域, 此时图2.就变成图4.所示
p1 i
┏━━━┓ ┏━━━┓
┃ ╂──→ ┃ 'a' ┃
┗━━━┛ ┗━━━┛
p2 j
┏━━━┓ ┏━━━┓
┃ ╂──→ ┃ 'a' ┃
┗━━━┛ ┗━━━┛
图4. *p2=*p1时的情形
通过指针访问它所指向的一个变量是以间接访问的形式进行的, 所以比直接
访问一个变量要费时间, 而且不直观, 因为通过指针要访问哪一个变量, 取决于
指针的值(即指向), 例如"*p2=*p1;"实际上就是"j=i;", 前者不仅速度慢而且目
的不明。但由于指针是变量, 我们可以通过改变它们的指向, 以间接访问不同的
变量, 这给程序员带来灵活性, 也使程序代码编写得更为简洁和有效。
指针变量可出现在表达式中, 设
int x, y *px=&x;
指针变量px指向整数x, 则*px可出现在x能出现的任何地方。例如:
y=*px+5; /*表示把x的内容加5并赋给y*/
y=++*px; /*px的内容加上1之后赋给y [++*px相当于++(px)]*/
y=*px++; /*相当于y=*px; px++*/

1.2. 地址运算
指针允许的运算方式有:
(1). 指针在一定条件下, 可进行比较, 这里所说的一定条件, 是指两个指
针指向同一个对象才有意义, 例如两个指针变量p, q指向同一数组, 则<, >, >=,
<=, ==等关系运算符都能正常进行。若p==q为真, 则表示p, q指向数组的同一元
素; 若p12)?name[0]:name[n]);
}
main()
{
int i;
for(i=0; i<13; i++)
printf("%s\n", month_name(i));

}

结 构(struct)
结构是由基本数据类型构成的、并用一个标识符来命名的各种变量的组合。
结构中可以使用不同的数据类型。

1. 结构说明和结构变量定义
在Turbo C中, 结构也是一种数据类型, 可以使用结构变量, 因此, 象其它
类型的变量一样, 在使用结构变量时要先对其定义。
定义结构变量的一般格式为:
struct 结构名
{
类型 变量名;
类型 变量名;
...
} 结构变量;
结构名是结构的标识符不是变量名。
类型为第二节中所讲述的五种数据类型(整型、浮点型、字符型、指针型和
无值型)。
构成结构的每一个类型变量称为结构成员, 它象数组的元素一样, 但数组中
元素是以下标来访问的, 而结构是按变量名字来访问成员的。
下面举一个例子来说明怎样定义结构变量。
struct string
{
char name[8];
int age;
char sex[2];
char depart[20];
float wage1, wage2, wage3, wage4, wage5;
} person;
这个例子定义了一个结构名为string的结构变量person, 如果省略变量名
person, 则变成对结构的说明。用已说明的结构名也可定义结构变量。这样定义
时上例变成:
struct string
{
char name[8];
int age;
char sex[2];
char depart[20];
float wage1, wage2, wage3, wage4, wage5;
};
struct string person;
如果需要定义多个具有相同形式的结构变量时用这种方法比较方便, 它先作
结构说明, 再用结构名来定义变量。
例如:
struct string Tianyr, Liuqi, ...;
如果省略结构名, 则称之为无名结构, 这种情况常常出现在函数内部, 用这
种结构时前面的例子变成:
struct
{
char name[8];
int age;
char sex[2];
char depart[20];
float wage1, wage2, wage3, wage4, wage5;
} Tianyr, Liuqi;

2. 结构变量的使用
结构是一个新的数据类型, 因此结构变量也可以象其它类型的变量一样赋值、
运算, 不同的是结构变量以成员作为基本变量。
结构成员的表示方式为:
结构变量.成员名
如果将"结构变量.成员名"看成一个整体, 则这个整体的数据类型与结构中
该成员的数据类型相同, 这样就可象前面所讲的变量那样使用。
下面这个例子定义了一个结构变量, 其中每个成员都从键盘接收数据, 然后
对结构中的浮点数求和, 并显示运算结果, 同时将数据以文本方式存入一个名为
wage.dat的磁盘文件中。请注意这个例子中不同结构成员的访问。
例3:
#include
main()
{
struct{ /*定义一个结构变量*/
char name[8];
int age;
char sex[2];
char depart[20];
float wage1, wage2, wage3, wage4, wage5;
}a;
FILE *fp;
float wage;
char c='Y';
fp=fopen("wage.dat", "w"); /*创建一个文件只写*/
while(c=='Y'||c=='y') /*判断是否继续循环*/
{
printf("\nName:");
scanf("%s", a.name); /*输入姓名*/
printf("Age:");
scanf("%d", &a.wage); /*输入年龄*/
printf("Sex:");
scanf("%d", a.sex);
printf("Dept:");
scanf("%s", a.depart);
printf("Wage1:");
scanf("%f", &a.wage1); /*输入工资*/
printf("Wage2:");
scanf("%f", &a.wage2);
printf("Wage3:");
scanf("%f", &a.wage3);
printf("Wage4:");
scanf("%f", &a.wage4);
printf("Wage5:");
scanf("%f", &a.wage5);
wage=a.wage1+a.wage2+a.wage3+a.wage4+a.wage5;
printf("The sum of wage is %6.2f\n", wage);/*显示结果*/
fprintf(fp, "%10s%4d%4s%30s%10.2f\n", /*结果写入文件*/
a.name, a.age, a.sex, a.depart, wage);
while(1)
{
printf("Continue?");
c=getche();
if(c=='Y'||c=='y'||c=='N'||c=='n')
break;
}
}
fclose(fp);
}

3. 结构数组和结构指针
结构是一种新的数据类型, 同样可以有结构数组和结构指针。
一、结构数组
结构数组就是具有相同结构类型的变量集合。假如要定义一个班级40个同学
的姓名、性别、年龄和住址, 可以定义成一个结构数组。如下所示:
struct{
char name[8];
char sex[2];
int age;
char addr[40];
}student[40];
也可定义为:
struct string{
char name[8];
char sex[2];
int age;
char addr[40];
};
struct string student[40];
需要指出的是结构数组成员的访问是以数组元素为结构变量的, 其形式为:
结构数组元素.成员名
例如:
student[0].name
student[30].age
实际上结构数组相当于一个二维构造, 第一维是结构数组元素, 每个元素是
一个结构变量, 第二维是结构成员。
注意:
结构数组的成员也可以是数组变量。
例如:
struct a
{
int m[3][5];
float f;
char s[20];
}y[4];
为了访问结构a中结构变量y[2]的这个变量, 可写成
y[2].m[1][4]


unicorn-h.spaces. ◇◆ sava-scratch.spaces.  noh enol ! pue pu!w hw u! shemle aq ll!m noh 
2006-10-07 16:33
unicorn
Rank: 4
等 级:贵宾
威 望:14
帖 子:1066
专家分:0
注 册:2005-10-25
收藏
得分:0 

二、结构指针
结构指针是指向结构的指针。它由一个加在结构变量名前的"*" 操作符来定
义, 例如用前面已说明的结构定义一个结构指针如下:
struct string{
char name[8];
char sex[2];
int age;
char addr[40];
}*student;
也可省略结构指针名只作结构说明, 然后再用下面的语句定义结构指针。
struct string *student;
使用结构指针对结构成员的访问, 与结构变量对结构成员的访问在表达方式
上有所不同。结构指针对结构成员的访问表示为:
结构指针名->结构成员
其中"->"是两个符号"-"和">"的组合, 好象一个箭头指向结构成员。例如要
给上面定义的结构中name和age赋值, 可以用下面语句:
strcpy(student->name, "Lu G.C");
student->age=18;
实际上, student->name就是(*student).name的缩写形式。
需要指出的是结构指针是指向结构的一个指针, 即结构中第一个成员的首地
址, 因此在使用之前应该对结构指针初始化, 即分配整个结构长度的字节空间,
这可用下面函数完成, 仍以上例来说明如下:
student=(struct string*)malloc(size of (struct string));
size of (struct string)自动求取string结构的字节长度, malloc() 函数
定义了一个大小为结构长度的内存区域, 然后将其诈地址作为结构指针返回。

注意:
1. 结构作为一种数据类型, 因此定义的结构变量或结构指针变量同样有局
部变量和全程变量, 视定义的位置而定。
2. 结构变量名不是指向该结构的地址, 这与数组名的含义不同, 因此若需
要求结构中第一个成员的首地址应该是&[结构变量名]。
4. 结构的复杂形式
一、嵌套结构
嵌套结构是指在一个结构成员中可以包括其它一个结构, Turbo C 允许这种
嵌套。
例如: 下面是一个有嵌套的结构
struct string{
char name[8];
int age;
struct addr address;
} student;
其中: addr为另一个结构的结构名, 必须要先进行, 说明, 即
struct addr{
char city[20];
unsigned lon zipcode;
char tel[14];
}
如果要给student结构中成员address结构中的zipcode赋值, 则可写成:
student.address.zipcode=200001;
每个结构成员名从最外层直到最内层逐个被列出, 即嵌套式结构成员的表达
方式是:
结构变量名.嵌套结构变量名.结构成员名
其中: 嵌套结构可以有很多, 结构成员名为最内层结构中不是结构的成员名。

二、位结构
位结构是一种特殊的结构, 在需按位访问一个字节或字的多个位时, 位结构
比按位运算符更加方便。
位结构定义的一般形式为:
struct位结构名{
数据类型 变量名: 整型常数;
数据类型 变量名: 整型常数;
} 位结构变量;
其中: 数据类型必须是int(unsigned或signed)。 整型常数必须是非负的整
数, 范围是0~15, 表示二进制位的个数, 即表示有多少位。
变量名是选择项, 可以不命名, 这样规定是为了排列需要。
例如: 下面定义了一个位结构。
struct{
unsigned incon: 8; /*incon占用低字节的0~7共8位*/
unsigned txcolor: 4;/*txcolor占用高字节的0~3位共4位*/
unsigned bgcolor: 3;/*bgcolor占用高字节的4~6位共3位*/
unsigned blink: 1; /*blink占用高字节的第7位*/
}ch;
位结构成员的访问与结构成员的访问相同。
例如: 访问上例位结构中的bgcolor成员可写成:
ch.bgcolor

注意:
1. 位结构中的成员可以定义为unsigned, 也可定义为signed, 但当成员长
度为1时, 会被认为是unsigned类型。因为单个位不可能具有符号。
2. 位结构中的成员不能使用数组和指针, 但位结构变量可以是数组和指针,
如果是指针, 其成员访问方式同结构指针。
3. 位结构总长度(位数), 是各个位成员定义的位数之和, 可以超过两个字
节。
4. 位结构成员可以与其它结构成员一起使用。
例如:
struct info{
char name[8];
int age;
struct addr address;
float pay;
unsigned state: 1;
unsigned pay: 1;
}workers;'
上例的结构定义了关于一个工从的信息。其中有两个位结构成员, 每个位结
构成员只有一位, 因此只占一个字节但保存了两个信息, 该字节中第一位表示工
人的状态, 第二位表示工资是否已发放。由此可见使用位结构可以节省存贮空间。

联 合(union)
1. 联合说明和联合变量定义
联合也是一种新的数据类型, 它是一种特殊形式的变量。
联合说明和联合变量定义与结构十分相似。其形式为:
union 联合名{
数据类型 成员名;
数据类型 成员名;
...
} 联合变量名;
联合表示几个变量公用一个内存位置, 在不同的时间保存不同的数据类型
和不同长度的变量。
下例表示说明一个联合a_bc:
union a_bc{
int i;
char mm;
};
再用已说明的联合可定义联合变量。
例如用上面说明的联合定义一个名为lgc的联合变量, 可写成:
union a_bc lgc;
在联合变量lgc中, 整型量i和字符mm公用同一内存位置。
当一个联合被说明时, 编译程序自动地产生一个变量, 其长度为联合中最大
的变量长度。
联合访问其成员的方法与结构相同。同样联合变量也可以定义成数组或指针,
但定义为指针时, 也要用"->"符号, 此时联合访问成员可表示成:
联合名->成员名
另外, 联合既可以出现在结构内, 它的成员也可以是结构。
例如:
struct{
int age;
char *addr;
union{
int i;
char *ch;
}x;
}y[10];
若要访问结构变量y[1]中联合x的成员i, 可以写成:
y[1].x.i;
若要访问结构变量y[2]中联合x的字符串指针ch的第一个字符可写成:
*y[2].x.ch;
若写成"y[2].x.*ch;"是错误的。

2. 结构和联合的区别
结构和联合有下列区别:
1. 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻,
联合中只存放了一个被选中的成员, 而结构的所有成员都存在。
2. 对于联合的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存
在了, 而对于结构的不同成员赋值是互不影响的。
下面举一个例了来加对深联合的理解。
例4:
main()
{
union{ /*定义一个联合*/
int i;
struct{ /*在联合中定义一个结构*/
char first;
char second;
}half;
}number;
number.i=0x4241; /*联合成员赋值*/
printf("%c%c\n", number.half.first, mumber.half.second);
number.half.first='a'; /*联合中结构成员赋值*/
number.half.second='b';
printf("%x\n", number.i);
getch();
}
输出结果为:
AB
6261
从上例结果可以看出: 当给i赋值后, 其低八位也就是first和second的值;
当给first和second赋字符后, 这两个字符的ASCII码也将作为i 的低八位和高八
位。


枚 举(enum)

枚举是一个被命名的整型常数的集合, 枚举在曰常生活中很常见。
例如表示星期的SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,
SATURDAY, 就是一个枚举。
枚举的说明与结构和联合相似, 其形式为:
enum 枚举名{
标识符[=整型常数],
标识符[=整型常数],
...
标识符[=整型常数],
} 枚举变量;
如果枚举没有初始化, 即省掉"=整型常数"时, 则从第一个标识符开始, 顺
次赋给标识符0, 1, 2, ...。但当枚举中的某个成员赋值后, 其后的成员按依次
加1的规则确定其值。
例如下列枚举说明后, x1, x2, x3, x4的值分别为0, 1, 2, 3。
enum string{x1, x2, x3, x4}x;
当定义改变成:
enum string
{
x1,
x2=0,
x3=50,
x4,
}x;
则x1=0, x2=0, x3=50, x4=51
注意:
1. 枚举中每个成员(标识符)结束符是",", 不是";", 最后一个成员可省略
","。
2. 初始化时可以赋负数, 以后的标识符仍依次加1。
3. 枚举变量只能取枚举说明结构中的某个标识符常量。
例如:
enum string
{
x1=5,
x2,
x3,
x4,
};
enum strig x=x3;
此时, 枚举变量x实际上是7。

类 型 说 明

类型说明的格式为:
typedef 类型 定义名;
类型说明只定义了一个数据类型的新名字而不是定义一种新的数据类型。这
里类型是Turbo C许可的任何一种数据类型。定义名表示这个类型的新名字。
例如: 用下面语句定义整型数的新名字:
typedef int SIGNED_INT;
使用说明后, SIGNED_INT就成为int的同义词了, 此时可以用SIGNED_INT 定
义整型变量。
例如: SIGNED_INT i, j;(与int i, j等效)。
但 long SIGNED_INT i, j; 是非法的。
typedef同样可用来说明结构、联合以及枚举。
说明一个结构的格式为:
typedef struct{
数据类型 成员名;
数据类型 成员名;
...
} 结构名;
此时可直接用结构名定义结构变量了。例如:
typedef struct{
char name[8];
int class;
char subclass[6];
float math, phys, chem, engl, biol;
} student;
student Liuqi;
则Liuqi被定义为结构数组和结构指针。
在第二节讲过的文件操作中, 用到的FILE就是一个已被说明的结构, 其说明
如下:
typedef struct
{
short level;
unsigned flags;
char fd;
unsigned char hold;
short bsize;
unsigned char *buffer;
unsigned char *curp;
unsigned istemp;
short token;
} FILE
这个结构说明已包含在stdio.h中, 用户只要直接用FILE 定义文件指针变量
就可以。事实上, 引入类型说明的目的并非为了方便, 而是为了便于程序的移植。

预 处 理 指 令

由ANSI的标准规定, 预处理指令主要包括:
#define
#error
#if
#else
#elif
#endif
#ifdef
#ifndef
#undef
#line
#pragma
由上述指令可以看出, 每个预处理指令均带有符号"#"。下面只介绍一些常
用指令。
1. #define 指令
#define指令是一个宏定义指令, 定义的一般形式是:
#define 宏替换名字符串(或数值)
由#define指令定义后, 在程序中每次遇到该宏替换名时就用所定义的字符
串(或数值)代替它。
例如: 可用下面语句定义TRUE表示数值1, FALSE表示0。
#define TRUE 1
#define FALSE 0
一旦在源程序中使用了TRUE和FALSE, 编译时会自动的用1和0代替。
注意:
1. 在宏定义语名后没有";"
2. 在Turbo C程序中习惯上用大写字符作为宏替换名, 而且常放在程序开头。
3. 宏定义还有一个特点, 就是宏替换名可以带有形式参数, 在程序中用到
时, 实际参数会代替这些形式参数。
例如:
#define MAX(x, y) (x>y)?x:y
main()
{
int i=10, j=15;
printf("The Maxmum is %d", MAX(i, j);
}
上例宏定义语句的含义是用宏替换名MAX(x, y)代替x, y中较大者, 同样也
可定义:
#define MIN(x, y) (x
程序也允许嵌入其它文件, 例如:
main()
{
#include
}
其中help.c为另一个文件, 内容可为
printf("Glad to meet you here!");
上例编译时将按集成开发环境的Options/Directories/Include directories
中指定的包含文件路径查找被嵌入文件。

4. #if、#else、#endif指令
#if、#els和#endif指令为条件编择指令, 它的一般形式为:
#if 常数表达式
语句段;
#else
语句段;
#endif
上述结构的含义是: 若#if指令后的常数表达式为真, 则编译#if到#else 之
间的程序段; 否则编译#else到#endif之间的程序段。
例如:
#define MAX 200
main()
{
#if MAX>999
printf("compiled for bigger\n");
#else
printf("compiled for small\n");
#endif
}

5. #undef指令
#undef指令用来删除事先定义的宏定义, 其一般形式为:
#undef 宏替换名
例如:
#define TRUE 1
...
#undef TURE
#undef主要用来使宏替换名只限定在需要使用它们的程序段中。


unicorn-h.spaces. ◇◆ sava-scratch.spaces.  noh enol ! pue pu!w hw u! shemle aq ll!m noh 
2006-10-07 16:33
快速回复:[推荐]从Turbo C学习C语言基础
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.034338 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved