计算机系统是由硬件系统和软件系统构成,硬件由IBM、HP、DLL、Acer以及联想这样的工厂制造出来,叫裸机。软件由微软、Oracle以及用友等公司的程序员用计算机语言编写出来的,叫程序。程序和编写该程序的文档一起构成了软件系统。裸机安装上了操作系统就构成了第一层虚拟机,计算机软硬件资源由操作系统来管理。在操作系统之上安装应用软件,就构成第二层虚拟机,用户一般与这层计算机打交道的。应用软件提供一个输入数据的界面,用户通过这个界面将要加工的原始数据(文字、数值 、声音、图片、图形、动画、电影等)输入给这个软件,然后它的加工部分对数据进行交换,最后将计算结果输出给用户。
软件是被记录下来的思维的逻辑推理过程,是计算机硬件的“学历”,是计算机系统的灵魂。没有安装软件的裸机就像是一台接收不到电视信号的电视一样,其“本事”不能被挖掘出来。因此,硬件的价值与安装到其上的软件功能成正比,人们借助软件间接地让硬件“劳动”。
计算机硬件的制造现在可以实现批量生产了,但软件的开发还需要人来写,目前还不能现让计算机来编写软件。用来写软件的计算机语言多达2000种,C语言能在众多计算机语言中脱颖而出,靠的就是既能写系统软软件又能写应用软件的特长。系统软件一般直接与硬件打交道,编写难度大。应用软件是用来解决特定领域的数据加工问题的。现在通常的做法是用C开发一个系统软件,然后用这个系统软件开发应用软件例如用C开发出的VFP 系统,用户使用VFP 系统开发其领域的应用软件,如考场安排系统,成绩管理系统以及售票系统等。
1.1 用C 写程序的思想框架
下面给出第一个C程序,命名为c1.c, C源程序的扩名为c。
main () // main函数的功能是调用其他函数,给其传递数据,并接收传来的数据。
{void drawsomething (char, int); // 对该函数进行声明
drawsomething (‘ ‘, 2);
drawsomething(‘#‘, 1); printf ("\n"); //括号内参数是实参
drawsomething(‘ ‘, 1);
drawspmething(‘#‘, 3); printf ("\n") //实参之间用逗号分隔
drawsomething(‘ ‘, 0);
drawsomething (‘#‘, 5); printf("\n"); //字符常量用单括撇括起
} // 分号是语句的标志,少了它就变成了表达式了。
/*下面函数的功能是输出n个由参数c 指定的字符*/
viod drawsomething(char c, int n) // c 和 n 是形式参数,简称为形参,char 即 character.
{ int i; // 定义变量i 是integer 型, C规定变量必须先定义,后使用。
for (i=0; i<n; i++) printf ("c%", c) //循环n次,每次输出一个字符。
} // for 循环中的分号是分隔符。第三章会讲到,同一符号在不同上下文中含义迥然。
由/*&*/ 括起来的部分是C和C++的多行注释语句,// 是C++的注释语句。本书所有程序都是在Turbo C++3.0 IDE (Integrated Development Evironment)下调试和编译。注释语句也叫内部文档,一般分两种:一种是放在源码的最前面,对该程序进行整体注释,介绍其功能,I/O接口中参数的含义、权限要求、算法的简单描述,调用了哪些函数、编者、创建日期、修改日期以及审核日期;另一种是行间注释,对可能引起歧义的语句进行说明。
该程序由main和drawingsomething 两个函数构成,每个函数完成一个特定的功能。 一个程序有且只有一个main 函数,mian函数是程序的入口函数,其位置任意。程序总是从main函数开始执行, main 函数执行完了,整个程序也就执行完了。所以,在拿到一个要进行数据变换的问题后,首先要做的就是将要解决的问题分解为若干功能单一的函数,以使每个函数都有“一技之长”。接下来main函数按照输入数据、变换数据、输出数据的顺序调用相应的函数,由其完成具体的任务。当然函数之间可以相互调用,但不能调用main函数。这就是用C解决数据加工问题的思维框架。
通过上面的示例可以看出,一个函数由函数首部和用花括号括起来的函数体两部分组成。
函数首部由函数返回值类型、函数名(类型 形参、类型 形参,...)构成。 上面的main函数没有形参,叫无参函数,没有返回值类型,默认为int 型,没有返回值语句,则执行完该函数后系统返回一个随机数。 drawsomething 函数的返回值类型是viod, 说明不能有返回值。 形参是定义函数时的形式参数,必须是变量,实参是调用函数时的实际参数,必须有明确的值。 调用时,按从右到左(TC++是这样的,但Fortran等语言按从左向右的顺序)的顺序将实参的值赋给形参,所以要求实参和形参的类型、个数、顺序要对称,否则是编译不通过,或者是计算结果不正确。现在让我们故意犯个错误,将main函数第3行的,2去掉,编译后给出“too few parameters in call to ‘drawsomething‘ in function main”的提示,将实参2改为2.9 ,运行结果不变,因为形参n是整数,它只要整数的部分。
函数内要先写局部变量定义,被调函数声明、判断、循环、赋值、 return等语句。函数体也可以是空语句,即只有一个函数首部后跟一对花括号,叫空函数。根据C的思维框架结构,我们在处理一个大的任务时,首先要做的是将大任务分解为小任务,如此分解下去,直到每个小任务只有一个功能,我们暂时就用这个空函数代表这个小任务,待分解合理了,任务之间的关系理顺了,再把空函数为真正的函数,然后上机调试、编译为EXE文件,就可以作为软件使用了。如,求两个正整数的最大公约数和最小公倍数,可以分解为如下三个函数:
int max(int, int){} // max 函数负责求最大公约数,返回值类型是int型。
min (int, int) {} // min 函数负责最小公倍数,省略了返回值类型。
void main () {} //负责接收待求数,调用max和min,接收其返回值,最后输出结果。
下面细化后的三个函数:
int max (int bcs, int cs) // bcs是被除数的拼音字母缩写,cs代表除数。
{ int yushu; // yushu代表余数,zdgys 代表最大公约数,zxgbs代表最小公倍数。
while(cs != 0) // while 循环结构,读作当条件为真时,执行循环体,然后返回到
{yushu=bcs/cs; //条件处继续判断,当条件仍为真时,继续执行循环体,如此循环,
cs=yushu; //当条件为假时,跳出循环,继续执行后继语句
bcs=cs; //当循环体语句多于一条时用{}括起来,构成复合语句;其功能相当于一条语句。
} // 下面的return语句是上面循环结构的后继语句
return (bcs): // 将加工结果返回调用处, return后面的圆括号可以省略。
} //将源代码写成锯齿状的目的是增强程序的可读性,程序的结构层次清淅,一目了然。