首页 > 解决方案 > 将指向字符矩阵的指针传递给 C++ 中的构造函数的问题

问题描述

我正在为使用 arduino 和按钮矩阵制作的键盘开发定制软件。我创建了一个 CustomKeyboard 类,其中包含与键盘相关的所有数据。它看起来像这样:


#define MAX_NROWS 10
#define MAX_NCOLS 30
#define MAX_NLAYERS 10
#define MAX_PRESSED_KEYS 7
#define KEY_ID_LENGTH 8


class CustomKeyboard{
  public:
    typedef void (*writeFunction) (CustomKeyboard *keyboard, char const *text);
    int z = 0;
    int cols[MAX_NCOLS];
    int rows[MAX_NROWS];
    int ncols, nrows, nlayers;
    int stateMatrix[MAX_NROWS][MAX_NCOLS];

    int maxPressedKeys = MAX_PRESSED_KEYS;
    int pressKeysCoordinates[MAX_PRESSED_KEYS][2];
    int holdKeysCoordinates[MAX_PRESSED_KEYS][2];
    int releaseKeysCoordinates[MAX_PRESSED_KEYS][2];

    char layout[MAX_NLAYERS][MAX_NROWS][MAX_NCOLS][KEY_ID_LENGTH];
    writeFunction pressFunctions[MAX_NLAYERS][MAX_NROWS][MAX_NCOLS];
    writeFunction releaseFunctions[MAX_NLAYERS][MAX_NROWS][MAX_NCOLS];

    CustomKeyboard(
      int const cols[], int const ncols, int const rows[], int const nrows, int const nlayers,
      char const layout[2][5][15][8], writeFunction const pressFunctions[2][5][15], writeFunction const releaseFunctions[2][5][15]){
      this->nlayers = nlayers;

      // cols
      this->ncols = ncols;
      memset(this->cols, -1, MAX_NCOLS * sizeof(int));
      memcpy(this->cols, cols, this->ncols * sizeof(int));
      for(int i = 0; i< this->ncols; i++) { pinMode(this->cols[i], OUTPUT); digitalWrite(this->cols[0], LOW); } 

      // rows
      this->nrows = nrows;
      memset(this->rows, -1, MAX_NROWS * sizeof(int));
      memcpy(this->rows, rows, this->nrows  * sizeof(int));
      for(int i = 0; i< this->nrows; i++) { pinMode(this->rows[i], INPUT_PULLDOWN); }
      
      // stateMatrix
      memset(stateMatrix, -1, sizeof(stateMatrix));
      for(int i = 0; i < this->nrows; i++){
        for(int j = 0; j < this->ncols; j++){
          this->stateMatrix[i][j] = 0;
        }
      }
      
      // layout and functions
      for(int i = 0; i < this->nlayers; i++){
        for(int j = 0; j < this->nrows; j++){
          for(int k = 0; k < this->ncols; k++){
            strcpy(this->layout[i][j][k],layout[i][j][k]);
            this->pressFunctions[i][j][k] = pressFunctions[i][j][k];
            this->releaseFunctions[i][j][k] = releaseFunctions[i][j][k];
          }
        }
      }
    }


    void updateStateMatrix(){
      // 0:idle 1:press 2:hold 3:release
      int pressKeyCounter = 0;
      memset(this->pressKeysCoordinates, -1, sizeof(pressKeysCoordinates));
      int holdKeyCounter = 0;
      memset(this->holdKeysCoordinates, -1, sizeof(holdKeysCoordinates));
      int releaseKeyCounter = 0;
      memset(this->releaseKeysCoordinates, -1, sizeof(releaseKeysCoordinates));

      for (int icol = 0; icol< this->ncols; icol++){
        digitalWrite(this->cols[icol], HIGH);
        for (int irow = 0; irow< this->nrows; irow++){
          if(digitalRead(this->rows[irow]) == 1){

            
            if(this->stateMatrix[irow][icol] == 0){ 
              // PRESS
              this->pressKeysCoordinates[pressKeyCounter][0] = irow;
              this->pressKeysCoordinates[pressKeyCounter][1] = icol;
              pressKeyCounter++;
              this->stateMatrix[irow][icol] = 1;
            }else{ 
              // HOLD
              this->holdKeysCoordinates[holdKeyCounter][0] = irow;
              this->holdKeysCoordinates[holdKeyCounter][1] = icol;
              holdKeyCounter++;
              this->stateMatrix[irow][icol] = 2;
            }
          }else{
            if(this->stateMatrix[irow][icol] == 1 || this->stateMatrix[irow][icol] == 2 ){
              // RELEASE
              this->releaseKeysCoordinates[releaseKeyCounter][0] = irow;
              this->releaseKeysCoordinates[releaseKeyCounter][1] = icol;
              releaseKeyCounter++;
              this->stateMatrix[irow][icol] = 3;
            }else{ 
              //IDLE
              this->stateMatrix[irow][icol] = 0;
            }
          }
        }
        digitalWrite(cols[icol], LOW);
        delay(1); // TODO: no entiendo porque esto es necesario
      }
    }

