【问题标题】:How do I make an array of 2D arrays that are not all the same width?如何制作宽度不同的二维数组?
【发布时间】:2016-07-06 23:54:09
【问题描述】:

这行得通,我知道。

int8_t intArray7[][2] = {-2, -1,
                          0, 1,
                          2, 3,
                          4, 5,
                          6, 7};

int8_t intArray8[][2] = {10, 9,
                          8, 7,
                          6, 5,
                          4, 3,
                          2, 1, 
                          0, -1,
                         -2, -3};

int8_t intArray9[][2] = {100, 101,
                         102, 103};

int8_t (*arrayOf2DArrays[])[2] = {intArray7, intArray8, intArray9};

现在,如果二维数组的宽度不一样怎么办?我该怎么做?

例如:这不起作用,因为 intArray11 的宽度为 3:

 int8_t intArray10[][2] = {-2, -1,
                            0, 1,
                            2, 3,
                            4, 5,
                            6, 7};

int8_t intArray11[][3] = {10, 9, 8,
                           7, 6, 5, 
                           4, 3, 2,
                           1, 0, -1};

int8_t intArray12[][2] = {100, 101,
                          102, 103};

int8_t (*arrayOf2DArrays2[])[] = {intArray10, intArray11, intArray12};

如何制作一个由不同元素大小的数组组成的数组?

我计划使用单独的变量来跟踪每个数组的大小。

【问题讨论】:

  • 检查哪个数组最大,然后操作其余的添加 0 以使行匹配,然后将它们加在一起。
  • 我敢打赌你需要更多的牙套。从我身边得到一些{{ x, y }, { z, 43 }}。好吧,说真的:使用std::vector<std::vector<int8_t>>
  • What must one do to make an array of arrays of different element sizes? in C++ .. 你可以使用STL container
  • @GabrielStaples 如果你想有一定的大小并在堆栈上分配你可以考虑使用std::array<>instead。
  • 您最好的选择(如果我正确地阅读了上面的 cmets)是使用 int 指针数组,然后将内存宽度分配给每个索引指针以匹配需要。尽管您可能会发现自己处理内存管理可能不值得任何边际性能提升。在大多数情况下,STL 容器无疑会比您在内存管理方面做得更好。如果容器管理不符合您的喜好,您可以随时创建自定义分配器。

标签: c++ arrays pointers multidimensional-array arduino


【解决方案1】:

我相信最兼容的方法是使用struct(或class)来描述数组:

struct Array_Attributes
{
  int8_t * array_memory;
  unsigned int maximum_rows;
  unsigned int maximum_columns;
};

您可以将array_memory 视为一个多维数组,将 2d 索引转换为 1d 索引:

unsigned index = row * maximum_columns + column;

你也可以用链表创建一个数组。这将允许不同尺寸的尺寸。

+-------+     +----------+     +----------+  
| row 0 | --> | column 0 | --> | column 1 | ...  
+-------+     +----------+     +----------+  
    |  
    |
    V  
+-------+     +----------+     +----------+  
| row 1 | --> | column 0 | --> | column 1 | ...  
+-------+     +----------+     +----------+  

