【问题标题】:Two dimensional array / initialize data in c++ (Arduino)二维数组/用 C++ 初始化数据(Arduino)
【发布时间】:2013-11-10 10:37:18
【问题描述】:

我想我失去了全部 C++ 知识...

我想要的是以正确(可读)的方式初始化 2D unsigned char 数组: 我的方法:

#define RADIO_ONOFF 0
#define RADIO_P1 1
#define RADIO_P2 2
... 

#define NR_OF_CODES = 5
#define CODE_LENGTH = 10

#1:

unsigned char** codes = new unsigned char*[NR_OF_CODES];
codes[RADIO_ONOFF] = new unsigned char[CODE_LENGTH]{ 9,180,88,11,33,4,0,255,64,191 }; //     does not work
...

#2:

unsigned char ICODES[NR_OF_CODES][CODE_LENGTH];
ICODES[RADIO_ONOFF] = { 9,180,88,11,33,4,0,255,64,191 };  // same as above
...

#3:

class Test {
  private:
    unsigned char data[CODE_LENGTH];

  public:
    Test(unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4, unsigned char a5, unsigned char a6, unsigned char a7, unsigned char a8, unsigned char a9, unsigned char a10);

    unsigned char* getData(void);
};

Test::Test(unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4, unsigned char a5, unsigned char a6, unsigned char a7, unsigned char a8, unsigned char a9, unsigned char a10) {
  this->data[0] = a1;
  this->data[1] = a2;
  this->data[2] = a3;
  this->data[3] = a4;
  this->data[4] = a5;
  this->data[5] = a6;
  this->data[6] = a7;
  this->data[7] = a8;
  this->data[8] = a9;
  this->data[9] = a10;
}

unsigned char* Test::getData(void) {
  return data;
}

void setup() {

  test[RADIO_ONOFF] = new Test( 9,180,88,11,33,4,0,255,64,191 );
  test[RADIO_P1] = new Test( 9,180,88,11,33,4,0,255,64,192 );
  ...
}

#4

const unsigned char RADIO_ONOFF[]  = { 9,180,88,11,33,4,0,255,64,191 };
const unsigned char RADIO_P1[]     = { 9,180,88,11,33,4,0,255,64,192 };
...

#1 和 #2 我收到的错误消息:(代码应该为 Arduino 编译,它需要一个设置函数)

