我正在尝试从 openweathermap.org api 中提取天气图标,并使用 u8g2 库(Arduino IDE,C++11)将它们显示在 ESP32 驱动的 OLED 显示器上。
在openweathermap.org weather api中,16种天气定义为
const *char[]
如"01d"
、"01n"
、"02d"
等
u8g2 库使用 unsigned char 数组来定义 XBM 位图格式的图标。我已经这样定义了所有图标:
static unsigned char icon01d[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...
}
可以通过以下方式在 OLED 上显示图标:
u8g2.drawXBMP( 96, 0, 32, 32, icon01d );
我想使用 std::map 将天气 api 中的字符串链接到指向图标的指针,例如:
map< string, unsigned char[]* > WEATHER_ICONS = {
{ "01d", &icon01d },
{ "01n", &icon01n },
...
};
然后(在我的幻想中)能够显示适当的图标,如:
u8g2.drawXBMP( 96, 0, 32, 32, *WEATHER_ICONS[ weatherIcon ] );
with weatherIcon 是
const *char[]
投射到一个字符串。
我尝试了各种替代方法来设置地图:
std::map< std::string, <<variable reference>> > WEATHER_ICONS = {
{ "01d", &icon01d },
{ "01n", &icon01n }
};
根据表格
<<variable reference>>
,我得到各种错误信息:
使用的变量引用 | 返回错误信息 |
---|---|
|
|
|
|
|
|
|
|
|
|
没有一条错误信息对我很有帮助。看来我已经到了“c 指针地狱”。
我在 stackoverflow 上看到关于定义指向指针数组的指针的建议,例如
unsigned char**
但我缺少足够的细节来让它工作。
什么是正确的解决方案?
作为解决方法,我已经实现了它:
if ( strcmp( weatherIcon, "01d" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon01d );
else if( strcmp( weatherIcon, "01n" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon01n );
else if( strcmp( weatherIcon, "02d" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon02d );
else if( strcmp( weatherIcon, "02n" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon02n );
else if( strcmp( weatherIcon, "03d" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon03d );
else if( strcmp( weatherIcon, "03n" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon03n );
else if( strcmp( weatherIcon, "04d" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon04d );
else if( strcmp( weatherIcon, "04n" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon04n );
else if( strcmp( weatherIcon, "09d" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon09d );
else if( strcmp( weatherIcon, "09n" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon09n );
else if( strcmp( weatherIcon, "11d" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon11d );
else if( strcmp( weatherIcon, "11n" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon11n );
else if( strcmp( weatherIcon, "13d" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon13d );
else if( strcmp( weatherIcon, "13n" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon13n );
else if( strcmp( weatherIcon, "50d" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon50d );
else if( strcmp( weatherIcon, "50n" )==0 ) u8g2.drawXBMP( 96, 0, 32, 32, icon50n );
有效,但不是很优雅。
在 C 和 C++ 中,评估数组的名称会产生指向数组中第一个值的指针。
你的
static unsigned char icon01d[]
真的是变相的unsigned char *
。所以:
map< string, unsigned char* > WEATHER_ICONS = {
{ "01d", icon01d },
{ "01n", icon01n },
...
};
从您的问题中不清楚是否有必要知道每个此类数组的大小。如果所有这些
unsigned char
数组的大小都相同,那么就可以了。否则,也许,你可以存储两者,吐出这样的东西:
map< string, tuple<unsigned char*, size_t> > WEATHER_ICONS = {
{ "01d", {icon01d, sizeof(icon01d)} },
{ "01n", {icon01n, sizeof(icon01n)} },
...
};
在您对
drawXBMP
的第一个示例调用中,您有:
u8g2.drawXBMP(96, 0, 32, 32, icon01d);
那么,在这种情况下,
icon01d
是什么?由于您传递的是不带索引的数组名称,因此您实际上传递的是指向数组中第一个元素的指针。在这种情况下,它是一个unsigned char*
.
当你声明你的地图时,这就是你应该使用的。像这样:
map<string, unsigned char*> WEATHER_ICONS = {
然后你应该像这样调用
drawXBMP
:
u8g2.drawXBMP(96, 0, 32, 32, WEATHER_ICONS[weatherIcon]);
看起来解决方案是:
std::map< std::string, unsigned char (*)[128] > WEATHER_ICONS = {
{ "01n", & icon01n },
{ "02d", & icon02d },
别问我怎么知道的..
感谢两位尝试回答问题,如果问题不清楚,我很抱歉。