【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
一、常用的代码组织形式
将所需要使用的函数分类,总体思想是如果两个函数操作的是一个资源,完成的是类似的功能,则将这两个函数划分在一个模块中,比如对一个链表的的插入和删除操作而言应该划分到一个模块内,在C语言中,一个文件即代表一个模块。
其次,如果模块中的函数是一个函数接口,需要被其他模块所引用,则应当定义为外部函数。如果函数仅在模块内使用,则应当定义为static函数。这样做可以防止各个模块中的函数因为重名现象而出现的错误。使用static关键字定义函数之后,该函数对其他的模块来说是透明的,只有本模块的函数可以对其进行调用。同理,仅在模块内使用的全局变量也应当定义为static。
最后,定义一个common.h头文件,该头文件包括以下内容:
- 头文件区:包含所有模块共同需要的头文件。例如常用的stdio.h、stdlib.h等
- 全局宏区:包含所有模块公用的宏定义,例如调试开关,一些缓冲区的大小等
- 全局变量区:包含所有非static全局变量的声明
- 函数接口区:包含所有模块的函数接口
有了该common.h头文件后,各个模块的头文件只要包含该头文件,就可以应用函数接口和全局变量,包含所需要的头文件和宏定义。
下面是一个经过组织的链表处理程序:
/**
* common_list.h 总领头文件
*
*/
/* 头文件区 */
#include <stdio.h>
#include <stdlib.h>
/* 全局定义区 */
typedef struct node * Node; //结点指针
/**
* 链表结点结构
* val:结点的值
* next:下个结点的指针
*/
struct node{
int val;
Node next;
};
/* 全局变量声明 */
extern Node head;
/* 函数接口声明区 */
extern int insert(int val);
extern void print();
extern void destroy();
/**
* list.c 定义所有操作链表的函数
*/
#include "list.h"
Node head;//链表头
//插入结点函数
int insert(int val)
{
Node p, q;
p = head;
if(p != NULL) { //链表非空
while(p->next != NULL) {
p = p->next;
}
}
q = (Node)malloc(sizeof(struct node)); //创建新的结点
if(q == NULL)
return -1;
q->next = NULL;
q->val = val;
if(p == NULL){
head = q;
return 1;
}
p->next = q; //结点加入链表
return 1;
}
//遍历链表,打印每个结点的值
void print()
{
Node p = head;
while(p != NULL){
printf("%d\n", p->val);
p = p->next;
}
}
//遍历链表,删除每一个结点
void destroy()
{
Node p = head;
while(p != NULL){
Node q;
q = p;
p = p->next; //指向下一个结点
free(q); //释放该结点
}
head = NULL;
}
/**
* main.c main函数
*/
#include "list.h"
int main(void)
{
Node p;
int i;
printf("insert\n");
for(i = 1; i < 8; i++){
insert(i);
}
print(); //遍历链表,打印链表结点
printf("destroy\n");
destroy();
return 0;
}
二、调试开关
在调试大程序时免不了需要输出一些当前程序执行的信息,如下例所示:
#include <stdio.h>
void bubble_sort(int a[], int n)
{
int i, j, temp;
for (j = 0; j < n - 1; j++)
for (i = 0; i < n - 1 - j; i++)
if(a[i] > a[i + 1]){
temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
}
}
int main(void)
{
int array[5] = {1, 2, 4, 3, 0};
int i;
printf("before sort\n");
bubble_sort(array, 5); //调用冒泡排序函数
printf("after sort\n");
for(i = 0; i < 5; i++){
printf("%d\n", array[i]);
}
return 0;
}
运行结果:
当不需要这些输出信息时,需要注释掉这些语句,这种注释很麻烦,当代码很长的时候这种注释难免会出现问题,这时应当使用条件编译技术,将这些输出信息定义为宏,如下所示:
#include <stdio.h>
#define DEBUG 1 //调试开关
#ifdef DEBUG
#define PRINT(str) printf(str) //输出一个参数的printf函数
#define PRINT_1(str, arg); printf(str, arg); //两个参数的printf函数
#else
#define PRINT(str)
#define PRINT_1(str, arg); ;
#endif
void bubble_sort(int a[], int n)
{
int i, j, temp;
for (j = 0; j < n - 1; j++)
for (i = 0; i < n - 1 - j; i++)
if(a[i] > a[i + 1]){
temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
}
}
int main(void)
{
int array[5] = {1, 2, 4, 3, 0};
int i;
PRINT("before sort\n");
bubble_sort(array, 5); //调用冒泡排序函数
PRINT("after sort\n");
for(i = 0; i < 5; i++){
PRINT_1("%d\n", array[i]);
}
return 0;
}
在不使用输出信息时,只要关闭调试开关就可以了,如下所示:
//#define DEBUG 1 /*注释掉这一行,所有的条件编译则不会编译*/
这样程序就不会输出任何东西了:
来源:oschina
链接:https://my.oschina.net/u/2368202/blog/771566