在函数'void setup()'中: revTest:58:错误:“{”标记之前的预期主表达式 revTest:58: 错误: 预期 `;'在'{'令牌之前

好的 - 我的问题:

对我来说 - #3 和 #4 很好读。 #3 的努力是最高的 - 但我认为这是 如果我想的话,最快的方法是在 switch 语句中使用数组。 - 是吗?

我认为 #1 和 #2 中的数组初始化应该这样工作????

非常Arduino具体:

我不确定什么必须在 setup() 内部定义,什么应该在 setup() 之外定义。静态初始化和全局外部,动态内部还是什么?

我对 Arduino 的 PROGMEM 感到不满 - 我认为在这种情况下不值得付出努力。我是对的? (我想我会有大约 50 个不同的代码......)

谢谢!

【问题讨论】:

    标签: c++ arrays initialization arduino


    【解决方案1】:

    在回答您的问题之前,让我们看看解决方案 1 和 2 出了什么问题。

    解决方案 1 和 2 的问题在于,您使用的是初始化程序(即 `{} 语法),而您的编译器需要一个赋值表达式。

    初始化语法只能在声明变量的地方使用。粗略地说,初始化应该理解为变量一构造就给它一个值。赋值应该理解为给已经在别处构造的变量赋值。

    所以当你这样做时:

    unsigned char** codes = new unsigned char*[NR_OF_CODES];
    

    您正在进行初始化。您正在将变量 codes 初始化为一个新分配的指向 unsigned char 的指针数组。

    在下一行,你告诉编译器你正在做一个赋值。您正在使用 = 符号并分配给 codes,这是在上一行声明的 - 编译器将此视为分配。

    codes[RADIO_ONOFF] = new unsigned char[CODE_LENGTH] ... 
    

    但是,紧接着,您尝试使用初始化语法。

    你的编译器在抱怨,因为它读到了这个:

    codes[RADIO_ONOFF] = new unsigned char[CODE_LENGTH] ... 
    

    作为一个完整的表达。当您分配一个 CODE_LENGTH 字节数组并将其分配给 codes 的第 RADIO_ONOFF 个成员时,它会读取。

    它希望你停在那里,用一个分号,但你继续并添加了初始化语法{}。它不明白,因为您将分配和初始化混合在一起 - 这是两件不同的事情。这就是为什么你会从编译器中得到“我期望一个分号”类型的错误。

    要回答您的问题,解决方案 3 和 4 都需要很长的路要走。在 C++ 中有更快的方法来初始化二维数组。我也同意之前关于使用uint8_t 的回答。

    这样的会更合适吗?

    uint8_t codes[CODE_LENGTH][NR_OF_CODES] = 
                                  {{0, 1, 2, 3, 4, 5, 6, 7}, 
                                  {0, 1, 2, 3, 4, 5, 6, 7}, 
                                  {0, 1, 2, 3, 4, 5, 6, 7}, 
                                  {0, 1, 2, 3, 4, 5, 6, 7} };
    

    读取数组语法的一个好方法是将方括号[] 中的最后一个(最右边的)值作为某个数组的大小,然后倒推。

    所以uint8_t codes[CODE_LENGTH][NR_OF_CODES] 将解码为大小为NR_OF_CODESsomething 数组。为了得到那个一些东西,我们看到uint8_t codes[CODE_LENGTH] - 所以它是一个长度为NR_OF_CODES的数组uint8_t,每个长度为CODE_LENGTH

    希望对你有帮助。

    注意。回答您关于需要使用命名索引对数组进行索引的评论 - 没有什么可以阻止您通过索引引用 codes 的各个成员。 您可以做的是通过 {0} 初始化整个事物 - 将所有成员初始化为 0 的简写。

    您可以单独分配 RADIO_ONOFF 数组(或任何数组)的成员,例如

    codes[RADIO_ONOFF][3] = 255;
    

    试试这个例子 - 并注意输出:

      #include <iostream>
    
      const int NR_OF_CODES = 4;
      const int RADIO_ONOFF = 0;
      const int CODE_LENGTH = 11;
    
      const unsigned char RADIO_ONOFF_ARR[] = { 180,99,33,11,22,33,55, 22,22,33, 10};
    
      int main()
      {
        unsigned char codes[CODE_LENGTH][NR_OF_CODES] = {
                                                       {0},
                                                      };
        std::cout << "Before:\n";
    
        for(int x = 0; x < CODE_LENGTH; x++)
        {
          std::cout << static_cast<int>(codes[RADIO_ONOFF][x]) << ", ";
        }
    
        codes[RADIO_ONOFF][3] = 3;
    
        std::cout << "\nAfter:\n";
    
        for(int x = 0; x < CODE_LENGTH; x++)
        {
          std::cout << static_cast<int>(codes[RADIO_ONOFF][x]) << ", ";
        }
    
        // or try memcpy 
        memcpy(codes[RADIO_ONOFF], RADIO_ONOFF_ARR, sizeof RADIO_ONOFF_ARR);
    
        std::cout << "\nAfter Memcpy:\n";
    
        for(int x = 0; x < CODE_LENGTH; x++)
        {
          std::cout << static_cast<int>(codes[RADIO_ONOFF][x]) << ", ";
        }
    
        char c;
        std::cin >> c;
        return 0;
      }
    

    【讨论】:

    • 感谢您非常详细的回答!您推荐的初始化方式不适合我,因为我希望能够使用命名的 indizes 来索引我的数组——比如 RADIO_ONOFF 等等。这是一个主要要求。这一行:code[RADIO_ONOFF] = new unsigned char[CODE_LENGTH]{ 9,180,88,11,33,4,0,255,64,191 };
    • 我认为它将代码 [RADIO_ONOFF] 声明为具有 CODE_LENGTH 长度的无符号字符数组,并使用 { values }... 一步初始化数组...但是,是的,似乎我错了:- )我可能会留在#4。我认为 Arduino (lowmem) 更喜欢它......
    • 你仍然可以使用命名索引来引用你的数组,我已经用一个例子编辑了我的答案 - 但是,如果你把它一次性分配整个数组 codes[RADIO_ONOFF] 会更棘手作为二维数组的一部分。
    • 结合 memcpy() 和您的解决方案 4 应该没问题。您将消除对 new 的需求 - 但这实际上取决于该二维数组是本地数组还是需要持久存在。无论如何 - 有很多选择。
    【解决方案2】:

    首先,由于这是标记为 C++,我要说没有必要做#define。您现在可以访问具有相同功能但类型安全的静态 const 变量。

    以下是 Google C++ 风格指南对花括号列表的看法:

    http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Braced_Initializer_Lists

    当我不从事已设置样式的项目时,我通常会遵循本指南。另外,我应该提一下,风格真的很主观,所以你最终可能会得到各种各样的答案。

    另外,不要使用 char,您只想存储字节数据。这就是 uint8_t 的用途。

    此外,有关如何初始化数组的所有选项,请参阅此 SO 线程:How to initialize all members of an array to the same value? 在大多数情况下,由于它们只是保持不变的常量,因此您可以将它们设置为静态常量。

    像这样:

    static const size_t kMyCodeArraySize = 14;  // an example
    static const uint8_t[kMyCodeArraySize] = {1, 2, 3, 4};  // example intialization
    

    【讨论】:

    • 感谢您向我指出 Google 风格指南和您的回答。我接受了上述答案(拼凑而成),因为它对我的 Q(2 暗淡 + 索引)更具体一些 - 无论如何 - 谢谢!
    猜你喜欢
    • 1970-01-01
    • 2014-05-14
    • 2012-11-29
    • 1970-01-01
    • 2014-08-09
    • 2014-05-24
    相关资源
    最近更新 更多