在项目开发中,错误码的设计本身就是一个重要的模块。
出错信息的处理
你会处理出错信息吗?哦,它并不是简单的输出。看下面的示例:
if ( p == NULL ){
printf ( "ERR: The pointer is NULL\n" );
}
告别学生时代的编程吧。这种编程很不利于维护和管理,出错信息或是提示信息,应该统一处理,而不是像上面这样,写成一个 " 硬编码"。管理错误信息,那就要有以下的处理:
/* 声明出错代码 */
#define ERR_NO_ERROR 0 /* No error */
#define ERR_OPEN_FILE 1 /* Open file error */
#define ERR_SEND_MESG 2 /* sending a message error */
#define ERR_BAD_ARGS 3 /* Bad arguments */
#define ERR_MEM_NONE 4 /* Memeroy is not enough */
#define ERR_SERV_DOWN 5 /* Service down try later */
#define ERR_UNKNOW_INFO 6 /* Unknow information */
#define ERR_SOCKET_ERR 7 /* Socket operation failed */
#define ERR_PERMISSION 8 /* Permission denied */
#define ERR_BAD_FORMAT 9 /* Bad configuration file */
#define ERR_TIME_OUT 10 /* Communication time out */
/* 声明出错信息 */
char* errmsg[] = {
/* 0 */ "No error",
/* 1 */ "Open file error",
/* 2 */ "Failed in sending/receiving a message",
/* 3 */ "Bad arguments",
/* 4 */ "Memeroy is not enough",
/* 5 */ "Service is down; try later",
/* 6 */ "Unknow information",
/* 7 */ "A socket operation has failed",
/* 8 */ "Permission denied",
/* 9 */ "Bad configuration file format",
/* 10 */ "Communication time out",
};
/* 声明错误代码全局变量 */
long errno = 0;
/* 打印出错信息函数 */
void perror( char* info)
{
if ( info ){
printf("%s: %s\n", info, errmsg[errno] );
return;
}
printf("Error: %s\n", errmsg[errno] );
}
这个基本上是ANSI的错误处理实现细节了,于是当你程序中有错误时你就可以这样处理:
bool CheckPermission( char* userName )
{
if ( strcpy(userName, "root") != 0 ){
errno = ERR_PERMISSION_DENIED;
return (FALSE);
}
...
}
main()
{
...
if (! CheckPermission( username ) ){
perror("main()");
}
...
}
一个即有共性,也有个性的错误信息处理,这样做有利同种错误出一样的信息,统一用户界面,而不会因为文件打开失败, A 程序员出一个信息,B 程序员又出一个信息。而且这样做,非常容易维护。代码也易读。
当然,物极必反,也没有必要把所有的输出都放到errmsg中,抽取比较重要的出错信息或是提示信息是其关键,但即使这样,这也包括了大多数的信息。
tplink的错误处理
错误码以枚举的形式定义在tplinkType.h文件中。
typedef enum
{
ERR_NO_ERROR = 0, // No Error. Note: OK is defined in VxWork.
ERR_BAD_PARAM, // Bad parameter, special aim at pointer is NULL
ERR_NOT_SUPPORT, // not support
...
ERR_THE_END,
} TP_ERROR_CODE;
错误提示信息则以结构体数组形式放在了errCode.c文件中。
typedef struct
{
TP_ERROR_CODE switchErrorCode;
UINT8 *errorString;
}SWITCH_ERROR_CODE;
SWITCH_ERROR_CODE ErrorCodeEnglish[] =
{
{ ERR_NO_ERROR, "Operation successful." },
{ ERR_BAD_PARAM, "Error parameters." },
{ ERR_NOT_SUPPORT, "Function not supported."},
...
{ ERR_THE_END, "unknown error." }
};
对于结构体数组ErrorCodeEnglish中错误信息的获取,由于采取的是for循环逐个查询匹配的方式,所以无需对每一个枚举类型都给出错误信息。同时,顺序也无需一一对应。
可以利用c99新特性memberwise initialization进行改进tplink的错误处理,达到查询为常量时间、减少占用空间、顺序也无需一一对应的。示例代码如下。(根据廖泽衔的评论添加,2012-8-20)
#define DEF_ERR(_no, _str) [_no]=(_str)
typedef enum
{
ERR_NO_ERROR=0,
ERR_1TH_ERROR,
ERR_2TH_ERROR,
ERR_CODE_END
} ERROR_CODE;
char *errStr[] =
{
DEF_ERR(ERR_NO_ERROR, "No Error"),
DEF_ERR(ERR_2TH_ERROR, "2th Error"),
DEF_ERR(ERR_1TH_ERROR, "1th Error")
};