web-dev-qa-db-ja.com

Cの連想配列

一連のデータをプログラム可能なドングルに転送する方法を実装しています。ドングルはスマートカードテクノロジーに基づいており、内部で任意のコードを実行できます。入力および出力データは、入力および出力ポインターを介してアクセスできるバイナリブロックとして渡されます。

連想配列を使用して、データ処理コードを簡素化したいと思います。すべてがこのように動作するはずです:

最初にホストアプリケーション:

// Host application in C++
in_data["method"] = "calc_r";
in_data["id"] = 12;
in_data["loc_a"] = 56.19;
in_data["loc_l"] = 44.02;
processor->send(in_data);

次に、ドングル内のコード:

// Some dongle function in C
char* method_name = assoc_get_string(in_data, "method");
int id = assoc_get_int(in_data, "id");
float loc_a = assoc_get_float(in_data, "loc_a");
float loc_l = assoc_get_float(in_data, "loc_l");

私の質問はドングル部分の機能についてです。上記のような連想配列の動作を実装するCコードまたはライブラリはありますか?

42
ezpresso

私の疑いは、あなたがあなた自身のものを書かなければならないということです。説明しているアーキテクチャを理解している場合、データのチャンク全体を1つのピースで送信する必要があります。そうだとすれば、ほとんどのライブラリはそのために動作しません。なぜなら、それらは複数のメモリを割り当てている可能性が高く、そのために複数の転送が必要になるからです(そして構造の内部理解)。ライブラリハッシュ関数を使用して、send関数にルートポインターを渡すだけで、そのコンテンツをソケット上のネットワーク経由で送信するのと似ています。

単一のメモリブロックで非常に単純な連想配列(またはハッシュ)を管理する独自のユーティリティを作成することが可能です。データの量が少ない場合、エントリに対して単純な線形検索を使用でき、かなりコンパクトなコードになります。

10
Mark Wilkins

Glibのハッシュテーブル マップインターフェイスまたは(連想配列)を実装します。そして、Cで最もよく使用されるハッシュテーブル実装です。

GHashTable *table=g_hash_table_new(g_str_hash, g_str_equal);

/* put */
g_hash_table_insert(table,"SOME_KEY","SOME_VALUE");

/* get */
gchar *value = (gchar *) g_hash_table_lookup(table,"SOME_KEY");
22

Cでハッシュテーブルを実装するヘッダーライブラリである thash を試してください。これは小さく、かなり簡単に使用できます。

10
Hasturkun

はい。ただし、指定した方法では機能しません。代わりにstructを使用して、その構造体で動作するデータと関数を保存し、必要な結果を提供します。 Cの単純な連想配列ライブラリ を参照してください。使用例:

struct map_t *test;

test=map_create();
map_set(test,"One","Won");
map_set(test,"Two","Too");
map_set(test,"Four","Fore");
3
James

GLibの Hash Tables および Balanced Binary Trees はあなたが望んでいるものかもしれません。

2
Matt Joiner

これは古いスレッドですが、実装を探している人にとってはこれがまだ役立つと思いました。あまり多くのコードを必要としません。私は、追加のライブラリなしで最大100行で作業を行いました。 pythonデータ型に対応しているので)辞書と呼んでいます。コードは次のとおりです。

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

typedef struct hollow_list hollow_list;

struct hollow_list{
    unsigned int size;
    void *value;
    bool *written;
    hollow_list *children;
};

//Creates a hollow list and allocates all of the needed memory
hollow_list hollow_list_create(unsigned int size){
    hollow_list output;
    output = (hollow_list) {.size = size, .value = (void *) 0, .written = calloc(size, sizeof(bool)), .children = calloc(size, sizeof(hollow_list))};
    return output;
}

//Frees all memory of associated with a hollow list and its children
void hollow_list_free(hollow_list *l, bool free_values){
    int i;
    for(i = 0; i < l->size; i++){
        hollow_list_free(l->children + i, free_values);
    }
    if(free_values){
        free(l->value);
    }
    free(l);
}

//Reads from the hollow list and returns a pointer to the item's data
void *hollow_list_read(hollow_list *l, unsigned int index){
    if(index == 0){
        return l->value;
    }
    unsigned int bit_checker;
    bit_checker = 1<<(l->size - 1);
    int i;
    for(i = 0; i < l->size; i++){
        if(bit_checker & index){
            if(l->written[i] == true){
                return hollow_list_read(l->children + i, bit_checker ^ index);
            } else {
                return (void *) 0;
            }
        }
        bit_checker >>= 1;
    }
}

