如何制作宽度不同的 2D 数组数组

How do I make an array of 2D arrays that are not all the same width?

本文关键字:数组 2D 何制作      更新时间:2023-10-16

我知道这行得通。

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};

现在,如果 2D 阵列的宽度不同怎么办?我该如何做到这一点?

例如:这不起作用,因为 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};

必须做什么才能制作不同元素大小的数组数组?

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

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

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

您可以通过从 2d 索引转换为 1d 索引将array_memory视为多维数组:

unsigned index = row * maximum_columns + column;

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

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

"请停下来观想一下," 记忆"实际上是什么样子的。

显然,arrayOf2DArrays2由:"三个指针的数组"组成。

不幸的是,在所有这些中,没有任何

内容可以预测这三个元素中的每一个组成,我们可以非常清楚地看到它们三个都是不同的。 "可是,C++...不能!(因为:到目前为止,您还没有提供任何手段来这样做。

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

arrayOf2DArrays2应该由"一个容器"组成,目前包含(三个)其他"容器",每个容器都能够告诉您包含多少元素,并且在您尝试访问不包含的元素时也会引发运行时异常。

当你这样做时,一个"简单"的陈述,如arrayOf2DArrays2[x][y](或你有什么......)将被C++"自动"理解为指代一系列实际上复杂的事件:首先,将要求外部容器解析[x]然后要求因此引用的内部容器解析[y]

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

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 在他的答案中所教导的那样,要访问特定的 2D 数组、行和列,请使用以下内容:

byte index = row * maximum_columns + column;

在我上面的例子中,这将是:

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

注意:byte等效于 uint8_t