12

我正在尝试让哈希表或字典在 Arduino Mega 2560 上工作。我的目标是拥有类似的东西

dictionary[ENGLISH]["ACCOUNT"] = "Account";
dictionary[ENGLISH]["DATE_AND_TIME"] = "Date and Time";
dictionary[ENGLISH]["IDLE"] = "Idle";
dictionary[ENGLISH]["Language"] = "Languge"
dictionary[ENGLISH]["MAIN_MENU"] = "Main Menu";
dictionary[ENGLISH]["PRESCRIPTION"] = "Prescription";
dictionary[ENGLISH]["SETTINGS"] = "Settings";
dictionary[ENGLISH]["SOUND"] = "Sound";

其中 ENGLISH 本质上是一个常数 0,我也会有 SPANISH 和 FRENCH(分别为 1 和 2)。也就是说,一个包含 3 个字典元素的数组。

在第一次 Google 搜索中,我找到了一个指向 C++ STL 建模库的链接,但它根本不适用于我的 Arduino 1.0.3。我想知道是否有人可以为我在 arduino 中使用地图/哈希表的替代方法,或者修复以使提到的库正常工作。

对于我的情况,我正在通过 Arduino 上的触摸屏对菜单系统进行建模,它必须接受 3 种语言(用于按钮)。所选语言位于 EEPROM 中的某个位置,我将其保存在变量 'lang' 中,当我需要在屏幕上打印某些内容时,我会执行以下操作:

    screen.print(dictionary[lang]["SOUND"], CENTER, 23);

并且根据用户选择的“语言”,理想情况下,它将相应地打印。

4

3 回答 3

27

我认为这里可能不需要哈希表,无论如何在这个平台上都有很好的理由避免它。

为什么哈希表可能是不必要的

通常在这种情况下,不需要字符串键,因为键仅在代码内部可见,并且不会与程序外部交互。因此,通常的解决方案是拥有一个(伪)整数键,其形式#define由预处理器而不是您的程序处理:

#define kWORDIDX_LANGUAGE   1
#define kWORDIDX_SOUND      2
#define kWORDIDX_MAINMENU   3
#define kWORDIDX_SPAGHETTI  4
...
dictionary[ENGLISH][kWORDIDX_SOUND] = "Sound";
...

然后,您可以像这样Sreen.print(dictionary[lang][kWORDIDX_SOUND], CENTER, 23);或类似的东西访问您的字典条目。

这种方法的优点是:

  • 您正在节省内存空间:不使用字符串键
  • 您正在节省处理时间:虽然哈希表访问在技术上是 O(1),但仍然涉及到计算哈希的常量因素。数组访问速度更快。
  • 您的代码不太容易出错:如果您使用字符串访问(无论如何都是幻数的一种形式)拼错了您的密钥,您将得到一个哈希表未命中。如果你拼错了其中一个#defined 键,你会得到一个编译错误,这就是你想要的

为什么你不想要 Arduino 上的哈希表

Arduino 是一个内存受限的平台:它的内存非常有限。使用真正的哈希映射的问题如下:

  • int字符串(通常)占用更多的内存空间。使用#define由编译器转换为整数文字的键,每个键使用 1、2 或 4 个字节(取决于您的编译器设置),而每个字符串键都需要strlen(s) + 1存储空间。这个空间实际上被使用了两次:一次在闪存中(即变量初始化的地方),一次在 SRAM 中。
  • 哈希映射数据结构本身占用更多内存:哈希映射中的空条目(在开放寻址方案中)或链表(在单独的链接方案中)存在开销。由于您的数据是只读的,因此您不需要该开销,因为不会添加哈希表。
  • 人们用来在 Arduinos 中保存内存的一个技巧是使用关键字将只读数据(例如字符串)仅存储在程序内存(而不是 SRAM)中PROGMEM。如果您使用哈希映射构建字典,则您将无法使用此路由。另一方面,给定#define上面的 -type 索引方案,将所有语言字符串存储为字符串将非常容易PROGMEM
于 2013-03-31T16:58:29.353 回答
9

您还可以使用数据结构来定义字典:

typedef struct { 
  uint8_t lang;
  char* sound;
  char* value;
} langDictionary;

然后,您可以使用要使用的值定义结构数组:

const langDictionary myDictionaryArr[] {
    {0, "ENGLISH", "Settings"},
    {1, "SPANISH", "Ajustes"},
    {2, "FRENCH", "Paramètres"}
};

最后,您可以使用数组来搜索属性:

void setup() {
  Serial.begin(115200);
  for(uint8_t i = 0; i < sizeof(myDictionaryArr)/sizeof(langDictionary); ++i) {
      Serial.println(myDictionaryArr[i].value); //Prints the values: "Settings", "Ajustes" and "Paramètres"
  }
}
于 2017-07-28T14:38:49.923 回答
4

虽然我完全同意前面的答案,但arduino 游乐场有“ Arduino HashMap 库”。

于 2013-06-27T22:28:04.683 回答