函数与渐进式编程

函数

理解函数

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

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

渐进式编程(渐进开发)

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

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

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

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

实例

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

#include <stdio.h>

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 <stdio.h>
// 在最开始的时候, 主函数与该段注释之前没有任何东西        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定义,改为判断两个数的绝对值大小,返回绝对值大的那个数,然后返回值就可正可负,弥补了只能为正的缺憾

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351