程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C語言的一個不錯的模式

C語言的一個不錯的模式

編輯:關於C語言
 

耐心地看,包括例子,你會有收獲的!

//先熟悉一下函數指針的用法

#include <stdio.h>

int f1(int a);
int f2(int a, int b);
typedef int(*F)();       
//注意形參為空,自由度大一點

typedef struct _A
{
        int n;
        F f;
}A;

int main()
{
    A a[]={{10, f1}, {100, f2}};
    
    printf("%d\n", a[0].f(a[0].n));
    printf("%d\n", a[1].f(a[1].n, a[1].n));
   
    system("pause");
    return 0;
}

int f1(int a)
{
    return a;
}

int f2(int a, int b)
{
    return a+b;
}


//下面的模型我覺得挺不錯的

//*****************************************************my_struct.h
#ifndef MY_STRUCT_H
#define MY_STRUCT_H

typedef struct _my_struct
{
        char *code;
        int (*func1)();     //函數形參可以省略,C編譯器不檢查,增加了自由度,但是也增大了出錯幾率,要小心!!
        int (*func2)();
}my_struct;

extern my_struct   Code_func[];   //extern變量聲明(不是定義),所以其他文件只要包含該頭文件就可使用該全局變量,‘extern’關鍵字不能省略!!

extern int tr003();               //函數聲明,‘extern’關鍵字可省略
extern int prs003();             //函數形參可以省略,C編譯器不檢查,增加了自由度,但是也增大了出錯幾率,要小心!!

extern int tr004();
extern int prs004();

extern int tr006();
extern int prs006();

#endif

//*************************************************************var_def.c

#include "my_struct.h"

//定義並初始化了一個全局數組,添加交易直接在此處添加,並在頭文件裡面聲明對應的函數

my_struct Code_func[]=
{
        {"003",tr003,prs003},
        {"004",tr004,prs004},
        {"006",tr006,prs006},
        {NULL}
};

//********************************************************************main.c

#include "my_struct.h"

//這樣就可以直接用 Code_func 數組了

int main()

{

........

while (Code_func[i].code != NULL)
    {
        if (strcmp(msgHead->txCode, Code_func[i].code) == 0)
        {
            result1 = (Code_func[i].func1)(writer,buf,pBodyIn,iBodyNum);

            //result1 = (*Code_func[i].func1)(writer,buf,pBodyIn,iBodyNum);和上面的調用沒有區別

            result2 = (Code_func[i].func2)(......);

             break;
        }
        i++;
    }

.......

}

例子:《深入淺出MFC》第一章 第20頁——消息映射(Message Map)的雛形


       有沒有可能把窗口函數的內容設計得更模塊化、更一般化些?下面是一種作法。請注意,
以下作法是MFC「消息映射表格」(第9章)的雛形,我所采用的結構名稱和變量名稱,
都與MFC 相同,藉此讓你先有個暖身。

首先,定義一個MSGMAP_ENTRY 結構和一個dim 宏:
struct MSGMAP_ENTRY {
UINT nMessage;
LONG (*pfn)(HWND, UINT, WPARAM, LPARAM);
};
#define dim(x) (sizeof(x) / sizeof(x[0]))


請注意MSGMAP_ENTRY 的第二元素pfn 是一個函數指針,我准備以此指針所指之函
數處理nMessage 消息。這正是對象導向觀念中把「資料」和「處理資料的方法」封裝
起來的一種具體實現,只不過我們用的不是C++ 語言。
接下來,組織兩個數組_messageEntries[ ] 和_commandEntries[ ],把程序中欲處理的消
息以及消息處理例程的關聯性建立起來:


// 消息與處理例程之對照表格
struct MSGMAP_ENTRY _messageEntries[] =
{
      WM_CREATE,        OnCreate,
       WM_PAINT,             OnPaint,
      WM_SIZE,                OnSize,
      WM_COMMAND,     OnCommand,
      WM_SETFOCUS,     OnSetFocus,
      WM_CLOSE,            OnClose,
      WM_DESTROY,       OnDestroy,
} ;         ↑                              ↑
      這是消息             這是消息處理例程

//Command-ID與處理例程之對照表格
struct MSGMAP_ENTRY _commandEntries =
{
       IDM_ABOUT,          OnAbout,
       IDM_FILEOPEN,      OnFileOpen,
       IDM_SAVEAS,         OnSaveAs,
} ;         ↑                                   ↑
這是WM_COMMAND消息     這是消息處理例程


//----------------------------------------------------------------------
//於是窗口函數可以這麼設計:
//----------------------------------------------------------------------

//窗口函數:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,WPARAM wParam, LPARAM lParam)
{
int i;
for(i=0; i < dim(_messageEntries); i++){ //消息對照表
if (message == _messageEntries[i].nMessage)
return((*_messageEntries[i].pfn)(hWnd, message, wParam, lParam));
}
return(DefWindowProc(hWnd, message, wParam, lParam));
}


//----------------------------------------------------------------------
// OnCommand --專門處理WM_COMMAND
//----------------------------------------------------------------------


LONG OnCommand(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
int i;
for(i=0; i < dim(_commandEntries); i++) { //命令項對照表
if (LOWORD(wParam) == _commandEntries[i].nMessage)
return((*_commandEntries[i].pfn)(hWnd, message, wParam, lParam));
}
return(DefWindowProc(hWnd, message, wParam, lParam));
}


//-------------------------------------消息處理函數-------------------
LONG OnCreate(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
...
}

LONG OnAbout(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
...
}

......
//----------------------------------------------------------------------
        這麼一來,WndProc 和OnCommand 永遠不必改變,每有新要處理的消息,只要在
_messageEntries[ ] 和_commandEntries[ ] 兩個數組中加上新元素,並針對新消息撰寫新
的處理例程即可。
        這種觀念以及作法就是MFC 的Message Map 的雛形。MFC 把其中的動作包裝得更好
更精致(當然因此也就更復雜得多),成為一張龐大的消息地圖;程序一旦獲得消息,
就可以按圖上溯,直到被處理為止。我將在第3章簡單仿真MFC 的Message Map,並在
第9章「消息映射與繞行」中詳細探索其完整內容。

PS:《深入淺出MFC》(侯捷著) 是一本非常出色的書!

非常喜歡侯捷的一句話:程序設計領域裡,每一個人都想飛。但是,還沒學會走之前,連跑都別想!

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved