从零开始学C程序设计(txt+pdf+epub+mobi电子书下载)


发布时间:2020-08-29 05:55:27

点击下载

作者:吴惠茹 等

出版社:机械工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

从零开始学C程序设计

从零开始学C程序设计试读:

前言

在计算机发展的几十年间,众多程序设计语言不断被各个时期的“达人”创造出来,进而不断被淘汰、取代、修订、融合或改头换面。和近年流行的程序设计语言(如Python、C#、Java、C++、PHP、JavaScript等)相比,C语言显得有点“古董”,因为C语言的发展历史最悠久——设计思想萌芽于1970年年初,主体完成于1973年。但C语言在2015年仍然高居全世界所有程序设计语言使用人数的榜首,到2016年才被Java超过而屈居第二。

C语言之所以长久不衰,是因为程序代码简洁高效、编译方式简易、能处理底层的存储器、产生的机器代码简短精悍,而且不需要复杂的系统运行环境便能高效运行。C语言的这些特质深受广大程序员喜爱,并被广泛应用于操作系统和编译器的开发。例如,UNIX和Linux就是基于C语言开发出来的,其他众多系统级的工具和各种高级程序设计语言的编译器或解释器大多也是使用C语言开发的。所以,C语言被称为程序员的第一程序设计语言一点都不为过。

现在学C语言过时吗?作为一门通用计算机程序设计语言,C语言远没有到过时的时候,只要学习C语言时不禁锢于面向过程程序设计思维,从零开始迅速掌握其精髓,而后补充面向对象程序设计的新思想,之后在学习C++、C#、Java或Python语言时就能得心应手。如果从一开始就学习上述4种面向对象的通用程序设计语言,会感到头疼不已。在出版本书的同时,我们还出版了一本《从零开始学C++程序设计》供大家参考。C++语言=C语言+面向对象的概念,在C#、Java甚至Python中均可看到C++的影子。

本书以教学为背景,分16章说明C语言相关的语法,除了在正文的讲解中穿插大量范例程序的分析外,还在各章末尾辅以课后习题与解答,并提供了丰富的上机程序测试题。本书适合作为大专院校计算机及相关专业的教材,也适合作为程序设计初学者的自学教材,同样可作为有一定编程经验、想快速掌握C语言的程序员的学习参考书。

本书的范例程序有两类:一类是各章正文讲解使用的范例程序,另一类是各章后面“上机程序测验”提供的参考范例程序。读者可以从以下网址免费下载所有范例程序的源代码:

http://pan.baidu.com/s/1nvDbllZ(注意区分数字和字母大小写)

如果下载有问题,请发送电子邮件至booksaga@126.com,邮件主题设置为“求从零开始学C程序代码”。

全书所有范例程序都可以在标准C语言编程环境中编译通过和顺利运行。本书选用免费的Dev C++5.11集成开发环境对书中所有范例程序进行编译、修改、调试和测试,确保可以准确无误地运行,读者可以放心参考、使用。另外,附录A包含“C的标准函数库”,以便读者在学习的过程中速查常用的C语言标准函数的用法。附录B包含“C编译程序的介绍与安装”,重点介绍Dev C++集成开发环境的安装步骤和基本使用方法,读者可以在学习本书之前在自己的计算机上安装好Dev C++集成开发环境。

本书主要由吴惠茹编著,卞诚君、王叶、周晓娟、刘雪连、吉媛媛、闫秀华、关静、孟宗斌、魏忠波、王翔、郭丹阳等人也参与了本书的编写与校对工作。虽然本书校稿过程力求无误,但是难免有疏漏之处,还望各位不吝赐教!

最后,祝大家学习顺利,迅速掌握C语言程序设计的精髓,进而成为使用C语言编程的高手,迈出成为合格程序员关键的一步。编者2017年2月第1章C语言的第一堂课“程序设计语言”是人类用来和计算机沟通的语言,也是指挥计算机运行或运算的指令集合,可以将程序设计者的思考逻辑和语言转换成计算机能够理解的语言。C语言称得上是一种历史悠久的高级程序设计语言,也往往是初学者最先接触的程序设计语言,它对近代的程序设计领域有着非凡的贡献。1-1 C语言的起源

1972年,贝尔实验室的Dennis Ritchie以B语言为基础,持续改善与发展,除了保留BCLP及B语言中的许多概念外,还加入了数据类型的概念和函数的功能,并且重新将它发表为C语言。在许多平台的主机上都有C语言的编译程序,例如MS-DOS、Windows系列操作系统、UNIX/Linux,甚至Apple公司的Mac系列系统等都有C语言的专用编译程序。许多程序设计人员使用C语言能够轻易地跨越不同平台来开发程序,因此让C语言广受科技界的欢迎。

由于各家厂商所开发和发布的C语言在编译程序时经常融入不同的特性与特殊的语法,因此给程序员在开发上增添了不少困扰。在20世纪80年代初(1980),美国国家标准局(American National Standard Institution)特别为C语言订制了一套完整的国际标准语法,称为ANSI C,最终成为了C语言的业界标准。于是1980年后,与C语言程序开发相关的工具一般都支持符合ANSI C的语法,所以大家在学习C语言时,使用最纯粹且符合ANSI C规范的C语言语法,几乎可以在各个平台上通行无阻。

经过数十年的发展,市场上众多厂商开发了许多种C语言编译程序,其中包含Borland公司的Turbo C/C++、Borland C++与Borland C++Builder以及Microsoft公司的Visual C++等。另外,还有免费版本的C语言编译程序,包含MinGW、GCC、Dev C++等。C程序的特色

一般我们将程序设计语言分为高级语言与低级语言,但C语言经常被程序员称为中级语言,原因是C语言不但具有高级语言的亲和力(例如C语言的语法让人容易理解,可读性高,相当接近人类的习惯用语),而且在C语言的程序代码中允许开发者加入低级的汇编程序,使得C程序能够与硬件系统直接沟通。

在还没有正式编写C程序之前,大家先要了解C本身属于一种编译式语言,也就是使用编译程序(Compiler,或称为编译器)将源程序转换为机器可读取的可执行文件或目标程序,不过编译程序必须先把源程序读入主存储器(内存)才可以开始编译。

编译后的目标程序可直接对应成机器码,故可在计算机上直接执行,不需要每次执行时再重新编译,执行速度自然较快。每次修改源程序,必须重新经过编译程序编译,才能保持运行文件为最新版本。

提示 解释式语言与编译式语言不同,前者是使用解释器(Interpreter)来对高级语言的源代码进行逐行解释,每次解释完一行程序语句才会解释下一行程序语句。解释的过程中如果发生错误,解释动作就会立刻停止。由于使用解释器解释的程序每次运行时都必须再解释一次,因此运行速度较慢,不过因为仅需存取源程序、不需要转换为其他类型的文件,所以占用的内存较少。例如,BASIC、Lisp、Prolog等语言都使用解释执行的方法。

C语言可以直接处理底层内存,甚至用于实现位逻辑运算,因此所能实现的功能不仅仅限于开发常规的软件包,还可以开发硬件驱动程序、网络协议以及嵌入式系统等。特别值得一提的是以C语言开发出来的程序文件容量相对较小,并且不需要依赖虚拟机或运行时(runtime)环境就可以直接运行。与Java、Visual Basic、Pascal等程序设计语言相比,C语言的执行效率相当高,运行时也相当稳定。例如,相当知名的开放源码操作系统——Linux便是以C语言所编写而成的,一般对修改Linux源代码有兴趣的学者与工程师,肯定都要有C语言的基础才能够入门。C的设计模式与语法深深影响了许多后来发展出来的程序设计语言,最显著的例子是C++、Java、C#等。1-2 我的第一个C程序

其实学习程序设计语言和学游泳一样,下水直接体验才是最快的方法。从笔者多年从事程序设计语言的教学经验中得出这样的结论:在教初学者学习新的程序设计语言时,废话不要太多,让他们从无到有、实际编写和运行一个程序最为重要,许多编程高手都是程序写多了,对所使用的程序设计语言的领悟就越来越深。

早期,要学习C语言程序设计,首先必须找一种文本编辑器来进行程序的编辑,例如Windows系统下的“记事本”编辑器,或者Linux系统下的vi编辑器,接着选一种C语言的编译程序(如Turbo C/C++、MinGW、GCC等)编译,然后运行。不过现在不用这么麻烦了,只要找个可将程序的编辑、编译、运行与调试等功能集成于同一个操作环境下的“集成开发环境”(Integrated Development Environment,IDE)即可。

由于C语言的应用市场很大,市面上较为知名的IDE就有Dev C++、Visual C++Express、C++Builder、Visual C++和GCC等。现在流行的几种C/C++集成开发环境都有一些自定义的语法与特殊功能。对于初学者而言,只要从基本的内容着手,将重点放在语法、逻辑等方面就可以了。目前市面上几乎没有单纯的C语言编译程序,通常都是与C++编译程序兼容,称为C/C++编译程序或编译器。注意,本书中所有的C程序文件都是以免费的Dev C++集成开发环境来进行编译与运行的。

现在请各位读者按照附录B的说明,在你的计算机中安装好Dev C++,然后开始运行Dev C++集成开发环境,随后就会出现程序运行界面,如图1-1所示。图1-1 Dev C++集成开发环境

接下来带领大家使用Dev C++来编写第一个程序helloworld(文件名)。首先要打开的是单个文件的功能,也就是编写单个程序。请选择“文件”→“新建”→“源代码”以打开一个新的源代码文件,然后在Dev C++的程序代码编辑区中输入第一个C语言练习程序代码:#include #include int main(void){ int no; no=2; printf("There are %d pandas in Beijing.\n",no); /*输出北京有两只熊猫*/ system("PAUSE"); return 0; }1-2-1 程序代码编写规则

当我们开始在Dev C++中输入程序代码时,C语言的程序代码编写采用的是自由格式(free format),也就是只要不违背基本语法规则,就可以自由安排程序代码的位置,不过字母大小写是有区分的。请注意,Dev C++是一种可视化的窗口编辑环境,而且还会将程序代码中的字符串(红色)、指令(黑色)与注释(深蓝色)标示成不同颜色。

每一条语句以“;”(分号)作为结尾与分隔,中间有空格符、Tab键、换行,它们都算是空白(white space)。也就是说,我们可以将一条语句拆成几行,或将几条语句放在同一行。

这是因为编译程序会忽略程序代码中所有的空白(除了“""”包括的内容,因为它属于字符串内容),只有当编译程序遇到“;”(分号)时,才会判定该条语句结束。在同一条语句中,完整不可分割的单元称为标记符号(token),两个标记符号间必须以空格键、tab键或回车键来分隔,如图1-2所示。图1-2 C语言程序在Dev C++集成开发环境中显示的样子

如果这个文件是新建的文件,而且尚未存盘,Dev C++会提醒你先将该文件存盘。在此我们将文件存为helloworld.c,如图1-3所示。图1-3 将新建的C语言程序文件存盘1-2-2 编译程序代码

接下来开始执行编译过程,单击工具栏中的“编译”按钮或依次选择“运行”→“编译”菜单选项,接着在“编译日志”窗格中显示编译过程,代表文件正在编译,如果编译成功,就会显示出如图1-4所示的编译结果。图1-4 编译成功后显示的编译日志

编译阶段包括“编译”“链接”两个步骤,如果没有语法错误,编译程序就会把翻译结果存成目标文件(object file)。目标代码是一种二进制文件,此文件的扩展名为“*.obj”,这个目标文件经由链接程序(linker)链接到其他目标文件和函数库后,最后生成可执行文件。由于在Dev C++中默认使用完这个目标文件后会删除,因此一般看不到这类文件。1-2-3 运行C程序

可执行文件的扩展文件名在Windows系统下是“*.exe”,当C语言的程序代码“摇身一变”成了可执行文件后,可以依次选择“运行”→“运行”菜单项或单击“运行”按钮,出现如图1-5所示的运行结果,再按任意键回到Dev C++的编辑环境。图1-5 C程序运行结果的范例1-2-4 程序代码的调试

由于上面使用的是范例程序,因此不会出现错误信息。当我们编写一个新程序在第一次运行时发生错误而看到出错提示的信息时,千万不要大惊小怪。如果编写完一个较长的程序而完全没有错误,反而是件怪事。调试(Debug)是程序员编写程序时的日常工作,通常会出现的错误可以分为语法错误与逻辑错误两种。

所谓语法错误,是指程序员未按照C语言的语法与格式编写,从而造成编译程序解读时产生的错误。Dev C++编译时会自动定位错误,并在下方显示出错误的信息,以便程序员可以清楚地知道错误的位置或者错误的语法,只要加以改正,再重新编译即可。图1-6所示为字母小写误用大写的语法错误。图1-6 C程序运行结果的范例

如果是逻辑上的错误,在编译时一般可以正常通过,但是在运行时无法得到预期的结果。对于这种错误类型,Dev C++没有办法直接告诉我们错误出现在哪里,因为我们所编写的程序代码完全符合C语言的规定,只是存在内在的逻辑错误,当然这种错误可能发生在任何环节中。面对这种逻辑错误,就要考验程序员的水平了,通常是将程序代码逐句确认,抽丝剥茧地找出问题所在。1-3 helloworld程序快速解析

事实上,无论程序有多么复杂,C程序的外观都和helloworld范例程序大同小异,只是程序代码不同而已。在尚未开始正式介绍C语言的语句之前,将针对helloworld范例程序中相关的语句或指令结构进行简单说明。注意在本书中的每行程序语句之前都有行号,这是为了便于书中的解说,大家不要把这些行号作为代码一起输入到自己的程序中,以免编译时发生错误。【范例:helloworld.c】01 #include 02 #include 03 04 int main(void)05 {06 int no;07 no=2;08 printf(There are %d pandas in Beijing.\n",no);09 /*输出北京有两只熊猫*/ 10 11 system("PAUSE");12 return 0;13 }1-3-1 头文件的作用

C语言是一种符合模块化(module)设计精神的语言,模块化最大的好处是内建了许多标准函数(function)供程序设计者使用。这些函数被分门别类地放置在扩展名为“.h”的不同头文件(header files)中。我们只要通过“#include”语句就可以将相关的头文件“包含”(include)到我们的程序中使用,而不用从头到尾自行编写,如范例helloworod.c中的01与02行:#include #include

大家看01行中的#include,就是把C语言中的标准输入输出函数的stdio.h文件“包含”进来。printf()函数就是定义在stdio.h文件中的,而system()函数包含在02行中的头文件中。表1-1列出了C语言中常见的内建头文件,以供大家参考。表1-1 C语言中常见的内建头文件“#include”语句的作用就是告诉编译程序要加入哪些C语言中所定义的头文件或指令。在C语言中,“#include”语句是一种预处理指令,并不是C语言的正式语句,所以不需要在语句最后加上“;”作为结束标志。当使用C语言所提供的内建头文件时,还必须用“<>”将其括住。如果大家使用的是自定义的头文件,就必须换成以“""”符号来括住。方式1:#include <内建头文件的名称>方式2:#include "自定义头文件的名称"

方式1用来加载内建头文件,而方式2用来加载程序设计者自行编写的头文件。例如,在A文件中要引用B文件时,就可以在A文件中加入自定义的头文件#include"B.c"。

大家可能会好奇这两种加载方式的不同。事实上,两者之间的差异就在于头文件的搜索路径不同。如果采用方式1的加载方式,编辑器就会去寻找系统默认的函数库目录,方式2则会先在当前的工作目录下寻找,找不到才会寻找系统默认的函数库目录。1-3-2 main()函数简介

首先大家要清楚一点,C程序本身就是由各种函数所组成的。所谓函数(function),就是执行特定功能的程序语句的集合。我们可以自行建立函数,或者直接使用C语言中内建的标准函数库,例如main()函数和printf()函数都是C语言所提供的标准函数。

main()函数是C语言中一个相当特殊的函数,代表所有C程序的开始进入点,也是唯一且必须使用main作为函数名称的函数。C程序开始运行时,不管是在程序代码中的任何位置,一定会先从main()函数开始执行,编译程序都会找到它,然后开始编译程序内容,因此main()函数又称为C语言的“主函数”。

一般来说,函数主体是以“{}”(一对大括号)定义的。在函数主体的程序段中,可以包含多行程序语句(statement),而每一条语句都要以“;”结尾。另外,程序段结束后必须以“}”(右大括号)告知编译程序,而且在“}”后无须加上“;”作为结尾。以main()函数来说,最简单的C程序可以如下定义:

C语言函数前的类型声明用来表示函数执行完成后的返回值类型,例如int main()表示返回值为整数类型。如果函数不返回值,就可以把数据类型设置为“void”。括号中使用void时代表这个函数没有任何需要传入或传出函数体的参数,也可以直接以“()”(空白括号)来表示。例如,可以声明成以下两种方式:void main(void);void main();

注意:在Dev C++集成编程环境中,我们无法声明函数返回值为void类型,在Dev C++中所有main()函数都必须声明为int类型,否则编译时就会发生错误。以下两种方式都可以在Dev C++中使用:int main(void);int main();

在此范例的main函数中,第08行调用了printf()内建函数。printf()就是C语言的输出函数,会将括号中“"”(引号)内的字符串输出到屏幕上,其中“/n”是转义字符的一种,具有换行的作用。在printf()函数中也使用到了“%d”格式,表示以十进制整数格式输出变量no的值,后面会有更详细的说明,在此大家先有个概念即可。

第12行的return语句用来表示函数是否有返回值,在函数定义中我们可以使用return语句来返回对应函数的整数值,如果返回0,就停止运行程序,并且将控制权还给操作系统。1-3-3 system()函数的作用

system()函数是C语言的一种内建函数,其功能相当有趣。我们不妨把第11行“system("PAUSE");”语句拿掉,再重新编译与运行一次,会发现运行界面一闪即逝,根本来不及看清楚运行的结果,原因是当程序在Windows系统中正常运行结束后,Windows会直接关掉C/C++的运行窗口。

