Chinaunix首页 | 论坛 | 博客
  • 博客访问: 172797
  • 博文数量: 41
  • 博客积分: 1679
  • 博客等级: 上尉
  • 技术积分: 730
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-24 10:24
文章分类

全部博文(41)

文章存档

2011年(34)

2010年(7)

分类: C/C++

2011-08-19 17:42:58

第2章  通过例子学习

学习目标

  • 通过阅读简单的例子来初步了解C语言的结构。
  • 理解库作为简化程序设计过程的工具盒的重要性,并能运用库函数完成简单的输入和输出。
  • 认识简单程序的三个组成部分:输入、计算、输出。
  • 理解程序中变量用于保存数据的作用。
  • 了解不同的数据类型,包括int、double、string。
  • 能够利用算术表达式执行指定的简单计算。
  • 理解数字转换的过程。
  • 能够通过修改现有的程序得到新程序。
本书目的是讲述程序设计的基本原理。在此过程中,读者将会逐渐熟悉一门叫做C语言的程序设计语言,但C语言的细节并不是本书的重点。程序设计是一门用计算机解决问题的科学。本书所讲述的大部分知识与C语言的特定细节无关。即便如此,最终也应掌握许多C语言的细节,以便能最大限度地利用C语言所提供的工具。
从一个程序设计初学者的角度来考虑,既要理解抽象的程序设计概念,又需要在一定程度上了解一门程序设计语言的细节,这常常使人陷入一个两难的境地:找不到合适的着手点。要学习程序设计,就需要写一些相当复杂的程序。为了用C语言编写程序,就必须对这门语言有足够的了解,以便恰当地使用一些工具。但如果将全部精力投入到学习C语言上,那么在学习程序设计的通用方法方面将会事倍功半。此外,C语言并非为初学者而设计。若对程序设计一无所知而试图精通C语言,那么将会被C语言的细节所困扰,最终导致只见树木不见森林的结果。
在掌握程序设计的错综复杂的内容之前,对什么是程序设计有一个感性认识很重要,因此本章开头举出一些完整的简单程序。试着从整体上理解这些程序而不要拘泥于细节。这些细节将在第4章中讲述。本章和下一章的主要目的在于帮助读者建立起对程序设计和问题解决的直观认识。从长远看,这比学习具体的细节重要得多。

2.1   “Hello world”程序
为纪念C语言的设计者,第一个程序范例选自C语言的定义文档—Brian Kernighan和Dennis Ritchie合著的The C Programming Language。这个范例就是“Hello world”程序,它是所有C程序员共有的财富,而你也即将成为其中的一员。程序的文本见图2-1。

图2-1   hello.c
该程序本身作为一个文件存储在你所用的计算机系统的永久存储器中。文件名为hello.c,其中.c说明该文件为C语言程序。
如图2-1所示,hello.c程序分为三个部分:程序注释、库包含列表和主程序。尽管其结构非常简单,但它是下面几章将介绍的所有程序的典型,应将其作为C语言程序组织的范例。

2.1.1   注释
hello.c程序的第一部分只是一段英文注释,描述该程序的作用。在C语言中,注释(comment)是在“/*”与“*/”之间所有的文字,可以占连续的几行。在hello.c程序中,注释从第一行的/*开始,在第八行的*/后结束。
注释是写给人看的,而不是写给计算机的。他们向其他程序员传递该程序的有关信息。当C语言编译器将程序转换为可由机器执行的形式时,注释被完全忽略。
本书中的每一个程序都以一个专门的、从整体上描述程序操作过程的注释开头,这段注释称为程序注释(program comment)。它包括程序文件的名称和一些描述程序操作的信息。本例中的程序注释还说明了程序的来源。注释还可以描述程序中特别复杂的部分,指出可能的使用者,对如何改变程序行为提出一些建议等等。像hello.c这样简单的程序通常不需要很多的注释。但当程序越来越复杂时,读者就会发现给出合适的注释是使程序易读的最好方法之一。

2.1.2   库包含
程序的第二部分由以下两行组成:
  1. #include <stdio.h>
  2. #include "genlib.h"
