第4章
从一个程序走进C语言
本章先给大家编写一个程序。编写这个程序的目的是让大家对编程有一个基本的了解,通过这个程序让大家了解什么是编程、怎么编程,以及编程的思路。
下面编写解一元二次方程的程序。这个程序的功能是把任何一个一元二次方程ax 2 +bx+c=0的解给求出来。
写程序之前,首先要建立编程的思路。大家想想第一步需要做什么?对于解一元二次方程,首先要知道解哪个一元二次方程。而确定一个一元二次方程须通过a、b、c三个系数。所以第一步要将这三个系数输入计算机中;第二步要求b 2 –4ac的值,就是数学书中所说的Δ;然后最终的值 。如果b 2 –4ac>0,则有两个解;如果b 2 –4ac=0,则有两个相同解;如果b 2 –4ac<0,则没有解。然后求出解。
这不就是解题的思路吗?编程与此相同,区别无非就是将思路转化成计算机能执行的语言。
那么怎么将a、b、c三个数输入计算机中呢?这时候就需要使用“变量”。这个稍后会详细地讲,这里大家先有一个认知就可以了。
首先将程序的基本框架写好:
# include <stdio.h> int main(void) { return 0; }
这个框架前面已经讲过了,然后再在里面写程序,这是一个固定的格式。
# include <stdio.h> # include <math.h> /*因为要用到求平方函数sqrt(),所以要包含头文件<math.h>*/ int main(void) { //把三个系数保存到计算机中 int a = 1; // “=”不表示相等,而是表示赋值 int b = 2; int c = 1; double delta; //delta存放的是b*b - 4*a*c的值 double x1, x2; //分别用于存放一元二次方程的两个解 delta = b*b - 4*a*c; if (delta > 0) { x1 = (-b + sqrt(delta)) / (2*a); x2 = (-b - sqrt(delta)) / (2*a); printf("该一元二次方程有两个解,x1 = %f, x2 = %f\n", x1, x2); } else if (0 == delta) { x1 = (-b) / (2*a); x2 = x1; //左边值赋给右边 printf("该一元二次方程有一个唯一解,x1 = x2 = %f\n", x1); } else { printf("无解\n"); } return 0; }
第一步先要定义变量。a、b、c分别用来存放三个系数,它们都定义成int型。int型表示整型,即里面可以存放整数。delta用来存放b 2 –4ac的值,它可能是小数,所以定义成double型。double型表示双精度浮点型,可以存放小数(当然也可以存放整数)。x1和x2分别用来存放一元二次方程的解,解也可能是小数,所以也定义成double型。第二步是对变量进行一些运算,先通过b 2 –4ac求出delta。如果delta>0则有两个解,然后将这两个解分别存放到x1和x2里面;如果delta=0则有一个解,x1和x2相等;如果delta<0则无解。
这同数学中的解题思路一模一样。也就是说,编程的第一步是要知道这个问题如何解决;第二步再使用一种语言来实现解决方案。
对于上面这个程序,笔者只将八个比较特别的点提示一下,其他的具体每一句是什么意思现在先不讲,等以后再讲。
第一点: 键盘上没有带上标的b 2 ,只能写成b*b。
第二点: 数学中4a表示4乘以a,但C语言中没有这种写法。C语言中要表示两个数相乘,就必须在它们中间加一个星号“*”,相除的话加一个斜杠“/”。但是负号与数字或变量在一起的时候不用加“*”,如–b不用写成–1*b。
第三点: 键盘上没有“根号”这个键,所以我们要使用一个工具,这个工具叫sqrt。它是Visual C++专门用来求平方根的函数,直接调用就可以了。但是因为它是一个数学工具,所以如果要调用的话,就必须在前面写上:
# include <math.h>
include是“包含”的意思,后面的math.h是一个文件。sqrt这个工具不在stdio.h这个文件里,而是在math.h这个文件里,所以如果不包含math.h这个文件的话,那sqrt这个工具就不能用。也就是说,如果不写“#include<math.h>”的话,那么编译的时候Visual C++就会报错。
第四点: delta、x1、x2为什么要定义成double型?要是定义成float型会怎么样?float型也是用来存放小数的,但是它叫单精度浮点型,所以它存放的小数的位数比double型短。如果定义成float型,编译的时候不会报错,但是会警告“1.obj-0 error(s),4 warning(s)”。这是因为编译时计算机认为会丢失精度。因为float型是4字节,而double型是8字节,所以写float型的话计算机认为你将8字节整合成了4字节,它认为这样很可能会丢失数据,所以产生一个警告。这个后面还会详细地讲。
第五点: 程序中的分号一定是英文输入法下的分号,如果是中文输入法下的分号编译时就会报错。
第六点: 因为main前面写的是int,即int main(void),所以最后的“return 0”千万不能省略。如果不写的话编译时就会产生一个警告。警告的内容是“'main':function should return a value;”,即“main函数应该有一个返回值”。原因是函数定义的是int型。
以前旧的写法中main也可以没有返回值,此时main前面写void,即void main(void)。但是当main前面写void之后main函数中还写“return 0”的话就不是警告了,而是报错。报错的内容是“'main':'void'function returning a value”,即“没有返回值的函数正在返回一个值”。这个大家了解一下就行了,void main()这种写法是不标准的写法,在最新的C99标准中规定main函数必须要有返回值。
第七点: C语言中“=”表示赋值,而不是表示相等。C语言中相等用的是双等号,即“==”。很多初学者很难从传统的数学中走出来,常将“=”当成等号。比如else if(0==delta)这句,初学者经常容易犯的错误是写成这样:else if(delta=0),即将赋值符号当成等于号。更严重的是,虽然这么写对于我们来说是错误的,但对于计算机来说它却是正确的,因为它没有语法错误,所以编译的时候既不会报错也不会警告。这样就会导致程序是错的而我们却不知道。所以笔者建议大家在写程序的时候,当写到“相等”时将数字写在前面,如else if(0==delta)。这样有一个好处就是,如果你不小心写成了else if(0=delta),那么编译的时候不仅会报错,而且还会警告,这样就能避免明明错了我们还不知道的情况。
第八点:
x1 = (-b + sqrt(delta)) / (2*a);
和
x1=(-b+sqrt(delta))/(2*a);
你觉得哪种写法好?第一种写法好。第一种加了空格看起来更清爽!所以推荐大家使用第一种写法。在编程的时候代码一定要书写规范,一定要养成敲空格的习惯。当然代码书写规范还有很多,都是为了让程序看起来更舒服,这些稍后再讲。
下面进行编译、链接、执行,看看结果,如图4-1所示。
图4-1 程序运行结果
上面这个程序功能比较弱,三个系数需要读者自己改,改一次就要重新“编译–链接–执行”一次,这样很麻烦。等后面讲流程控制的时候再完善该程序,使之功能更强一点。比如运行的结果是如图4-1中让你从键盘输入三个系数,然后将结果算出来。完了之后还会问你:“您想继续吗?”继续的话可以再输入三个系数,否则输入“N”就退出。