函数与渐进式编程

函数

理解函数

要理解函数,首先要弄懂什么是函数和如何使用函数。
函数是已命名的,执行专项任务的独立C代码段,可选择是否向调用它的程序返回一个值。现在,仔细分析这段定义。

  • 函数是已命名的 每个函数都有独一无二的函数名。在程序的其他部分使用函数名,可以执行该函数中的语句。这也称为调用(call)函数。可以在函数中调用其他函数。
  • 函数是独立的 函数可独立执行任务,无需程序其他部分干预。
  • 函数可以向调用它的程序返回一个值 程序调用函数时,会执行函数中的语句。如果需要的话,可以把特定信息传递给调用它们的程序。

渐进式编程(渐进开发)

初学者常常犯这样一个错误,即在不尝试编译的情况下就编写大量代码,然后再花费大量的时间调试代码。我们认为渐近开发是一种更好的方法,这种方法的要点如下:

  • 先编写一个能够运行的简单程序,再逐步修改。这样的话,无论什么时候出现错误,你都知道该检查哪些地方。
  • 用变量存储中间值,以便能够用打印语句或调试器检查它们。
  • 程序能够正确运行之后再将多条语句合并为复合表达式(前提是这样不会导致程序更难理解。

------以上内容来自《JAVA编程思维》

结合《代码整洁之道》的思想,我们可以将每一部分的小代码提取成为一个实用的函数(在面向对象中实用性更高),然后通过渐进式编程确保每个函数的绝对正确性,这样在出现错误时,更方便检查出错的地方。

实例

求三个整数(有正有负)中绝对值最大的数。
输入 12 -14 7
输出 -14
以下代码是没有使用函数的渐进式编程,测试位置在注释中给出。

#include 

int main(void)
{
    // 首先读取三个数
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);
    // !!! 初期建议在此处停止编写代码, 应当验证数据是否读取
    // !!! 在以后的数组读取中, 这里的重要性很高, 数组经常会出现少读、多读、读错位置的情况
    // !!! 以下为测试代码, 验证成功后可以删掉或者注释掉
    // printf("a = %d, b = %d, c = %d", a, b, c);

    // 定义一个变量用来存储绝对值最大的数
    int maxAbsolute;

    // 比较 a 与 b, 找出绝对值最大的值
    if (a < 0)
    {
        // 此时花括号里的 a 都是负值
        if (b < 0)
        {
            // 此时 a b 都为负数, 谁更小谁的绝对值就越大
            if (a < b)
                maxAbsolute = a;
            else
                maxAbsolute = b;
        }
        else
        {
            // 此时 a 为负, b 为正, 如果和小于 0, 则负数的绝对值大, 反之同理
            if (a + b > 0)
                maxAbsolute = a;
            else
                maxAbsolute = b;
        }
    }
    else
    {
        // 此时花括号里的 a 都是正值
        if (b < 0)
        {
            // 此时 a 为正, b 为负, 如果和大于 0, 则正数的绝对值大, 反之同理
            if (a + b > 0)
                maxAbsolute = a;
            else
                maxAbsolute = b;
        }
        else
        {
            // 此时 a b 都是正数, 谁大谁的绝对值就大
            if (a > b)
                maxAbsolute = a;
            else
                maxAbsolute = b;
        }
    }
    // !!! 这一部分代码写完之后, 最好验证一下 a 与 b 之间的判断是否正确
    // !!! 测试代码如下, 测试完之后删掉或者注释掉
    // printf("maxAbsolute between a and b is: %d", maxAbsolute);

    // 比较 maxAbsolute 与 c 谁的绝对值更大
    if (maxAbsolute < 0)
    {
        // 此时 maxAbsolute 为负
        if (c < 0)
        {
            // 此时 maxAbsolute 与 c 都为负, 谁越小谁的绝对值越大
            if (maxAbsolute < c)
                ;
            else
                maxAbsolute = c;
        }
        else
        {
            // 此时 maxAbsolute 为负, c 为正, 和小于0, 则负数的绝对值大, 反之同理
            if (maxAbsolute + c < 0)
                ;
            else
                maxAbsolute = c;
        }
    }
    else
    {
        // 此时 maxAbsolute 为正
        if (c < 0)
        {
            // 此时 maxAbsolute 为正, c 为负, 和大于0, 则正数的绝对值大, 反之同理
            if (maxAbsolute + c > 0)
                ;
            else
                maxAbsolute = c;
        }
        else
        {
            // 此时 maxAbsolute 与 c 都为正, 谁越大谁的绝对值就越大
            if (maxAbsolute > c)
                ;
            else
                maxAbsolute = c;
        }
    }
    // !!! 本来此处也是需要验证的, 但是程序最终输出值恰好就是此处的结果
    // !!! 所以可以直接执行后面的输出即可


    printf("%d\n", maxAbsolute);
    return 0;
    // 事实是我在全部敲完所有代码之后才编译了, 因为觉得简单, 但是在运行的时候却又一种
    // 庆幸感, 觉得程序没出错很幸运, 如果我没做一段就验证的话, 那我将会对结果有绝对的
    // 掌控, 而不是用幸运来形容. 
}