在程序设计中要解决这种现象有两种方法,一种是直接使用命令行操作界面(DOS界面)来查看运行结果,另一种是加上第11行的“system("PAUSE");”。因为system()函数会调用系统参数PAUSE,并让程序运行到这条语句时先暂停,同时在运行窗口中显示“请按任意键继续…”等文字,当我们按任意键后程序才会继续往下执行。1-3-4 注释与缩排

在此特别要补充一点,虽然helloworld范例只是一个用于简单测试Dev C++功能的很小的程序,但是如果从小程序就能养成使用“注释”的好习惯,在日后编写程序时就能提供足够的注释说明,从而提高程序的可读性。

注释(comment)既可以帮助其他程序员了解程序的内容,也能够在日后进行程序维护与修订时省下不少时间成本。在C语言中,只要是在“/*”与“*/”之间的文字都属于注释内容。另外,注释也能够跨行使用。例如:

C程序是由一个或数个程序区块(block)所构成的。程序区块由“{}”组成,包含多行或单行语句,就像我们一般编写文章时的段落。除了加上注释外,编写程序和写作文一样,最后都希望能够段落分明,适当的缩排就可以达到这样的效果,区分出程序区块的层次。例如,主程序中包含子区段,或者子区段中又包含其他子区段时,就可以通过缩排来区分出程序代码的层次,让程序可读性更强。1-4 课后练习【问答与实践题】

