Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 三维字符串数组_C++_Arrays_Arduino_Progmem - Fatal编程技术网

C++ 三维字符串数组

C++ 三维字符串数组,c++,arrays,arduino,progmem,C++,Arrays,Arduino,Progmem,我正在尝试制作一个LCD项目(16x2),它可以循环浏览一组消息。其想法是,它将循环浏览当前选定组中的所有消息,并且在手动更改之前不会离开该组。最初我有一个3D数组:级别1是消息组,级别2是要显示的消息,级别3是行 #define WIDTH 16 #define HEIGHT 2 #define NGRP 3 #define MAXGRP 6 String mainMsgs[NGRP][MAXGRP][HEIGHT] = { {

我正在尝试制作一个LCD项目(16x2),它可以循环浏览一组消息。其想法是,它将循环浏览当前选定组中的所有消息,并且在手动更改之前不会离开该组。最初我有一个3D数组:级别1是消息组,级别2是要显示的消息,级别3是行

#define WIDTH 16
#define HEIGHT 2
#define NGRP 3 
#define MAXGRP 6
String mainMsgs[NGRP][MAXGRP][HEIGHT] = { 
                      {
                       {"Value 1","Value 2"},
                       {"Value 3","Value 4"},
                       {"Value 5","Value 6"},
                       {"Value 7","Value 8"},
                       {"Value 9","Value 10"},
                      },
                      {
                       {"Value 1","Value 2"},
                       {"Value 3","Value 4"},
                       {"Value 5","Value 6"},
                       {"Value 7","Value 8"},
                       {"Value 9","Value 10"},
                       {"Value 9","Value 10"},
                       {"Value 11","Value 12"},
                      },
                      {
                       {"Value 1","Value 2"},
                       {"Value 3","Value 4"},
                       {"Value 5","Value 6"},
                       {"Value 7","Value 8"},
                      }
})

我让它或多或少地工作,但我认为数组太大了,内存不够,因为在第3组进行到一半时,它停止显示消息。当我测试它时,数组索引总是正确的。我假设数组已被截断。在尝试解决此问题时,我遇到了PROGMEM。我尝试在以下位置转换arduino字符串教程: 从一维数组转换为三维数组,但无法使其工作,它要么编译失败,要么返回垃圾。下面是我的几次尝试

const char message1[][2] PROGMEM = { "Value 1", "Value 2" }; // Through to message15
const char* const group1[][5] PROGMEM = { message1, message2, message3, message4, message5 };
const char* const group2[][6] PROGMEM = { message6, message7, message8, message9, message10, message11 };
const char* const group3[][4] PROGMEM = { message12, message13, message14, message15 };
const char* const groups[] PROGMEM = { group1, group2, group3 }; // Attempt 1
const char* const groups[NUMGRP][6] PROGMEM = { 
                                        {message1, message2, message3, message4, message5}, 
                                        {message6, message7, message8, message9, message10, message11}, 
                                        {message12, message13, message14, message15}, 
                                      }; // Attempt 2
因此,我尝试使用

const char* const mainMsgs[NUMGRP][6][HEIGHT] = { /* same content as before*/ };
strcpy_P(buff, (char*)pgm_read_word(&(mainMsgs[groupID][msgID][i])));
但它仍然返回垃圾。 因此,我想我应该尝试将数据转换成一维数组,然后使用偏移量访问消息和行

编辑:编辑以下代码以反映我在原始草图中使用的代码

const char message1[] = "Value 1";
const char message2[] = "Value 2"; // Down to message30
const char* const messages[] PROGMEM = { message1, message2,
                    message3, message4,
                    // ... ... ...
                    message29, message30
                  };
int groupStarts[] = { 0, 10, 22 }; // The first index of each group
int numMsgs[] { 5, 6, 4 };
char buff[WIDTH];
这是我使用的测试循环:

int id = 0;
for( groupID = 0; groupID < NGRP; groupID++ ) {
   for( msgID = 0; msgID < numMsgs[groupID]*HEIGHT; msgID+=HEIGHT ) {
     for( lineID = 0; lineID < HEIGHT; lineID++ ) {
       id = groupStarts[groupID] + msgID + lineID;
       strcpy_P(buff, (char*)pgm_read_word(&(messages[id])));
       Serial.print(id);
       Serial.print(" ");
       Serial.print(buff);
     }
     Serial.println("");
     delay(500);
   }
}
您可能会注意到,没有显示值10,值11和12重复两次,当它达到值19时,它只是卡在一个无限循环中

我不太清楚最后的循环应该是什么

理想情况下,我更愿意保留3D数组结构,因为我发现它更易于阅读和理解,但我很乐意为这两个版本的代码提供解决方案

编辑以反映shuttle87的建议:

#include <avr/pgmspace.h>

#define WIDTH 16
#define HEIGHT 2

const char string1[] PROGMEM = "Message 1";
const char string2[] PROGMEM = "Message 2";
const char string3[] PROGMEM = "Message 3";
const char string4[] PROGMEM = "Message 4";
const char string5[] PROGMEM = "Message 5";
const char string6[] PROGMEM = "Message 6";

const int groupLen[] = { 2, 3, 1 };

const char* msgs[][3][2] = {
  {
    {string1, string2 },
    {string3, string4 }
  },
  {
    {string5, string6 },
    {string3, string4 },
    {string1, string2 }
  },
  {
    {string2, string3 }
  }
};