//Writes to the hollow list, allocating memory only as it needs
void hollow_list_write(hollow_list *l, unsigned int index, void *value){
    if(index == 0){
        l->value = value;
    } else {
        unsigned int bit_checker;
        bit_checker = 1<<(l->size - 1);
        int i;
        for(i = 0; i < l->size; i++){
            if(bit_checker & index){
                if(!l->written[i]){
                    l->children[i] = hollow_list_create(l->size - i - 1);
                    l->written[i] = true;
                }
                hollow_list_write(l->children + i, bit_checker ^ index, value);
                break;
            }
            bit_checker >>= 1;
        }
    }
}

typedef struct dictionary dictionary;

struct dictionary{
    void *value;
    hollow_list *child;
};

dictionary dictionary_create(){
    dictionary output;
    output.child = malloc(sizeof(hollow_list));
    *output.child = hollow_list_create(8);
    output.value = (void *) 0;
    return output;
}

void dictionary_write(dictionary *dict, char *index, unsigned int strlen, void *value){
    void *hollow_list_value;
    dictionary *new_dict;
    int i;
    for(i = 0; i < strlen; i++){
        hollow_list_value = hollow_list_read(dict->child, (int) index[i]);
        if(hollow_list_value == (void *) 0){
            new_dict = malloc(sizeof(dictionary));
            *new_dict = dictionary_create();
            hollow_list_write(dict->child, (int) index[i], new_dict);
            dict = new_dict;
        } else {
            dict = (dictionary *) hollow_list_value;
        }
    }
    dict->value = value;
}

void *dictionary_read(dictionary *dict, char *index, unsigned int strlen){
    void *hollow_list_value;
    dictionary *new_dict;
    int i;
    for(i = 0; i < strlen; i++){
        hollow_list_value = hollow_list_read(dict->child, (int) index[i]);
        if(hollow_list_value == (void *) 0){
            return hollow_list_value;
        } else {
            dict = (dictionary *) hollow_list_value;
        }
    }
    return dict->value;
}

int main(){
    char index0[] = "hello, this is a test";
    char index1[] = "hello, this is also a test";
    char index2[] = "hello world";
    char index3[] = "hi there!";
    char index4[] = "this is something";
    char index5[] = "hi there";

    int item0 = 0;
    int item1 = 1;
    int item2 = 2;
    int item3 = 3;
    int item4 = 4;

    dictionary d;
    d = dictionary_create();
    dictionary_write(&d, index0, 21, &item0);
    dictionary_write(&d, index1, 26, &item1);
    dictionary_write(&d, index2, 11, &item2);
    dictionary_write(&d, index3, 13, &item3);
    dictionary_write(&d, index4, 17, &item4);

    printf("%d\n", *((int *) dictionary_read(&d, index0, 21)));
    printf("%d\n", *((int *) dictionary_read(&d, index1, 26)));
    printf("%d\n", *((int *) dictionary_read(&d, index2, 11)));
    printf("%d\n", *((int *) dictionary_read(&d, index3, 13)));
    printf("%d\n", *((int *) dictionary_read(&d, index4, 17)));
    printf("%d\n", ((int) dictionary_read(&d, index5, 8)));
}

残念ながら、list [x]構文を複製することはできませんが、これは私が思いついた最良の代替案です。

2
2.71828-asy

マーク・ウィルキンスはあなたに正しい答えを与えました。データを単一のチャンクとして送信する場合は、アーキテクチャーでC++マップがどのように表されるかを理解し、アクセス関数を記述する必要があります。

とにかく、もしあなたがドングルで地図を再作成することに決めたら、あなたが書くことができる小さなCライブラリを書きました。

tbl_t in_data=NULL;

tblSetSS(in_data,"method","calc_r");
tblSetSN(in_data,"id",12);
tblSetSF(in_data,"loc_a",56.19);
tblSetSF(in_data,"loc_l",44.02);

その後:

char  *method_name = tblGetP(in_data, "method");
int    id          = tblGetN(in_data, "id");
float  loc_a       = tblGetF(in_data, "loc_a");
float  loc_l       = tblGetF(in_data, "loc_l");

ハッシュテーブルはHopscotchハッシュのバリエーションであり、平均的にかなり良好であり、キーとデータのタイプを任意に組み合わせることができます(つまり、テーブル全体をキーとして使用できます)。

その関数の焦点は純粋な速度ではなくプログラミングの緩和にあり、コードは徹底的にテストされていませんが、アイデアが気に入って拡張したい場合は、 googlecode のコードを見ることができます。

(可変長文字列や高速なパターンマッチング関数のような他のものがありますが、これらはこの場合には興味がないかもしれません)。

2
Remo.D