1.美国国家标准协会为何要制定一个标准化的C语言?

2.在程序中使用函数的优点是什么?

3.什么是“集成开发环境”?

4.试说明main()函数的作用。

5.试说明如何在程序代码中使用标准链接库所提供的功能。

6.程序的错误按照性质可分为哪两种?

7.请问头文件的包含方式有哪两种?

8.请问下面的语句是否为一条合法的语句?printf("我的第一个程序!!\n"); system("pause"); return 0;

9.在Dev C++中,可否声明为void main()?

10.试说明C语言有哪些特色与优点。

11./**/除了用来作为注释之外,有些程序员还喜欢用它将不需要的程序片段暂时隐藏起来,而不被编译程序编译,但是下面这个程序出现了问题,请问错误在哪里?01 #include 02 int main(void){03 /*04 /*显示Hello! World!*/05 printf("Hello World!");06 */07 printf("哈喽!你好");08 return 0;09 }

12.为什么C语言也称为中级语言?

13.如果大家要使用自定义的头文件,语法是什么?【习题解答】

1.解答:随着C语言在不同操作平台上的发展,逐渐有不同的版本出现,它们的语法相近,却因为操作平台不同而不兼容。于是在1983年,美国国家标准协会开始着手制定一个标准化的C语言,以使同一份C语言程序代码能在不同平台上使用,而不需要重新改写。

2.解答:

①简化程序内容:从主程序中通过函数调用的方式执行各个函数中所定义的程序功能,简化了原本应编写在主程序中的程序内容。

②程序代码再用:不必每次重新编写相同的程序代码来执行同样的程序功能。

3.解答:所谓集成开发环境,就是把有关程序的编辑(Edit)、编译(Compile)、执行/运行(Execute/Run)与调试(Debug)等功能集成在同一个操作环境下,从而简化程序开发的步骤,让程序员只需通过单一集成的环境就可以完成轻松编写、调试和运行程序的工作。

4.解答:main()是一个相当特殊的函数,代表所有C程序的进入点,也是唯一且必须使用main作为函数名称的函数。也就是说,当程序开始运行时,一定会先运行main()函数,不管它在程序中的什么位置,编译程序都会找到它开始编译程序的内容,因此main()又称为“主函数”。

5.解答:在程序代码中使用标准链接库的功能,必须要先以预处理器指令#include来包含对应的头文件。

6.解答:(1)语法错误

这是在程序开发过程中最常发生的错误。语法错误在程序编译时会发生编译时错误,编译程序会将错误显示在“输出窗口”中,程序开发人员可以根据窗口上的提示迅速找出错误位置并加以修正。(2)逻辑错误

逻辑错误是程序中最难发现的“漏洞”(bug)。这类错误在编译时并不会出现任何错误信息,必须要靠程序开发人员自行判断,与程序开发人员的专业素养、经验和细心程度有着密不可分的关系。例如,薪资的计算公式、财务报表等都必须在开发过程中以数据进行实际测试,以确保日后程序运行结果的准确性和精确性。

