- 論壇徽章:
- 0
|
實際情況是這樣的,我想寫一個某格式文件的parser,當parser運行時,將調用使用者自定義的callback,一般而言,callback會將parse_data(parse出來的data)整理成user_data(使用者的data),這樣就可將parse與使用者的業(yè)務邏輯在代碼上分開。但是遇到一個問題,看如下的示例代碼吧。代碼中我將parse的動作,用一個簡單的while loop來代替了。ya_my_cbk_3中,我將對user_data的搜集用一個簡單的求和代替了,實際情況parse會做正常的parse文件的動作,搜集user_data可能會將user_data放到一個大的數(shù)據(jù)結構比如list中去。
parse.h
- //////////////////////////////////////////////////////////////////////////////////////
- #ifndef PARSE_H_INCLUDED
- #define PARSE_H_INCLUDED
-
- typedef int parse_data_t; // parse_data_t可能比較復雜,這里只用int來舉例
- typedef void (*cbk_t) (parse_data_t, void*); //callback type也可能比較多,這里只用一個
-
- // 三個默認的callback
- cbk_t cbk_1 = 0;
- cbk_t cbk_2 = 0;
- cbk_t cbk_3 = 0;
-
- // 暴露給使用者重定義callback
- void set_cbk_1(cbk_t cbk) {
- cbk_1 = cbk;
- }
- void set_cbk_2(cbk_t cbk) {
- cbk_2 = cbk;
- }
- void set_cbk_3(cbk_t cbk) {
- cbk_3 = cbk;
- }
-
- // parse的類型,實際可能有其它成員,這里只放了幾個user_data,為了能在parse時方便的調用到。
- typedef struct {
- void* user_data_1;
- void* user_data_2;
- void* user_data_3;
- } parse_t;
-
- //簡單初始化,這一步沒有也可以。
- void parse_init(parse_t* parse) {
- parse->user_data_1 = 0;
- parse->user_data_2 = 0;
- parse->user_data_3 = 0;
- }
-
- // parse過程,用一個簡單的循環(huán)來模擬,當cbk_N不是默認值時,調用使用者自定義的callback.
- void parse_run(parse_t* parse) {
- int i = 0;
- while(i++ < 100) {
- if (i == 11) {
- if (cbk_1) {
- cbk_1((parse_data_t)i, parse->user_data_1);
- }
- } else if (i == 21) {
- if (cbk_2) {
- cbk_2((parse_data_t)i, parse->user_data_2);
- }
- } else if (i > 0 && i < 11) { //parse在這里會調用多次callback
- if (cbk_3) {
- cbk_3((parse_data_t)i, parse->user_data_3);
- }
- }
- }
- }
-
- #endif // PARSE_H_INCLUDED
復制代碼 main.c
- //假設使用者的代碼在main.c里面
- //////////////////////////////////////////////////////////////////////////////////////
- #include <stdio.h>
- #include "parse.h"
-
- //自定義的callback,將parse_data整理成user_data
- void my_cbk_1_2 (parse_data_t parse_data, void* user_data) {
- // just an example
- // simply assign parse_data to user_data;
- *(parse_data_t*)user_data = parse_data;
- }
-
- // 下面兩個callback在parse_run時會被多次調用。
- // 其中一個callback
- // 如果將user_data送進去,最后user_data只會是最后parse到的那個值
- // assign parse_data to user_data every callback invoking
- void my_cbk_3 (parse_data_t parse_data, void* user_data) {
- *(parse_data_t*)user_data = parse_data;
- }
-
-
- // 另外一個callback,模擬將user_data搜集起來。
- // yet another callback to add user_data_3 to sum_for_user_data_3
- int sum_for_user_data_3 = 0; //就是這個讓我心痛的全局變量哇~~~~
- void ya_my_cbk_3(parse_data_t parse_data, void* user_data) {
- *(parse_data_t*)user_data = parse_data;
- sum_for_user_data_3 += *(int*)user_data;
- }
-
- int main()
- {
- set_cbk_1(my_cbk_1_2);
- set_cbk_2(my_cbk_1_2);
- //set_cbk_3(my_cbk_3); //如果用這個cbk給cbk_3,最后user_data_3只會是parse過程的最后一個值
- set_cbk_3(ya_my_cbk_3); //如果用這個cbk給cbk_3,就要用那個全局的變量。
-
- int my_user_data_1;
- int my_user_data_2;
-
- int my_user_data_3;
-
- parse_t parse;
- parse_init(&parse);
- parse.user_data_1 = &my_user_data_1;
- parse.user_data_2 = &my_user_data_2;
- parse.user_data_3 = &my_user_data_3;
- parse_run(&parse);
-
- printf("my_user_data_1 : %d\n", my_user_data_1);
- printf("my_user_data_2 : %d\n", my_user_data_2);
- //printf("my_user_data_3 : %d\n", my_user_data_3);
- printf("sum_for_user_data_3 : %d\n", sum_for_user_data_3);
-
- return 0;
- }
復制代碼 上面代碼可以編譯通過。我本意是希望使用者可以自定義callback來使用parse_data,將他所需的parse_data整理成user_data。如果callback只會調用一次,我可以將user_data在parse里各放一份引用。
但當同一個callback被調用多次時(比如while循環(huán)中的那個 else if (i > 0 && i < 11)),那個user_data會被不停地覆蓋,但又不能跑多少次callback就申明多少個user_data,因為到底跑多少次callback是不一定的事。所以每次callback要將user_data搜集起來,可看來看去,這個搜集到的地方,只能是全局變量。
我不想讓user_data只能被搜集到全局變量,是哪里出錯了嗎?
求教啊 |
|