0

次のタスクを実行するアプリケーションが 1 つあります。

1.) UI application will send command code (integer value).
2.) DLL interface(in c++) will get that integer value and execute corresponding command function.

コマンド名とコマンド コードは次のように維持されます。

#define PING 50

500 個のコマンドがあり、SWITCH CASE を適用するとうまく聞こえません。だから私は以下のように私のコードに関数ポインタを実装することにしました

   #include "stdafx.h"

    #include<iostream>
    #define PING 20

    using namespace std;
    //extern const int PING = 10; 
    void ping()
    { 
                    cout<<"ping command executed";
    }


    void get_status(void)
    {


    cout<<"Get_status called"<<endl;

    }

    class ToDoCommands
    {
            public:
                void getCommand( void (*CommandToCall)() );                         
    };



    void ToDoCommands::getCommand( void (*CommandToCall)())
    {


        void (*CommandToCall1)();

        CommandToCall1  = CommandToCall;

        CommandToCall1();

    }

    int main()
    {
            int code;
            ToDoCommands obj;
            cout<<"enter command code";
            cin>>code;  // if UI send 50 then Ping function get executed as #define PING 50

            obj.getCommand(ping);   // here m passing ping manually..
            //obj.getCommand(get_status);

                return 0;
    }

コマンドコードに対応するコマンド名を渡すにはどうすればよいですか

obj.getCommand(ping); 
4

3 に答える 3

3

関数へのポインタを作成し、文字列名std::mapstd::string対応する関数ポインタにペアリングするデータで初期化し、実行時にそのマップを使用して、渡された文字列パラメータに基づいて正しいポインタを選択します。

#include <iostream>
#include <string>
#include <map>

using namespace std;

void ping() {
    cout << "ping" << endl;
}
void test() {
    cout << "test" << endl;
}
int main() {
    map<string,void(*)()> m;
    m["ping"] = ping;
    m["test"] = test;
    // I am using hard-coded constants below.
    // In your case, strings will come from command line args
    m["test"]();
    m["ping"]();
    return 0;
}

でデモにリンクしstd::mapます。

なしでそれを行う方法はmap次のとおりです(線形検索のために遅くなりますが、名前をアルファベット順に並べてバイナリ検索を使用することで修正できます)。

#include <iostream>
#include <cstring>

using namespace std;

void ping() {
    cout << "ping" << endl;
}
void test() {
    cout << "test" << endl;
}
typedef void (*fptr_t)();
int main() {
    const fptr_t fptrs[] = {test, ping};
    const char *names[] = {"test", "ping"};
    const char *fname = "test";
    for (int i = 0 ; i != 2 ; i++) {
        if (!strcmp(fname, names[i])) {
            fptrs[i]();
            break;
        }
    }
    return 0;
}

配列を使用してデモにリンクします。

于 2012-09-17T10:32:34.330 に答える
0

@dasblinkenlightは正しいと言えますが、std :: mapを使用したくない場合は、自分でマップを実装する必要があります。これはバグがあり、最適化された方法ではない可能性がありますが、STLを使用したくない場合は、自分で実装する必要があるようです。

対応するインデックスを持つ2つの配列を使用できます。それらchar *の1つは配列であり、もう1つは関数ポインターです。MyMapのような名前のクラスにカプセル化することをお勧めします。

class MyMap {
  public:
    ...

    inline void add(char *name, (void (*ptr)(void)) ) {
      names_[currIndex_] = name; // Or stcpy
      ptrs_[currIndex_] = ptr;
      currIndex_++;
    }

    inline (void(*)(void)) get(char *name) {
      int foundIndex = -1;
      for (int i = 0; i < currIndex_; i++) {
        // Find matching index
      }
      if (foundIndex_ >= 0) {
        return ptrs_[foundIndex_];
      }
      return NULL;
    }

  private:
    int currIndex_;
    char *names_[10];
    (void (*ptrs_[10])(void));
};
于 2012-09-17T10:43:13.230 に答える
0

関数ポインターの配列を宣言します。インデックスを「コード」として扱う場所。例えば:

void foo(){
    printf("foo\n");
}

void bar(){
    printf("bar\n");
}

int main(void)
{
    void (*code_to_function[100])();
    int code;

    code_to_function[0] = foo;
    code_to_function[1] = bar;
    printf("Enter code: ");
    scanf("%d", &code);
    code_to_function[code]();

    return 0;
}

この初歩的な例では、0 と 1 以外の整数コードを入力すると、segfault が発生することに注意してください。

于 2012-09-17T10:46:28.367 に答える