7.解答:根据头文件所在路径的不同有两种包含方式:一种是以一组“<>”符号来包含编译环境默认路径下的头文件,另一种是以一组“""”来包含与源代码相同路径下的头文件。

8.解答:是,因为C语言的程序编写采用自由格式。

9.解答:虽然语法逻辑正确,但是有些系统不能通过编译,例如本书所使用的Dev C++就不行,所有main()函数都必须声明为int类型。

10.解答:程序可移植性高,具有跨平台能力,体积小且运行效率高,具有底层处理能力、可作为学习其他语言的基础。此外,C语言本身可以直接处理底层的内存,甚至可以处理位逻辑运算。所能实现的功能不仅用于开发软件包,硬件驱动程序、网络协议以及嵌入式系统等也都可以用C语言实现。

11.解答:/**/注释不可以使用嵌套的方式,所以在第4行的/*作用前,第3行的/*必须先对应一个*/。

12.解答:C语言不但具有高级语言的亲和力(例如C的语法让人容易理解、可读性强,相当接近人类的习惯用语),而且在C语言的程序代码中允许开发者加入低级的汇编程序,使得C程序更易于与硬件系统直接沟通,因而被称为中级语言。

13.解答:#include"自定义头文件的名称"。第2章变量与常数

计算机主要的功能就是强大的运算能力,基本过程就是将从外界得到的数据输入计算机,并通过程序来进行运算,最后输出所要的结果。当程序运行时,外界的数据进入计算机后要有个栖身之处,这时系统会分配一个内存空间给这份数据。在程序代码中,我们所定义的变量(Variable)与常数(Constant)扮演的就是这样的角色。

变量与常数主要用来存储程序中的数据,以便程序进行各种运算。无论是变量还是常数,必须事先声明一个对应的数据类型(data type),并在内存中保留一块区域供其使用。两者之间最大的差别在于变量的值是可以改变的,而常数的值是固定不变的,如图2-1所示。图2-1 变量和常数在内存中存储的示意图

我们可以把计算机的主存储器(内存)想象成一个豪华旅馆、外部数据当成来住房的旅客,旅馆的房间有不同的等级,就像属于不同的数据类型,最贵的等级价格自然高,不过房间也较大,就像有些数据类型所占内存空间的字节数较多。

定义变量就像向C系统要房间,这个房间的房号就是内存中的地址,房间的等级就是数据的类型,当然这个房间的客人是可以变动的。而常数就像是被长期租用的房间,不可以再变更住客,除非这个程序运行结束。2-1 认识变量

变量是程序设计语言中不可或缺的部分,代表可变更数据的内存空间。变量声明的作用在于告知计算机所声明的变量需要多少内存空间。C语言属于一种强类型(strongly typed)语言,当声明变量时,必须以数据类型作为声明变量的依据,同时要设好变量的名称。基本上,变量具备4个形成要素,如图2-2所示。图2-2 变量的4个要素(1)名称:变量在程序中的名字,必须符合C语言中标识符的命名规则及可读性。(2)值:程序中变量所赋予的值。(3)引用位置:变量在内存中存储的位置。(4)属性:变量在程序中的数据类型,如整数、浮点数或字符。2-1-1 变量命名原则

在C语言的程序代码中所看到的代号,通常不是标识符(IDentifier)就是关键字(Keyword)。在真实世界中,每个人、事及物都有一个名称,程序设计也不例外,标识符包括变量、常数、函数、结构、联合、枚举等代号(由英文大小写字母、数字或下划线组合而成),例如helloworld范例中的no、printf、system都属于标识符。至于关键字,就是具有语法功能的保留字,所有程序员自行定义的标识符都不能与关键字相同,在ANSI C中共定义了表2-1所示的32个关键字,在Dev C++中会以粗黑体字来显示这些关键字,如helloworld程序中的int、void、return就是关键字。表2-1 ANSI C中定义的32个关键字

基本上,变量名称都是由程序设计者自行定义的,为了考虑程序的可读性,大家最好以符合变量赋予的功能与意义来给变量命名,例如总和取名为“sum”、薪资取名为“salary”等,程序规模越大越重要。变量属于标识符的一种,必须遵守以下基本规则:(1)变量名称开头可以是英文字母或下划线,但不可以是数字,名称中间也不可以有空白。(2)变量名称中间可以有下划线,例如int_age,但是不可以使用-、*、$、@、…等符号。(3)变量名称长度不可超过127个字符,另外根据ANSI C标准(C99标准),只有前面63个字符被视为变量的有效名称,后面的64个字符会被舍弃。(4)变量名称必须区分字母的大小写,例如Tom与TOM会视为两个不同的变量。(5)不可使用关键字(Keyword)或与内建函数名称相同的名字。

为了程序可读性,建议对于一般变量进行声明时以小写字母开头,例如name、address等,而常数最好以大写字母开头并配合“_”(下划线),如PI、MAX_SIZE。

至于函数名称,习惯以小写字母开头,如果由多个英文单词组成,那么其他英文单词的开头字母为大写,如copyWord、calSalary等。下面对合法与不合法的变量名称进行比较。2-1-2 变量的声明

由于变量的值可以改变,因此不同数据类型的变量所使用的内存空间大小以及可表示的数据范围有所不同。在程序设计语言中,有关变量存储地址的方法有两种,如表2-2所示。表2-2 变量存储地址的方法

