C语言最佳实践
上QQ阅读APP看书,第一时间看更新

1.2.2 妙手理码

拿到坏代码时,一个很好的习惯就是对代码按照编码规范的要求进行整理。这一过程本身就是阅读代码的过程,通过整理,我们可以使代码变得更加清晰易懂,也可能发现并解决一些潜在的问题。

程序清单1.2是按照符合惯例的编码风格对程序清单1.1中的代码进行修改后的版本。

程序清单1.2 一个简单的链表实现(整理后)

#include <stdio.h>
#include <stdlib.h>
 
struct linked_list {
    const char         *title;
    struct linked_list *next;
}
 
/* Creates and initializes a new linked list. */
static struct linked_list *init_linked_list(void);
 
/* Dumps the contents of a linked list */
static void dump_linked_list(struct linked_list *list);
 
/* Destroys a linked list */
static void destroy_linked_list(struct linked_list *list);
 
static const char *titles[] =
{
    "第1章 提高代码可读性",
    "第2章 用好写好头文件",
    "第3章 消除编译警告",
    "第4章 常量的定义和使用",
    "第5章 充分利用构建系统生成器"
};
 
int main(void)
{
    /* Creates and initialize a new linked list with chapter titles */
    struct linked_list *list = init_linked_list();
 
    printf("A new linked list has been created and initialized: \n");
    dump_linked_list(list);     // dump the contents
 
    destory_linked_list(list);  // destroy the list
    return 0;
}
 
struct linked_list *init_linked_list(void)
{
    struct linked_list *head = NULL;
 
    /* allocates a node for the head of the linked list */
    struct linked_list *head = (struct linked_list*)malloc(sizeof(*head));
 
    /* initializes the head node */
    head->title = titles[0];
    head->next = NULL;
 
    struct linked_list *p = head;
    for (int i = 1; i < 5; i++) {
        struct linked_list *a;
        a = (struct linked_list*)malloc(sizeof(*a));
        a->title = titles[i];
        a->next = NULL;
 
        p->next = a;
        p = a;
    }
 
    return head;
}

可以看到,修改之后的代码排版错落有致,逻辑清晰,给人一种赏心悦目的感觉。除了排版,我们还在如下6个方面对原有的代码做了调整,以便提高代码可读性以及代码质量。

struct linked_list结构体中的第一个成员(elem)更名为更具实际意义的title

init_linked_list()函数声明为static类型,避免命名污染。

display()函数重命名为dump_linked_list(),并声明为static类型。display这个术语通常用于在窗口或者页面中显示一个图形,而在本例中,展示一个链表通常意味着将其内容转储(dump)到指定的文件或者标准输出(标准输出本质上也是文件),以便事后查看或者调试。因此,使用dump这个术语来命名这个函数,显然要比使用display强很多。

新增destroy_linked_list()函数,用于销毁新创建的链表,并声明为static类型。原有代码在main()函数返回时并未做内存的清理工作。尽管在这个简单的链表实现中不必如此严谨,但作为专业程序员,我们应该养成良好的习惯并逐渐形成条件反射:既然有链表的创建函数,就应该有对应的链表销毁函数。

init_linked_list()函数的实现中,移除了不必要且易混淆的temp变量。

使用sizeof(*head)的写法替代了sizeof(struct linked_list)的写法,避免代码行过长。

注意,上述代码中未包含dump_linked_list()destroy_linked_list()两个函数的实现,有兴趣的读者可自行实现。