    void execFunctions(){
      for (int i = 0; i < this->maxPressedKeys; i++){
        if(pressKeysCoordinates[i][0] != -1){
          int row = pressKeysCoordinates[i][0];
          int column = pressKeysCoordinates[i][1];
          char *text = layout[this->z][row][column];
          writeFunction function= pressFunctions[this->z][row][column];
          function(this, text);
        }
        if(releaseKeysCoordinates[i][0] != -1){
          int row = releaseKeysCoordinates[i][0];
          int column = releaseKeysCoordinates[i][1];
          char *text = layout[this->z][row][column];
          writeFunction function= releaseFunctions[this->z][row][column];
          function(this, text);
        }
      }
    }
}

由于我使用的是 arduino,为了避免动态内存分配,我决定使用一些较大的值来创建矩阵(MAX_NROWS、MAX_NCOLS 等),然后我将使用我需要的空间。这种方法似乎工作正常,但我有一个问题。我不知道我将传递给类的构造函数的矩阵的大小。正如您在构造函数中看到的那样,我使用了值 2,5 和 15,因为这些是我的键盘矩阵的测量值。

CustomKeyboard(
      int const cols[], int const ncols, int const rows[], int const nrows, int const nlayers,
      char const layout[2][5][15][8], writeFunction const pressFunctions[2][5][15], writeFunction const releaseFunctions[2][5][15])

我在测试中通过的矩阵是:

char const layout[nlayers][nrows][ncols][KEY_ID_LENGTH] = {
  {
    {"`"    , "1"    , "2"    , "3"    , "4"    , "5"    , "_"    , "_"    , "6"    , "7"    , "8"    , "9"    , "0"    , "-"    , "="    },
    {"caps" , "q"    , "w"    , "e"    , "r"    , "t"    , "_"    , "_"    , "y"    , "u"    , "i"    , "o"    , "p"    , "["    , "]"    },
    {"tab"  , "a"    , "s"    , "d"    , "f"    , "g"    , "_"    , "_"    , "h"    , "j"    , "k"    , "l"    , ";"    , "'"    , "\\"   },
    {"shift", "z"    , "x"    , "c"    , "v"    , "b"    , "_"    , "_"    , "n"    , "m"    , ","    , "."    , "/"    , "_"    , "_"    },
    {"ctrl" , "mod"  , "_"    , "_"    , "_"    , "_"    , "-"    , "_"    , "_"    , "_"    , "_"    , "_"    , "_"    , "_"    , "_"    }
  },{
    {"2A1", "2A2", "2A3", "2A4", "2A5", "2A6", "2A7", "2A8", "2A9", "2A10", "2A11", "2A12", "2A13", "2A14", "2A15"},
    {"2B1", "2B2", "2B3", "2B4", "2B5", "2B6", "2B7", "2B8", "2B9", "2B10", "2B11", "2B12", "2B13", "2B14", "2B15"},
    {"2C1", "2C2", "2C3", "2C4", "2C5", "2C6", "2C7", "2C8", "2C9", "2C10", "2C11", "2C12", "2C13", "2C14", "2C15"},
    {"2D1", "2D2", "2D3", "2D4", "2D5", "2D6", "2D7", "2D8", "2D9", "2D10", "2D11", "2D12", "2D13", "2D14", "2D15"},
    {"2E1", "2E2", "2E3", "2E4", "2E5", "2E6", "2E7", "2E8", "2E9", "2E10", "2E11", "2E12", "2E13", "2E14", "2E15"}
  }
};

CustomKeyboard::writeFunction const pressFunctions[nlayers][nrows][ncols]= {
  {
    {_______, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__, LAYER_1, _______, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__},
    {_______, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__, _______, _______, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__},
    {_______, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__, _______, _______, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__},
    {P_SHIFT, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__, _______, _______, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__, WRITE__},
    {_______, _______, _______, _______, _______, SPACE__, _______, _______, DEL____, P_ALT__, _______, _______, _______, _______, _______}
  },{
    {_______, TEST___, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
    {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
    {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
    {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
    {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______}
  }
};

CustomKeyboard::writeFunction const releaseFunctions[nlayers][nrows][ncols]= {
  {
    {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
    {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
    {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
    {R_SHIFT, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
    {_______, _______, _______, _______, _______, _______, _______, _______, _______, R_ALT__, _______, _______, _______, _______, _______}
  },{
    {_______, _______, _______, _______, _______, _______, LAYER_0, _______, _______, _______, _______, _______, _______, _______, _______},
    {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
    {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
    {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
    {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______}
  }
};

我认为将指针传递给矩阵而不是副本会更有意义,因为这样我不需要在构造函数中设置大小,并且可以避免使用不必要的内存。问题是我不知道该怎么做。我已经尝试了所有想到的东西。

例如,矩阵layout,因为它是一个数组(1)的数组(2)的数组(3)的数组(4)的字符我想我应该写char**** const layout在构造函数中,但这似乎不起作用. 错误如下所示:

error: no matching function for call to 'CustomKeyboard::CustomKeyboard(const int [15], const int&, const int [5], const int&, const int&, const char (*)[2][5][15][8], void (* const [2][5][15])(CustomKeyboard*, const char*), void (* const [2][5][15])(CustomKeyboard*, const char*))'

我确信这个问题是因为我没有正确理解一些基本概念。

我还读到,当您将数组作为参数传递给函数时(我想构造函数也是如此),它会衰减为指向第一个元素的指针,所以当我调用构造函数时,它应该是相同的,对吧?

标签: c++arraysmemoryarduino

解决方案


推荐阅读