看了《兩則c語言技巧》文章之後,很高興又學會了兩招用法!但是技巧畢竟還是要與實際應用相結合的,所以我下面就談一下我自己對這些技巧的看法,並貢獻自己發現的一下c
語言的用法。
1. Enum
{
FRUIT_APPLE,
FRUIT_PEAR,
FRUIT_BANANA,
FRUIT_NR
};
int price[FRUIT_NR] = { [FRUIT_APPLE] = 20, [FRUIT_PEAR] = 25, [FRUIT_BANANA] = 30};
上面這種用法較常規用法的好處是不用來回移動數組內容,也更具有可讀性和修改性!一般我會將這種用法用在配置資料上,比如我們需要為一個下列框填值,但是顯示的值序列
還不確定,這種方式就很好的適應這種需求。如果擴充這種使用方式,可以用來類比一個設定檔的用途,這在嵌入式開發中是很有益的。
2. case的連用,雖然這種方式比較簡便但是犧牲了可修改性,除非非常確定不準備擴充中間case的處理,所以不建議使用。
c語言中還有其他的提示,我最近發現一個,使用結構體來封裝一個類似於c++中類的對象,使用結構體和函數指標相結合。
具體的使用看下面給出一個實現的迴圈隊列的實現。
在"cqueue.h"中如下定義
struct tagAlgCycQueue;
typedef struct tagAlgCycQueue ALG_CYC_QUEUE;
typedef struct tagAlgCycQueue* PALG_CYC_QUEUE;
typedef int (* CQ_IsFull) (PALG_CYC_QUEUE);
typedef int (* CQ_IsEmpty) (PALG_CYC_QUEUE);
typedef void (* CQ_InQueue) (PALG_CYC_QUEUE, void *);
typedef void* (* CQ_OutQueue) (PALG_CYC_QUEUE);
typedef int (* CQ_Reverse) (PALG_CYC_QUEUE);
typedef void (* CQ_Jump)(PALG_CYC_QUEUE, int);
struct tagAlgCycQueue
{
int nStartPos;
int nCurPos;
int nEndPos;
int bInited;
int nElementSize;
int bDirect;
int nLength;
void* pBuf;
/*
* 注意這裡:用到前面的函數定義,通過這幾個函數定義,我們就可以實現自己的演算法,
* 如果別人不滿意也可以從這裡修改來添加他自己的演算法實現。
*/
CQ_IsFull IsFull;
CQ_IsEmpty IsEmpty;
CQ_InQueue InQueue;
CQ_OutQueue OutQueue;
CQ_Reverse Reverse;
CQ_Jump Jump;
};
這個函數用於初始化一個隊列結構
extern ALG_InitCycQueue(PALG_CYC_QUEUE pQueue,
int len, void *pBuf, int em_size);
在"cqueue.c"檔案中實現
#define _TEST_QUEUE(b) { \
if ( !(b) ) \
{ \
printf("error: queue don't initialize!\n"); \
return -1; \
} \
}
static int ALG_CQ_IsFull(PALG_CYC_QUEUE pQueue)
{
_TEST_QUEUE(pQueue->bInited);
return ( ((pQueue->nEndPos + 1) % pQueue->nLength) == pQueue->nStartPos );
}
static int ALG_CQ_IsEmpty(PALG_CYC_QUEUE pQueue)
{
_TEST_QUEUE(pQueue->bInited);
return ( ((pQueue->nStartPos + 1) % pQueue->nLength) == pQueue->nEndPos );
}
static int ALG_CQ_InQueue(PALG_CYC_QUEUE pQueue, void *pEm)
{
_TEST_QUEUE(pQueue->bInited);
if ( ALG_CQ_IsFull(pQueue) )
return 0;
if ( NULL == pEm )
{
memset(pQueue->pBuf+pQueue->nElementSize*pQueue->nEndPos, 0, pQueue->nElementSize);
}
else
{
memcpy(pQueue->pBuf+pQueue->nElementSize*pQueue->nEndPos, pEm, pQueue->nElementSize);
}
pQueue->nEndPos = (++pQueue->nEndPos) % pQueue->nLength;
return 1;
}
static void* ALG_CQ_OutQueue(PALG_CYC_QUEUE pQueue)
{
_TEST_QUEUE(pQueue->bInited);
if ( ALG_CQ_IsEmpty(pQueue) )
return NULL;
pQueue->nStartPos = (++pQueue->nStartPos) % pQueue->nLength;
return (pQueue->pBuf + pQueue->nElementSize*pQueue->nStartPos);
}
static void ALG_CQ_Jump(PALG_CYC_QUEUE pQueue, int offset)
{
int i = offset;
_TEST_QUEUE(pQueue->bInited);
while ( i > 0 )
{
if ( ALG_CQ_IsFull(pQueue) )
{
ALG_CQ_OutQueue(pQueue);
}
ALG_CQ_InQueue(pQueue, NULL);
i--;
}
}
/*
* DESC: this function is used to initialize tagAlgDCycQueue struct, you must call
* this function when you want to use tagAlgDCycQueue object.
*
* IN :pQueue tagAlgDCycQueue point
* len queue length
* pBuf queue buffer
* em_size the element size in queue
*
* RET : if success return 1, else return 0
*/
int ALG_InitCycQueue(PALG_CYC_QUEUE pQueue,
int len, void* pBuf, int em_size)
{
if ( NULL == pQueue || NULL == pBuf )
return 0;
pQueue->nLength = len;
pQueue->nElementSize = em_size;
pQueue->pBuf = pBuf;
pQueue->nStartPos = 0;
pQueue->nEndPos = pQueue->nStartPos + 1;
pQueue->nCurPos = 0;
pQueue->bInited = 1;
pQueue->bDirect = 0;
pQueue->IsEmpty = ALG_CQ_IsEmpty;
pQueue->IsFull = ALG_CQ_IsFull;
pQueue->InQueue = ALG_CQ_InQueue;
pQueue->OutQueue = ALG_CQ_OutQueue;
pQueue->Jump = ALG_CQ_Jump;
return pQueue->bInited;
};
這樣就可以實現一個比較原始的迴圈隊列的操作了,並且我們也對這個操作進行了一定的封裝。
但是以上的封裝還是有些問題,就是結構體內部的變數沒進行保護,呵呵,這個目前還沒有找到解決
方法。