这两行说明该程序使用了两个库。库(library)是一种工具的集合,这些工具由其他程序员编写,用于执行特定的功能。hello.c程序使用的库是由ANSI C提供的标准输入输出库(stdio)和专为本书设计的通用库(genlib)。本书的每个程序都会用到这两个库,也就是说,每个程序的程序注释结束后都会立即出现这两行。某些程序还会用其他的库,这些程序必须对每一个库使用一行#include。
读者自己编写程序时,可以使用这些库提供的工具,从而省去自己编写这些工具的麻烦。库对于程序设计来说是十分重要的,当读者开始编写一些更为复杂的程序时,你将马上依赖一些重要的库。
然而要使用一个库,就必须在程序中给出足够的信息,以便编译器知道库里有哪些工具可用。在大多数情况下,这些信息以头文件(header file)的形式提供,这种文件为编译器提供那个库所提供的工具的描述。例如,stdio.h是一个头文件的名称,它定义了标准输入输出库的内容。同样,genlib.h也是一个头文件的名称,它定义了通用库的内容。每个文件名中的.h说明这是一个头文件,就像hello.c文件中的.c说明它是一个C语言程序一样。头文件中的内容将在第7章和第8章中详细讨论。
注意,两个#include行使用的标点符号不同:
  1. #include <stdio.h>
  2. #include "genlib.h"
stdio库是使用ANSI C时总能获取的标准库,标准库用尖括号标记,所以可以编写以下语句包含标准库stdio:
  1. #include <stdio.h>
个人编写的库以及本书所用的扩展库用引号标明。由于genlib库是扩展库之一,于是#include行被写为:
  1. #include "genlib.h"
本书在介绍每个新的库时,都将在相应的#include行中使用适当的标点符号,以便读者了解该库是如何得来的。

2.1.3   主程序
图2-1所示的hello.c文件的最后一部分是程序主体,它由以下几行组成:
  1. main()
  2. {
  3.     printf ("Hello, world.\n");
  4. }
这四行是C语言中函数的第一个例子。函数(function)是一系列独立的程序步骤,将这些程序步骤集合在一起,并赋予一个名字,就形成了一个函数。该函数的名字(如第一行所示)为main。函数所执行的步骤在大括号中列出,这些步骤称为语句(statement)。这些语句共同组成函数的主体(body)。hello.c中的main函数只有一个语句,但大多数函数都有几个连续执行的语句。
当运行C语言程序时,计算机执行main函数主体中包含的语句,每个完整的C程序中都必须有这个函数。在hello.c中,main的主体由语句
  1. printf("Hello, world.\n");
组成。该语句用到了库函数printf,这个函数是标准输入输出库中的工具,只要程序员在程序的前面写过语句
  1. #include <stdio.h>
就可用printf函数。
但printf的作用是什么?和main一样,printf也是个函数,其名称printf代表一组操作。当想要调用这些操作时,只要使用其函数名就可以一起引用这些函数。在程序设计中,通过使用函数名来调用该函数的行为称为调用(calling)函数。hello.c程序中的语句
printf ("Hello, world.\n");
就是对函数printf的调用。
调用一个函数时,常常要提供一些额外的信息。例如,在C语言中,printf是一个在屏幕上显示数据的函数。但应该显示什么数据呢?这些额外信息由一组出现在函数名后的括号内的参数说明。参数(argument)是一个函数的调用程序提供给函数的信息。此处,printf被赋予了一个参数,它是一个列于引号中的一串字符,即字符串(string)
  1. "hello, world.\n"
该字符串是程序设计语言中数据的第一个例子。C语言中有许多不同类型的数据,应该特别注意如何使用数据的问题。现阶段只需将数据(data)看做程序所操作的信息:所有要显示的信息、用户要求的输入、作为计算结果传递的数值或计算过程的中间结果。
在本程序中,main函数中的语句通知库函数printf显示字符串中的所有字符,这些字符作为参数传入printf中。函数printf尽责地逐个显示H、e、l等等,直到屏幕上出现如下所示的完整消息。