char buffer[WIDTH];

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  for( int g = 0; g < 3; g++ ) {
    Serial.print("Switching to group: ");
    Serial.println(g);
    for( int m = 0; m < groupLen[g]; m++ ) {
      Serial.print("Switching to message: ");
      Serial.println(m);
      for( int l = 0; l < HEIGHT; l++ ) {
        Serial.print("Switching to line: ");
        Serial.println(l);
         strcpy_P(buffer, (char*)pgm_read_word(&(msgs[g][m][l])));
         Serial.println(buffer);
      }
      delay(500);
    }
  }
}
本应开始:

const char* const messages[][3][2] PROGMEM= {
      {
        {string1, string2 },
        {string3, string4 }
      },
      {
        {string5, string6 },
        {string3, string4 },
        {string1, string2 }
      },
      {
        {string2, string3 }
      }
    };
很抱歉。这似乎已经解决了这个问题。非常感谢您的帮助:)


谢谢。

您的大多数尝试都有相同的问题,您已将指向表的指针存储在progmem中,但实际的表数据本身(在本例中为字符串)未存储在progmem中。不幸的是,GCC属性(从GCC4.7开始)只适用于当前声明,因此必须在每个变量上指定progmem

所以当你有

 const char message1[][2] PROGMEM = { "Value 1", "Value 2" };
message1
存储在progmem中,但字符串
“Value 1”
不存储。此外,如果我没记错的话,AVRCC编译器总是在SRAM中存储字符串文本。即使您指定了一个位置将它们放在progmem中,它仍然会复制到SRAM中(有一次我试图编写一个库,使用c++11用户定义的字符串文本将它们放在progmem中,但这让我很失望)。一维数组解决方案也会遇到同样的问题

要解决此问题,请将所有内容显式存储在progmem中,例如,1D解决方案如下所示:

const char string_msg0_0[] PROGMEM = "Value 1";
const char string_msg0_1[] PROGMEM = "Value 2";

PGM_P strings_pgm_table[] PROGMEM = {string_msg0_0, string_msg0_1};

char buffer[MAX_STRING_SIZE];
strcpy_P(buffer, (PGM_P)pgm_read_word(&(strings_pgm_table[i])));

我建议您看看。

大多数尝试都有相同的问题,您已将指向表的指针存储在progmem中,但实际的表数据本身(在本例中为字符串)未存储在progmem中。不幸的是,GCC属性(从GCC4.7开始)只适用于当前声明,因此必须在每个变量上指定progmem

所以当你有

 const char message1[][2] PROGMEM = { "Value 1", "Value 2" };
message1
存储在progmem中,但字符串
“Value 1”
不存储。此外,如果我没记错的话,AVRCC编译器总是在SRAM中存储字符串文本。即使您指定了一个位置将它们放在progmem中,它仍然会复制到SRAM中(有一次我试图编写一个库,使用c++11用户定义的字符串文本将它们放在progmem中,但这让我很失望)。一维数组解决方案也会遇到同样的问题

要解决此问题,请将所有内容显式存储在progmem中,例如,1D解决方案如下所示:

const char string_msg0_0[] PROGMEM = "Value 1";
const char string_msg0_1[] PROGMEM = "Value 2";

PGM_P strings_pgm_table[] PROGMEM = {string_msg0_0, string_msg0_1};

char buffer[MAX_STRING_SIZE];
strcpy_P(buffer, (PGM_P)pgm_read_word(&(strings_pgm_table[i])));

我建议您看看。

您需要使用progmem指针来指向存储在progmem中的字符串。这不是什么:strcpy_p(buff,(char*)pgm_read_word(&(mainMsgs[groupID][msgID][I]);是吗?如果你已经回答了你的问题,在回答中写出来,而不是编辑问题。此外,编辑内容足够丰富,最好将其作为一个单独的问题发布,以避免将其变成看起来像一个问题的风险。你想要避免这种情况的原因,特别是像这样难以回答的问题,是因为像我这样厌倦了网站的用户会把这看作是一个危险信号,而不太愿意花时间去帮助别人。更清楚的是,我非常乐意帮上忙,以后只需发布其他问题,而不是进行大量编辑。您需要使用progmem指针指向progmem中存储的字符串。这不是什么:strcpy_P(buff,(char*)pgm_read_word(&(mainMsgs[groupID][msgID][i]);是吗?如果你已经回答了你的问题,在回答中写出来,而不是编辑问题。此外,编辑内容足够丰富,最好将其作为一个单独的问题发布,以避免将其变成看起来像一个问题的风险。你想要避免这种情况的原因,特别是像这样难以回答的问题,是因为像我这样厌倦了网站的用户会把这看作是一个危险信号,而不太愿意花时间去帮助别人。更清楚的是,我非常乐意帮上忙,以后只需发布其他问题,而不是进行大量编辑。您需要使用progmem指针指向progmem中存储的字符串。这不是什么:strcpy_P(buff,(char*)pgm_read_word(&(mainMsgs[groupID][msgID][i]);是吗?如果你已经回答了你的问题,在回答中写出来,而不是编辑问题。此外,编辑内容足够丰富,最好将其作为一个单独的问题发布,以避免将其变成看起来像一个问题的风险。你想要避免这种情况的原因,特别是像这样难以回答的问题,是因为像我这样厌倦了网站的用户会把这看作是一个危险信号,而不太愿意花时间去帮助别人