由于C语言属于“静态内存分配”(Static Storage Allocation,或称为静态存储器分配)的程序设计语言,必须在编译时分配内存空间给变量,因此C语言的变量必须先声明再使用。正确的变量声明由数据类型加上变量名称与分号构成,语法如下:数据类型 变量名称1, 变量名称2, …… , 变量名称n;变量名称1=初始值1;变量名称2=初始值2;……

我们知道在C语言中共有整数(int)、浮点数(float)、双精度浮点数(double)以及字符(char)四种基本数据类型可用于变量声明,关于这些数据类型的细节会在后面的章节中进行介绍。

例如,声明整数类型的变量var1如下:int var1;var1=100;

以上这两行程序代码类似于我们到餐厅订位,先预定var1的位置(具有4个字节的整数空间),但是不确定这个地址上的数值是什么,只是先把它保留下来。如果变量设置初始值为100,就会将100放入这4个字节的整数空间。【范例:CH02_01.c】

在声明变量的同时可自行决定是否要赋予初值。如果尚未设置初值就直接输出变量的内容,通常会打印出无法预料的数字。01 #include 02 #include 03 04 int main()05 {06 int a;07 int b=12;08 float _c=117.12345;09 10 printf("变量a=%d\n",a); /*打印出未初始化的a值*/11 printf("变量b=%d\n",b); /*打印出已初始化的b值*/12 printf("变量_c=%f\n",_c);/*打印出已初始化的_c值*/13 14 system("pause");15 return 0;16 }

运行结果如图2-3所示。图2-3 范例程序CH02_01.c的运行结果【程序说明】

第6~8行:声明了3个变量,其中a变量并未设置初始值。

第10行:输出a时会在屏幕上发现a=0。若显示的不是0也很正常,因为系统并未清除原先地址上的内容或值,出现的是先前存放的数值。因此,建议在声明变量后最好能同时设置初始值。

以上示范是声明变量后再设置值,当然也可以在声明时同步设置初值,语法如下:数据类型 变量名称1=初始值1;数据类型 变量名称2=初始值2;数据类型 变量名称3=初始值3;…

例如,声明两个整数变量num1、num2,其中int为C语言中整数声明的关键字:int num1=30;int num2=77;

这时C语言会分别自动分配4个字节的内存空间给变量num1和num2,它们的存储值分别为30和77。当程序运行过程中需要存取这块内存时,就可以直接使用变量名称num1与num2进行存取,如图2-4所示。图2-4 C语言自动分配内存和设置初值的示意图