字符串中最后一个字符为特殊字符,称作换行字符,用\n表示。当函数printf到达句末的句点时,光标停留于文本的末尾的句点后。若想扩展程序使之显示更多的信息,也许会想在每个新信息开始时另起一行。换行字符(newline)使其成为可能,该字符在所有的计算机系统中都进行了定义。当函数printf处理换行字符时,屏幕上的光标移至下一行的起始处,就像敲击了键盘上的Return键一样(有的计算机将该键标为Enter)。在C语言中,程序必须包含换行字符以标记每一行的结尾,否则所有的输出结果将不分行地显示在一起。

2.2   两个数的加法程序
为使读者对C语言程序的工作过程有更好的了解,我们来看一个稍复杂一些的例子。图2-2所示的add2.c程序要求用户输入两个数字,将其相加并显示总和。
add2.c程序中有一些hello.c中没有的概念。首先,add2.c用到了一个新的库—simpio,即简单输入输出库。该库是本书所使用的扩展库,因此在#include行使用引号,如同genlib一样。
  1. #include "simpio.h"
另一个值得特别注意的新特点出现在main函数的第一行:
  1. int n1, n2, total;
这一行是变量声明的第一个例子。在程序中,变量(variable)是一些在编写程序时值未知的数据的存放处。例如,在编写两个数的加法程序时,程序员尚不知道用户要将哪两个数相加。当程序运行时,用户才会输入两个数。为了在程序中引用这些目前尚未确定的数,可创建一个变量来保存这些需要记住的值,并给该变量命名。一旦要用到它包含的值时,可使用其变量名。变量的名称要用心选择,以便将来阅读程序的程序员能够容易地分辨出每个变量的作用。在程序add2.c中,变量n1和n2代表两个加数,变量total代表总和。

图2-2   add2.c
在C语言中,使用变量之前,必须先声明该变量。声明(declaring)一个变量就是告知C编译器引用了一个新的变量名,并指定了该变量可以保存的数据类型。例如,在程序add2.c中
  1. int n1, n2, total;
这一行声明了三个变量:n1、n2、total,并告知编译器每个变量中保存一个整型值。类型名int表示整型(integer),即没有小数部分的数。变量和声明将在本章的2.5.2节中详细介绍。
和任何程序一样,add2.c的运行也是通过执行main函数主体中的每一条语句来实现的。add2.c中的第一个语句和hello.c中组成整个程序主体的语句类似:
  1. printf ("This program adds two numbers.\n");
当执行该语句时,计算机仅在屏幕上显示如下消息:

并将光标(用竖线表示)移至下一行的起始处。该消息说明了程序的作用。
显示完介绍消息后,余下的部分可分为三个阶段:
1) 输入阶段:计算机要求用户输入将要相加的两个数。
2) 计算阶段:程序计算总和。
3) 输出阶段:程序在屏幕上显示计算结果。

2.2.1   输入阶段
在输入阶段,计算机必须要求用户输入两个加数并分别保存在变量n1和n2中。每个加数的输入过程包括两步。首先,程序应在屏幕上显示一个消息以使用户了解程序需要什么,这种类型的消息通常称为提示消息(prompt)。和向用户显示的其他消息一样,可使用printf来显示提示消息和其他消息,如下所示:
  1. printf ("1st number?");
注意,这里在传递给printf的参数字符串后没有换行字符。省略换行字符意味着光标将停在显示的文本后面,紧接在问号之后,如下面的运行示例所示:

行末的光标提示用户输入一个所需的数值,而提示消息则提示应输入什么样的值。大多数情况下,用于显示输出数据的printf函数调用需要用到换行字符,用于显示输入数据提示消息的printf函数则不需要使用换行字符。
为了读取数据,程序可以采用如下语句:
  1. n1=GetInteger();