以上代码算上注释足足111行,但是却只是做了一个很简单的判断三个数中绝对值最大的数的问题,接下来将使用渐进式编程与函数结合去解决这个问题。

#include 
// 在最开始的时候, 主函数与该段注释之前没有任何东西        23:31(当前时间)
int absolute(int n);    // 该段函数原型写于该函数定义完之后 23:38(当前时间)
int big(int a, int b);  // 该段函数原型写于该函数定义完之后 23:44(当前时间)

int main(void)
{
    // 依旧是获取三个数, 并将其存储起来
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);
    // 验证正确性, 代码如下, 之后可删可注释掉
    // printf("a = %d, b = %d, c = %d", a, b, c);

    // 定义一个存储最大绝对值的数
    int maxAbsolute;
    // 在这里我不想再一个个比较了, 我想直接得到他们的绝对值, 直接比较绝对值
    // 我假设 absolute(a) 这个东西便是 a 的绝对值, 于是我便需要定义函数absolute
    // (23:38) 函数定义了, 函数原型也写好了, 我得测试一下这个函数是不是能用
    // 测试代码如下, 实际测试数据需要更多, 以确保正确性
    // printf("absolute of -15 is: %d", absolute(-15));

    // 测试结束, (23:41) 绝对值没问题了, 但是还需要进行比大小, 我也不想写那么多比大小
    // 我假设 big(a, b) 这个东西便是 a b中的绝对值最大值所对应的数, 于是我便需要定义这个函数
    // (23:45) 函数定义, 原型都好了, 继续测试 big 函数是否正确
    // 测试代码如下
    // printf("the big of 15 and 21 is : %d", big(15, 21));

    // 测试结束, 我总算可以使用绝对值和比大小了, 直接开始使用
    maxAbsolute = big(a, b);
    maxAbsolute = big(a, b);


    printf("%d", maxAbsolute);

    return 0;
    // (23:53) 当前时间 
    // 因为big函数定义的时候是直接比大小, 所以返回值一定是个正数, 修改了一下函数
    // 将绝对值作为它调用的函数, 然后返回原数据(可正可负)

    // 因为每一个函数都做测试, 所以很容易知道最终出错是在big这里
}

// 该段函数定义于假设 absolute(a) 是 a 的绝对值之后 23:36(当前时间)
int absolute(int n)
{
    if (n < 0)
        n *= -1;
    return n;
}
// 函数定义完了, 因为定义在了 main 函数后面, 所以我便需要在前面写上函数原型

// 该段函数定义于假设 big(a, b) 是 a b中的最大值之后     23:43(当前时间)
// 该段程序修改于 23:52
int big(int a, int b)
{
    if (absolute(a) > absolute(b))
        return a;
    else 
        return b;
}
// 函数定义完了, 继续补上函数原型

函数整体61行,还可以继续优化,不过暂时就先这样了。
最大的错误在于使用big时返回值为正,然后将绝对值作为big的调用,改变big定义,改为判断两个数的绝对值大小,返回绝对值大的那个数,然后返回值就可正可负,弥补了只能为正的缺憾

你可能感兴趣的