如果要一次声明多个相同数据类型的变量,可以使用“,”隔开变量名称。为了养成良好的编写程序习惯,变量声明部分最好放在程序代码的开头,也就是紧接在“{”符号后声明(如main函数或其他函数)。例如:int a,b,c; int total =5000; /* int为声明整数的关键字 */float x,y,z;int month, year=2003, day=10;2-2 变量的作用域

变量除了有可变动的特性,在程序中不同的位置声明也会有不同的生命周期。我们知道语句(statement,或称为指令)是C语言最基本的执行单位,每一行语句都必须加上“;”作为结束。在C程序中,可以使用“{}”将多个语句包围起来,形式如下:{ 程序语句; 程序语句; 程序语句;}

以上程序代码以大括号“包围”的多行语句称为程序区块(statement block,或称为语句区块)。变量作用域(或称变量的有效范围)是根据变量所在的位置决定的,也就是用来判断在程序中有哪些程序区块中的语句(Statement)可以合法使用这个变量。在C语言中,变量的作用域通常可分为三个层次:全局变量(Global Variable)、局部变量(Local Variable)与区块变量(Block Variable)。2-2-1 全局变量

全局变量是指在主函数main()外声明的变量,在整个程序中任何位置的语句都可以合法使用这种变量。简单来说,声明在程序区块与函数外,且在声明语句以下的所有函数和程序区块都可以使用全局变量。通常全局变量用来定义一些不会经常改变的数值,不过初学者不应该为了方便而将所有变量都设置为全局变量,否则将来会发生变量名称管理上的问题,全局变量的生命周期始于程序开始之时,终于程序运行结束之后。float pi=3.14; /* pi是全局变量 */int main(){… …}2-2-2 局部变量

局部变量是指在函数内声明的变量,或者声明在参数行中的变量,作用域只在声明的函数区块中,其他函数不可以使用这种变量。局部变量的生命周期开始于函数被调用之后,终止于该函数运行完毕之时。void circle(){ float pi=3.14; /* pi是circle()函数中的局部变量 */}int main(){… …}2-2-3 区块变量

区块变量是指在某个程序区块中声明的变量,也是局部变量的一种,不过作用域更小。在某些程序代码区块中声明的变量有效范围仅在此区块中,此程序区块以外的程序代码都不能使用这个变量。{ /*在此区块中声明一个变量sum,有效范围仅在此“程序区块”内*/ int sum ; ...}【范例:CH02_02.c】

在这个范例程序中,我们在不同的位置声明salary变量,这个变量的生命周期有不同的意义,尤其当区块变量与全局变量同名时,以区块变量优先,大家可以仔细观察与比较。不过全局变量与区块变量同名很容易引起混淆,影响程序的可读性,大家在编写程序时最好避免这种情况。01 #include02 #include03 04 int salary=17500;/* 声明salary为全局变量 */ 05 06 int main()07 {08 09 printf("salary=%d\n",salary);10 {11 int salary=22000;/* 在此声明salary为区块变量 */ 12 printf("salary=%d\n",salary);13 }14 printf("salary=%d\n",salary);15 16 system("pause");17 return 0;18 }

运行结果如图2-5所示。图2-5 范例程序CH02_02.c的运行结果【程序说明】

第4行:声明salary为全局变量,在整个程序中任何位置的语句都可以合法使用该变量。

第9行:输出全局变量salary的值。

第11行:声明salary为区块变量。

第12行:输出区块变量salary的值。

第14行:因为离开了程序区块,所以又将输出全局变量salary的值。2-3 常数

前面谈的变量可以在程序运行过程中改变其值,常数在程序运行时会固定不变。例如,10、-568、0、5000等是整数常数,3.1416、0.001、82.51等是浮点数常数。如果是字符常数,就必须以单引号“''”括住字符(如'a''c');如果数据类型为字符串,就必须以双引号“""”括住字符串,例如"程序设计""Happy Birthday"等。2-3-1 常数命名规则

常数在程序中的应用也和变量一样,可以用一个标识符来表示,唯一的不同之处在于这个标识符所代表的数据值在此程序运行时是绝对无法改变的。例如,一个计算圆面积的程序,其中的PI值就可以使用常数标识符来表示。

通常有两种定义方式,标识符的命名规则与变量相同,习惯上会以大写英文字母来定义名称。这样不但可以增加程序的可读性,而且对程序的调试与维护有帮助。

·方式1:#define常数名称常数值

使用宏指令#define来声明。所谓宏(Macro),又称为“替换指令”,主要功能是以简单的名称取代某些特定常数、字符串或函数,善用宏可以节省不少程序开发的时间。由于#define为一种宏指令,并不是赋值语句,因此不用加上“=”与“;”。例如,定义常数的方式如下:#define PI 3.14159

当使用#define定义常数时,程序会在编译前先调用宏处理程序(Macro Processor),用宏的内容来取代所定义的标识符,然后进行编译的操作。简单来说,就是将程序中所有PI出现的部分都替换成3.14159,这就是使用宏指令的特点。【范例:CH02_03.c】

下面的范例程序说明如何以#define形式声明常数。与一般的指令不同,无须声明标识符的数据类型和使用“=”赋值符号,通常是将其加在程序最前端的预处理指令区。01 #include02 #include03 04 #define PI 3.14159 /*声明PI为3.14159*/ 05 06 int main()07 { 08 09 float radius =5.0,Area; /*声明与设置圆半径 */ 10 11 Area=radius*radius*PI; /* 计算圆面积 */ 12 13 printf("圆的半径为=%f ,面积为=%f \n",radius,Area); 14 15 system("pause"); 16 return 0;17 }

运行结果如图2-6所示。图2-6 范例程序CH02_03.c的运行结果【程序说明】

第4行:使用#define声明PI为3.14159,声明后程序中所有出现PI的部分都代表常数值3.14159,指令结束时也不用加分号。

第11行:计算圆面积的公式。

·方式2:const数据类型常数名称=常数值;

使用const保留修饰词来声明与设置常数标识符名称之后的数值,其实还是将所声明的变量进行限制,即在运行中都无法改变其数值。如果声明时并未设置初值,之后也就不能设置数值了。使用const保留字定义常数的方式如下:const float PI=3.14159;【范例:CH02_04.c】

在下面的范例程序中,我们要特别说明,在使用#define来定义常数时,其生命周期一直到这个程序运行结束,或使用到取消定义(undefined)为止。而const所定义的常数还有其生命范围的问题,例如在main函数中声明了一个const类型的常数salary,但如果在函数程序区块中也声明了一个const类型的常数salary,就可以改变其值。请大家注意,如果第10行中把const int拿掉,只有salary=17500,即要修改由const声明后的变量值,那么在编译时就会出现报错的信息。01 #include02 #include03 04 int main()05 {06 const int salary=25000;/* 声明salary为常数 */ 07 08 printf("salary=%d\n",salary);09 {10 const int salary=17500;/* 在此程序区块中声明salary为常数 */ 11 printf("salary=%d\n",salary);12 }13 14 printf("salary=%d\n",salary);15 16 system("pause");17 return 0;18 }

运行结果如图2-7所示。图2-7 范例程序CH02_04.c的运行结果【程序说明】

第6行:声明salary为常数。

第10行:在此程序区块中声明salary为常数。

第11、14行:这两行输出的salary值并不相同,一个为局部常数,一个为全局常数。2-4 课后练习【问答与实践题】

1.什么是变量,什么是常数?

2.请问程序设计习惯与变量或常数的存储长度有何关系?

3.试简述变量命名必须遵守哪些规则。

4.变量具备哪4个形成要素?

5.变量存储地址的方法有哪两种?

6.试说明区块变量的意义及特性。

7.当使用#define来定义常数时,程序会在编译前先进行哪些操作?

8.C语言的字符常数与字符串必须如何表示?

9.简介动态内存分配法。

10.什么是关键字?【习题解答】

1.解答:变量代表计算机中的一个内存存储位置,供用户设置数据并存储数据,其数值可变更,因此被称为“变量”。常数是在声明要使用内存位置的同时就已经给予固定的数据类型和数值,在程序运行中其数值不能做任何变动。

2.解答:一个好的程序设计习惯要学会充分考虑程序代码中变量或常数的存储长度。当使用较多字节存储时,优点是有更高的有效位数,缺点是会影响程序执行的性能。

3.解答:(1)变量名称必须由“英文字母”“数字”或“_”(下划线)组成,开头字符可以是英文字母或下划线,但不可以是数字。(2)变量名称中间可以有下划线,但是不可以使用-、*、$、@、…等符号。(3)变量名称区分大小写字母,例如Ave与AVE会视为两个不同的变量。(4)不可使用保留字或与函数名称相同的名字。

4.解答:(1)名称:变量在程序中的名字,必须符合标识符的命名规则及可读性。(2)值:程序中变量所赋予的值。(3)引用位置:变量在内存中存储的位置。(4)属性:变量在程序中的数据类型,如整数、浮点数或字符。

5.解答:

6.解答:区块变量是指声明在某个程序区块中的变量,也是局部变量的一种。在程序代码区块中所声明的变量,有效范围仅在此程序代码区块中,此程序代码区块以外的程序代码都不能引用该变量。

7.解答:当使用#define来定义常数时,程序会在编译前先调用宏处理程序,用宏的内容来替换宏所定义的标识符,然后才进行编译的操作。

8.如果是字符常数,就必须用单引号“''”括住字符,例如'a''c'。如果数据类型为字符串,就必须用双引号“""”括住字符串,例如"程序设计""Happy Birthday"等。

9.解答:变量内存分配的过程是在程序运行时进行的,如BASIC、Visual Basic、Lisp语言等。运行时才确定变量的类型称为“动态检查”,变量的类型与名称可在运行时随时改变。

10.解答:关键字是具有语法功能的保留字,程序员自行定义的标识符不能与关键字相同。第3章C语言的基本数据类型

C语言属于一种强类型语言,在声明变量时必须指定数据类型。C语言的基本数据类型有整数、浮点数和字符3种。数据类型在程序设计语言的定义中包含两个必备的层次,即规范性(specification)和实现性(implementation)。规范性包括数据属性,代表数值与该属性可能进行的各种运算。实现性包括数据的内存描述、数据类型的运算以及数据对象的存储器描述。3-1 认识基本数据类型

对于程序设计语言来说,不有基本数据类型的集合,还允许程序员定义更具有可读性的派生数据类型。由于数据类型各不相同,在存储时所需要的容量也不一样,因此必须分配不同大小的内存空间存储。下面分别介绍C语言中的整数、浮点数、字符3种基本数据类型以及转义字符。3-1-1 整数

C语言的整数(int)和数学上的意义相同,存储方式会保留4个字节(32位,即32比特)的空间,例如-1、-2、-100、0、1、2、1005等。在声明变量或常数数据类型时,可以同时设置初值,也可以不设置初值。在设置初值时,这个初值可以是十进制数、八进制数或十六进制数。

在C语言中,表示八进制数时必须在数值前加上数字0(例如073,也就是表示成十进制数的59)。在数值前加上“0x”或“0X”是C语言中十六进制数的表示法。例如,将no变量设置为整数80可以采用下列3种不同进制的方式表示:int no=80; /* 十进制表示法 */int no=0120; /* 八进制表示法 */int no=0x50; /* 十六进制表示法 */

此外,C语言的整数类型还可按照short、long、signed和unsigned修饰词来进行不同程度的定义。一个好的程序员首先应该学习控制程序运行时所占有的内存容量,原则就是“当省则省”,例如有些变量的数据值很小,声明为int类型要花费4个字节,但是加上short修饰词就会缩小到2个字节,能够节省内存,不要小看节省的2个字节,对于一个大型程序而言,能够积少成多。short int no=58;

long修饰词的作用正好相反,表示长整数。我们知道不同的数据类型所占内存空间的大小是不同的,往往也会因为计算机硬件与编译程序的位数不同而有所差异。在16位的系统下(如DOS、Turbo C),int的长度为2个字节,不过当一个整数声明为long int时,它的数据长度为4个字节,为之前的2倍。

如果读者所选的编译程序为32位(如Dev C++、Visual C++等),int数据类型会占用4个字节,而long int数据类型也是4个字节。简单来说,在目前的Dev C++系统下,声明int或long int所占据内存空间的大小是相同的。类型所占内存空间的字节数越大,代表可表示的数值范围越大。表3-1所示为C语言中各种整数类型的声明、数据长度以及数值范围。表3-1 C语言中各种整数类型的声明、数据长度以及数值范围

在C语言中,我们可以使用sizeof()函数来显示各种数据类型声明后的数据长度,这个函数就放在stdio.h头文件中。使用格式如下:sizeof(标识符名称);

接下来介绍有符号整数(signed),就是有正负号之分的整数。在数据类型之前加上signed修饰词,该变量就可以存储具有正负符号的数据。如果省略signed修饰词,编译程序会将该变量视为有符号整数。这种修饰词看起来有些多余,在程序中的用途其实是为了增加可读性。声明整数类型变量的数值范围只能在-2147483648和2147483647之间,例如:signed int no=58;

不过,如果在数据类型前加上另一种无符号整数(unsigned)修饰词,该变量只能存储正整数的数据(例如公司的员工人数,总不能是负的),那么它的数值范围中就能够表示更多的正整数。声明这种类型的unsigned int变量数据值,范围会变成在0到4294967295之间,例如:unsigned int no=58;

此外,英文字母“U”“u”与“L”“l”可直接放在整数常数后标示其为无符号整数(unsigned)和长整数(long)数据类型,例如:45U、45u /* 45为无符号整数 */45L、45l /* 45为长整数 */45UL、45UL /* 45为无符号长整数 */【范例:CH03_01.c】

我们知道整数的修饰词能够限制整数变量的数值范围,如果超过限定的范围就会“溢出”。下面的范例程序将分别设置两个无符号短整数变量s1、s2,请大家观察溢出后的输出结果。01 #include 02 #include 03 04 int main()05 {06 07 unsigned short int s1=-1;/* 超过无符号短整数的下限值 */ 08 short int s2=32768; /* 超过短整数的上限值 */ 09 10 11 printf("s1=%d\n",s1); 12 printf("s2=%d\n",s2); 13 14 system("pause");15 return 0;16 }

运行结果如图3-1所示。图3-1 范例程序CH03_01.c的运行结果

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载