• C专家编程 第8章 为什么程序员无法分清万圣节和圣诞节 8.8 软件比硬件更困难


    软件比硬件更困难
    软件很容易修改,但在其他的各个方面都比硬件显得更困难?因为软件是如此难于开发和获得
    正确的结果,作为程序员,我们需要找到尽可能容易的方法。其中一种方法(适用于所有语言,
    并不限于C语言)就是使代码便于调试。当你编写程序时,提供debugging hook。

    debugging hook
    你知不知道绝大多数调试器都允许从调试器命令行调用函数?如果你拥有十分复杂的数据结构,它
    将会非常有用。你可以编写并编译一个函数,用于遍历整个数据结构并把它打印出来。这个函数不会在代码的任何地方被调用,但它却是可执行文件的一部分。他就是debugging hook。
    当调试代码并停在某个断点是,你可以很容易就通过手工调用你的打印函数来检查结构的完整性。

    我们已经提示了可调试性编码。建议在为FSM编写代码时使用两个明显的阶段:首先进行状态转换,并只有当它们处于工作状态时才提供动作。不要把增量开发(incremental development)和显式代码调试(debugging code into existence)混为一谈,后者是程序员新手或那些开发时间非常紧的程序员常常采用的一种技巧。显式代码调试就是首先仓促地编写一个程序框架,然后在接下来几周的时间里通过修改无法运行的部分对程序进行持续的完善,直到程序能工作。同时,任何人如果要依赖系统组件,可能会急的发疯。Sendmail和make是两个广为人知的被认为原先是显示代码调试的程序。这就是为什么它们的命令语言是如此的考虑不周和难于学习。
    可调试编码意味着把系统分成几个部分,先让程序总体结构运行。只有基本的程序能够运行之后,
    你才为那些复杂的细节完善、性能调整和算法优化进行编码。 

    华丽的散列表
    散列(Hash)表是一种提高访问表中数据元素的方法。它不是线性地搜索表中的元素,而是一下子跳到最相像的元素来存储值。
    这是通过精心地向表载入元素来实现的。它并不是按照线性顺序,而是应用某种形式的转换(称为散列函数),把数据值和存储它的位置联系起来。散列函数会产生一个范围为0~表的长度减1的值,它就是所需要存储的数据的索引。
    如果这个位置已经被别的元素占领,那么就从这个位置起继续向前搜索,直到找到一个空的位置。
    另一个解决位置冲突的办法是建立一个链表,挂在这个位置的后面,所有散列函数值为这个位置的元素都添加到这个链表中(既可以从链表头部插入,也可以从尾部追加)。甚至可以在这个位置后面再挂一个散列表。
    当查找一个数据项时,不需要从表中第一个元素起挨个查找,而是先产生该数据项的散列函数值,并根据这个值找到表中相应的位置,然后从该位置开始查找该数据项。
    散列表是一种被广泛使用和严格测试的表查找优化方法,在系统编程中到处都有它的踪影:数据库、操作系统和编译器。

    我的同事需要编写一个程序。他并不想一步登天,一次完成所有的任务。他首先让最简单的情况
    能够运行,就是散列表函数总是返回一个零。这个散列函数如下:
    /*hash_file:占位符,为将来更复杂的程序留下位置*/
    int hash_filename(char *s) {
        return 0;

    调用这个散列函数的代码如下:
    /*
     *find_file:定为以前建立的文件描述符,需要时可以新建一下
     */
    file find_file_name(char *s) {
        int hash_value = hash_filename(s);
        file f;
        for (f = file_hash_table[hash_value]; f != NULL; f = f->flink) {
            if (strcmp(f->fname, s) == SAME) {
                return f;
            }
        }
        /*文件未找到,建立一个新文件*/
        f = allocate_file(s);
        f->flink = file_hash_table[hash_value];
        return f; 

    他总结为“brain,pain,gain”(思考、痛苦、收获) 
    int hash_filename(char *s) {
        int length = strlen(s);
        return (length + 4 * (s[0] + 4 * s[length/2])) % FILE_HASH

    有时候,花点时间把编程问题分解成几个部分往往是解决它的最快方法。 

  • 相关阅读:
    解码四大区块链发展先导区:共通、发展与未来
    使用appium启动app运行常见问题
    SpringMVC源码(1)-文件上传请求
    【Linux】《Linux命令行与shell脚本编程大全 (第4版) 》笔记-Chapter14-处理用户输入
    第53期|GPTSecurity周报
    springboot中自定义拦截器用Component注解不用Configuration注解的坏处是什么
    深入剖析 RocketMQ 源码 - 负载均衡机制
    无卷积骨干网络:金字塔Transformer,提升目标检测/分割等任务精度(附源代码)...
    Linux等待队列
    你的Spring应用启动很慢?不妨试试这个工具!
  • 原文地址:https://blog.csdn.net/weixin_40186813/article/details/126087985