手把手教你学C语言
上QQ阅读APP看书,第一时间看更新

第4章

从一个程序走进C语言

本章先给大家编写一个程序。编写这个程序的目的是让大家对编程有一个基本的了解,通过这个程序让大家了解什么是编程、怎么编程,以及编程的思路。

下面编写解一元二次方程的程序。这个程序的功能是把任何一个一元二次方程ax2+bx+c=0的解给求出来。

写程序之前,首先要建立编程的思路。大家想想第一步需要做什么?对于解一元二次方程,首先要知道解哪个一元二次方程。而确定一个一元二次方程须通过abc三个系数。所以第一步要将这三个系数输入计算机中;第二步要求b2-4ac的值,就是数学书中所说的∆;然后最终的值。如果b2-4ac > 0,则有两个解;如果b2-4ac=0,则有两个相同解;如果b2-4ac < 0,则没有解。然后求出解。

这不就是解题的思路吗?编程与此相同,区别无非就是将思路转化成计算机能执行的语言。

那么怎么将abc三个数输入计算机中呢?这时候就需要使用“变量”。这个稍后会详细地讲,这里大家先有一个认知就可以了。

首先将程序的基本框架写好:

    # 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用来存放b2 -4 ac的值,它可能是小数,所以定义成double型。double型表示双精度浮点型,可以存放小数(当然也可以存放整数)。x1和x2分别用来存放一元二次方程的解,解也可能是小数,所以也定义成double型。第二步是对变量进行一些运算,先通过b2 -4ac求出delta。如果delta > 0则有两个解,然后将这两个解分别存放到x1和x2里面;如果delta=0则有一个解,x1和x2相等;如果delta < 0则无解。

这同数学中的解题思路一模一样。也就是说,编程的第一步是要知道这个问题如何解决;第二步再使用一种语言来实现解决方案。

对于上面这个程序,笔者只将八个比较特别的点提示一下,其他的具体每一句是什么意思现在先不讲,等以后再讲。

第一点:键盘上没有带上标的b2,只能写成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”就退出。