问题 在C中执行查找表的最佳方法是什么?


我正在开发一个嵌入式C项目。我有一个LCD显示屏,每个字符有一个5x7点阵。要显示特定字符​​,您必须以5个字节移动,这些字节与要打开的点相关联。所以我需要使用一个键来制作某种查找表,我可以传入一个ASCII字符,然后返回一个包含5个字节的数组... 例如,像这样调用这个函数,

GetDisplayBytes('A'); 

应该返回`这样的数组......

C[0] = 0x7E : C[1] = 0x90 : C[2] = 0x90 : C[3] = 0x90 : C[4] = 0x7E

在C中这样做的最佳方法是什么?


11503
2017-08-04 18:19


起源

你的速度和记忆统计数据是多少:多快和多少RAM? - Hamish Grubijan
好吧,我可能会将它存储在闪存中,这样我就不会耗尽宝贵的RAM。我还没有任何特定的速度或尺寸要求,但我猜最小的将优先于最快。 - PICyourBrain
没有答案指明这一点,但我相信数组应该是静态的。 - Kurt E. Clothier


答案:


我会为你想要使用的连续ASCII块创建数组。数据。像这样的东西:

uint8_t displayBytesLetters[] = 
{
  0x73, 0x90, 0x90, 0x90, 0x73, // 'A'
  .
  .
  .
};

uint8_t displayBytesDigits[] = 
{
  0x12, 0x15, 0x25, 0x58, 0x80, // '0'
  .
  .
  .
};

然后你的 GetDisplayBytes() 是这样的:

uint8_t *GetDisplayBytes(char c)
{
  if (isdigit(c))
    return &displayBytes[5*(c - '0')];
  else if (isupper(c))
    return &displayBytes[5*(c - 'A')];
  else
    return NULL;
}

将返回的指针传递给任何函数输出数据:

void DoDisplay(uint8_t *displayBytes)
{
  int i;
  for (i = 0; i < 5; i++) 
  {
     SendOutput(displayBytes[i]);
  }
}

14
2017-08-04 18:23



这很好但是如果我不想使每个ASCII值可用于打印。假设我只想要大写字母,数字和几个符号(<,>,!,?)。在这种情况下,你的方法不会要求我使用不必要的内存空间。 - PICyourBrain
对不起,我应该在问题中指明一下...... - PICyourBrain
@Jordan S,然后为每个非连续的ascii块使用不同的查找表。我将用一个例子编辑我的答案。 - Carl Norum
然后,代替 (c - 'A'),编写一个函数/宏,它将把你支持的ASCII字符作为输入,并作为输出返回一个索引号(有点像迷你哈希函数)。您可能也想要处理非法字符输入。 - Santa
您是否还要添加一个如何调用GetDisplayBytes来演示如何遍历5个字节的示例。 - PICyourBrain


typedef char LCDDATA[5];   

LCDDATA lcdTable[256] = { {0,0,0,0,0},  // char 0
                          {.....},       // char 1
                        }

LCDDATA GetDisplayBytes(char chr)
{
     return lcdTable[chr];
}

这基本上是一个数组的数组。


2
2017-08-04 18:24



没有理由这种方法不能像卡尔那样进行。 - James Curran
+1用于正确打字而不是用算术玩游戏。但是有些小事:你的原型应该是 LCDDATA GetDisplayBytes(unsigned char chr) 并且使用所有大写字母的类型名称也是不常见的,通常这些大写是为宏保留的。 - Jens Gustedt
@Jens:我曾经用宏做过这个,习惯很紧张。 - James Curran
为数组创建类型定义是非常值得怀疑的。我不确定这甚至会编译(函数声明器上的数组返回类型)。应该在struct中包装数组以确保它 LCDDATA 可以分配项目,并且不会发生自动阵列衰减。 - user694733