【讨论】:

    【解决方案2】:

    “请停下来想象一下,”记忆”实际上是什么样子的。 . .

    arrayOf2DArrays2 显然包含:“一个由三个指针组成的数组。”

    对你来说很不幸,没有任何东西,可以预测这三个元素中的每一个由什么组成,我们可以非常清楚地看到他们三个都是不同的。 “但是,C++ ... 不能!”(因为:到目前为止,您还没有为它提供任何方法。)

    因此,您现在需要利用 C++ 的“容器类”。

    arrayOf2DArrays2应该由“一个容器”组成,目前包含(三个)其他“容器”,每个容器都能告诉你有多少it 包含的元素,如果您尝试访问 it 不包含的元素,也会引发运行时异常。

    完成此操作后,C++ 将“自动”理解为“简单”语句,例如 arrayOf2DArrays2[x][y](或 what-have-you ...) -复杂的一系列事件:首先,外部容器将被要求解析[x]然后因此被引用的内部容器将被要求解析@987654325 @。

    【讨论】:

      【解决方案3】:

      好的,我也想回答我自己的问题。这里有很多好主意,但让我发布这个简单且内存成本低的解决方案。对于内存最小的设备(例如:具有 512 字节 RAM 和几 kB 程序闪存的 ATTiny AVR 微控制器),我认为这可能是最好的解决方案。我已经测试过了;有用。使用指向int8_t的指针数组——即:指向一维数组的指针数组,如下:

      int8_t intArray10[][2] = {-2, -1,
                                  0, 1,
                                  2, 3,
                                  4, 5,
                                  6, 7};
      
      int8_t intArray11[][3] = {10, 9, 8,
                                 7, 6, 5, 
                                 4, 3, 2,
                                 1, 0, -1};
      
      int8_t intArray12[][2] = {100, 101,
                                102, 103};
      
      //get some array specs we need about the arrays
      byte arrayLengths[] = {sizeof(intArray10)/sizeof(int8_t), sizeof(intArray11)/sizeof(int8_t), 
                              sizeof(intArray12)/sizeof(int8_t)}; //redundant division since int8_t is 1 byte, but I want to leave it for verboseness and extension to other types 
      byte arrayCols[] = {2, 3, 2};
      
      //make pointers to int8_t's and point each pointer to the first element of each 2D array, as though each 2D array was a 1D array
      //-this works because the arrays use contiguous memory 
      int8_t *intArray10_p = &(intArray10[0][0]); 
      int8_t *intArray11_p = &(intArray11[0][0]);
      int8_t *intArray12_p = &(intArray12[0][0]);
      
      //make an array of those pointers to 1D arrays 
      int8_t *intArrayOfnDimArray[] = {intArray10_p, intArray11_p, intArray12_p};
      
      //print the 3 arrays via pointers to (contiguous) 1D arrays:
      //-Note: this concept and technique should work with ANY contiguous array of ANY number of dimensions
      for (byte i=0; i<sizeof(intArrayOfnDimArray)/sizeof(intArrayOfnDimArray[0]); i++) //for each 2D array 
      {
        for (byte j=0; j<arrayLengths[i]; j++) //for all elements of each 2D array 
        {
          Serial.print(intArrayOfnDimArray[i][j]); Serial.print("/"); //now read out the 2D array values (which are contiguous in memory) one at a time; STANDARD ARRAY ACCESS TECHNIQUE 
          Serial.print(*(intArrayOfnDimArray[i] + j)); Serial.print("/"); //ARRAY/POINTER TECHNIQUE (extra teaching moment)
          Serial.print((*(intArrayOfnDimArray + i))[j]); Serial.print("/"); //POINTER/ARRAY TECHNIQUE
          Serial.print(*(*(intArrayOfnDimArray + i) + j)); //POINTER/POINTER TECHNIQUE 
      
          //add a comma after every element except the last one on each row, to present it in 2D array form 
          static byte colCount = 0; //initialize as being on "Column 1" (0-indexed)
          if (colCount != arrayCols[i]-1) //if not on the last column number 
            Serial.print(", ");
          else //colCount==arrayCols[i]-1 //if we *are* on the last column number 
            Serial.println();
          colCount++;
          if (colCount==arrayCols[i])
            colCount = 0; //reset 
        }
        Serial.println(F("-----")); //spacer 
      }
      

      输出:

      -2/-2/-2/-2, -1/-1/-1/-1
      0/0/0/0, 1/1/1/1
      2/2/2/2, 3/3/3/3
      4/4/4/4, 5/5/5/5
      6/6/6/6, 7/7/7/7
      -----
      10/10/10/10, 9/9/9/9, 8/8/8/8
      7/7/7/7, 6/6/6/6, 5/5/5/5
      4/4/4/4, 3/3/3/3, 2/2/2/2
      1/1/1/1, 0/0/0/0, -1/-1/-1/-1
      -----
      100/100/100/100, 101/101/101/101
      102/102/102/102, 103/103/103/103
      -----
      

      注意:正如 Thomas Matthews 在他的回答中所教导的,要访问特定的二维数组、行和列,请使用以下命令:

      byte index = row * maximum_columns + column;
      

      在我上面的例子中是:

      byte rowColIndex = desiredRow * arrayCols[desired2DArrayIndex] + desiredColumn;
      int8_t val = intArrayOfnDimArray[desired2DArrayIndex][rowColIndex];
      

      注意:byte 等价于uint8_t

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-30
        • 2017-05-18
        • 1970-01-01
        • 1970-01-01
        • 2013-04-11
        • 2015-12-02
        • 2010-09-30
        • 2019-01-11
        相关资源
        最近更新 更多