[英]Associative arrays in 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 代碼或庫來實現像上面這樣的關聯數組行為?
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");
我的懷疑是你必須自己寫。 如果我理解您所描述的架構,那么您將需要將整個數據塊發送到一個單獨的部分。 如果是這樣,那么大多數庫都不會為此工作,因為它們很可能會分配多塊內存,這將需要多次傳輸(以及對結構的內部理解)。 這類似於嘗試使用庫哈希函數,然后僅通過將根指針傳遞給send
函數,通過套接字在網絡上發送其內容。
可以編寫一些自己的實用程序,在單個內存塊中管理一個非常簡單的關聯數組(或散列)。 如果數據量很小,它可以對條目使用簡單的線性搜索,這將是一段相當緊湊的代碼。
試試uthash ,這是一個在 C 中實現哈希表的頭庫。它很小而且很容易使用。
這是一個舊線程,但我認為這對於尋找實現的人來說可能仍然有用。 不需要太多代碼; 我在沒有任何額外庫的情況下用了大約 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] 語法,但這是我提出的最佳替代方案。
是的,但它不會按照您指定的方式工作。 相反,它將使用一個struct
來存儲對該struct
進行操作的數據和函數,從而為您提供所需的結果。 請參閱C 中的簡單關聯數組庫。 使用示例:
struct map_t *test;
test=map_create();
map_set(test,"One","Won");
map_set(test,"Two","Too");
map_set(test,"Four","Fore");
馬克威爾金斯給了你正確的答案。 如果您想將數據作為單個塊發送,您需要了解 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上的代碼。
(還有其他東西,如可變長度字符串和快速字符串模式匹配函數,但在這種情況下可能不感興趣)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.