该语句是一个极为重要的程序结构的实例,该结构称为赋值语句。在C语言中,赋值语句(assignment statement)将等号右边的数值存储于等号左边的变量中。在本例中,赋值语句的右边是对函数GetInteger的调用,左边是变量n1。
函数GetInteger是simpio库的一部分,用于从用户处读入整数。调用函数GetInteger时,程序等待用户用键盘输入一个完整的数值。用户输入完毕并按下回车键后,该数值作为函数GetInteger的结果返回主程序。在程序设计的术语中,称GetInteger返回(return)用户键入的数值。总的来说,这个赋值语句的作用就是调用GetInteger函数,让用户输入数值,并最终将GetInteger返回的数值存储于变量n1中。
仔细回顾以下语句的执行是很有好处的:
  1. printf ("1st number?");
  2. n1=GetInteger();
第一条语句仅在屏幕上显示特定的提示消息,光标停留在该行的末尾。计算机接下来执行语句
  1. n1=GetInteger();
作为GetInteger函数调用的一部分,程序等待用户键入一个数字值,并将该数字值解释为整型值。例如,输入2时,屏幕的显示如下面的运行示例所示。

在纸上跟踪程序的操作过程时,程序员通常使用一个简单的方框图形表示已将一个特定的值赋给一个变量。每个变量对应于图中的一个方框。每个方框有一个名字和一个值,方框的名字在函数运行过程中始终不变,当新的值存储到该变量中时,方框中的值随之改变。为表明赋值语句已将数值2存储于变量n1中,就要画出一个方框,命名为n1,并在框中写2以表示该变量的值,如右图所示。

读取第一个数后,程序重复同样的基本步骤来读取第二个数:
  1. printf ("2nd number?");
  2. n2=GetInteger();
例如,若第二个数为3,则屏幕上将显示

于是可将两个变量用下图所示的形式表示。


2.2.2   计算阶段
程序的计算阶段由计算出两个数的和组成。在程序设计中,计算是通过写一个表达式来指定的,该表达式指定了必需的操作步骤。表达式的结果由赋值语句存储于一个变量中,以便程序后面的部分使用该结果。本章后面的部分将详细定义表达式的结构。然而即使没有一个完整的定义,理解C语言的表达式如何工作也是很容易的,因为它们看上去与传统的数学表达式非常类似。
add2.c程序的目的是将存储在变量n1和n2中的数值相加。为了做到这一点,需要使用运算符“+”,这与基本算术运算相似。为了记录结果,需要将结果存储在为此而声明的变量total中。执行这些操作的赋值语句是:
  1. total=n1+n2;
和C语言中的任何赋值语句一样,计算机计算等号右边表达式的值,并将结果存储到表达式左边的变量中。这里的赋值语句的作用是将变量n1和n2中存储的两个值相加,并将结果存储到变量total中。

2.2.3   输出阶段
程序的输出阶段由显示计算结果组成。和其他的输出操作一样,结果的显示是使用printf函数来完成的。然而,此时有一个新的符号出现。程序add2.c的最后一个语句是:
  1. printf ("The total is %d.\n", total);
和以前一样,printf函数在屏幕上显示参数字符串中的每一个字符。但到了百分号(%)处就有所不同了。%及其后面的字母称为格式码(format code)。在本例中,格式码为%d。printf函数的格式码的作用就是作为值的占位符,在输出过程中值将被插入到该位置。格式码中的字母用于指定输出格式。本例中的格式码%d表示输出结果应显示为十进制整数。此时的程序将显示以下信息:

其中,下划线部分将由一个十进制整数代替。
要想知道显示的是什么样的整数,printf函数取调用时传来的第二个参数值,此处是变量total。它的值显示在屏幕上,换行符使光标移至下一行。最后一行加上之前已显示于屏幕上的信息就构成了程序add2.c的一个完整的运行示例:

printf函数可将任何数值作为输出的一部分显示出来。若想将一个整数作为输出的一部分,就应该在printf函数调用的第一个参数中包含格式代码%d。将要显示的实际值可以作为printf的另一个参数,按它们出现的次序排列。例如,若将add2.c的最后一行改为:
  1. printf ("%d+%d=%d\n", n1, n2, total);
则第一个%d处将显示变量n1的值,第二个%d处将显示变量n2的值,第三个%d处将显示变量total的值。计算机屏幕上最终显示的信息为

第3章中将详细讨论printf函数。
阅读(2130) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~