将动态所有分配数组的矩阵连接在一起的函数中的分段错误

问题描述 投票:0回答:1

我正在做一个工作,在该工作中,我被要求串联两个用C ++动态分配的2D数组(矩阵)。给定矩阵A和矩阵B,必须将矩阵A更新为串联的新矩阵,并且必须销毁矩阵B。在执行连接本身的函数中,连接的数组将按预期方式进行打印,但是我遇到了分段错误。返回分段错误的函数是horzcat()函数。

#include <iostream>
#include <stdexcept>
#include <string>
#include "matrix_helper.h"
// no other includes are allowed

using std::cout, std::endl;
using std::invalid_argument;
using std::to_string;
using std::size_t;
using std::ostream;

/*
dynamically allocates a new rows x cols matrix
initialize all elements to 0
*/
Matrix create_matrix(size_t rows, size_t cols) {
  int** MatrixA = new int*[rows];
  for (int a = 0; a < rows; a++) {
    MatrixA[a] = new int[cols];
  }

  for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
      MatrixA[i][j] = 0;
    }
  }

  return MatrixA;
}

// overload to create square matrices
// initialize all elements to 0
Matrix create_matrix(size_t n) {
  int** MatrixA = new int*[n];
  for (int a = 0; a < n; a++) {
    MatrixA[a] = new int[n];
  }

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      MatrixA[i][j] = 0;
    }
  }

  return MatrixA;
}

/*
given matrices A, B
horizontally concatenate B onto A
updates and returns A, frees B */

**Matrix& horzcat(Matrix& A, 
                size_t& rows_A, 
                size_t& cols_A, 
                Matrix& B,
                size_t& rows_B, 
                size_t& cols_B) {
  if (rows_A != rows_B) {
    throw invalid_argument("Non matching number of rows");
  }
  else {

    size_t newCols = cols_A + cols_B;
    //Matrix tempMatrix = create_matrix(rows_A, newCols);

    // pointer to new matrix
    Matrix tempMatrix = create_matrix(rows_A, newCols);

    // filling new matrix
    for (int i = 0; i < rows_A; i++) {
      for (int j = 0; j < cols_A; j++) {
        tempMatrix[i][j] = A[i][j];
      }
      for (int k = cols_A; k < newCols; k++) {
        tempMatrix[i][k] = B[i][k - cols_A];
      }
    }

    // delete A
    for (int i = 0; i < rows_A; i++) {
      delete [] A[i];
    }
    delete [] A;

    cols_A = newCols;
    Matrix A = create_matrix(rows_A, cols_A);
    for (int a = 0; a < rows_A; a++) {
      for (int b = 0; b < cols_A; b++) {
        A[a][b] = tempMatrix[a][b];
      }
    }

    delete [] B;

    delete [] tempMatrix;

    return A;
  }
}**

int main() {
  // A = [1 2 ; 3 4]
  Matrix A = create_matrix(2);
  size_t rows_A = 2;
  size_t cols_A = 2;
  A[0][0] = 1;
  A[0][1] = 2;
  A[1][0] = 3;
  A[1][1] = 4;
  print_matrix(A, rows_A, cols_A);

  // B = [5 6 7 ; 8 9 10]
  Matrix B = create_matrix(2,3);
  size_t rows_B = 2;
  size_t cols_B = 3;
  B[0][0] = 5;
  B[0][1] = 6;
  B[0][2] = 7;
  B[1][0] = 8;
  B[1][1] = 9;
  B[1][2] = 10;
  print_matrix(B, rows_B, cols_B);

  // horzcat(A, B)
  print_matrix(horzcat(A, rows_A, cols_A, B, rows_B, cols_B), rows_A, cols_A);

  // A
  print_matrix(A, rows_A, cols_A);

  // B
  print_matrix(B, rows_B, cols_B);

  // do you hear a leak?

  return 0;
}

这里是添加的matrix_helper.h代码

// DO NOT CHANGE ANYTHING IN THIS FILE
//   if you do, it could break the test cases
//   it will be your fault
//   you will lose points
// DO NOT CHANGE ANYTHING IN THIS FILE
#ifndef MATRIX_H
#define MATRIX_H

#include <cstddef>
#include <stdexcept>
#include <string>
#include <iostream>
#include <iomanip>
// no other includes are allowed

// typedef magic so that "Matrix" means "int**";
// if this confuses you, you can use "int**"" instead of "Matrix"
typedef int Value;
typedef Value* Row;
typedef Row* Matrix;
typedef const Value constValue;
typedef constValue* constRow;
typedef constRow const* constMatrix;


// length of n in characters
std::size_t get_width(int n) {
    if (n < 0) {
        return 1 + get_width(-n);
    }
    if (n < 10) {
        return 1;
    }
    return 1 + get_width(n/10);
}

// pretty print a matrix with right-aligned columns
void print_matrix(constMatrix matrix, std::size_t rows, std::size_t cols, std::ostream& os=std::cout) {
    // handle the empty matrix
    if (rows == 0 || cols == 0) {
        os << std::endl << "[]" << std::endl;
        return;
    }

    // compute column widths
    std::size_t* width = new std::size_t[cols]{0};
    for (std::size_t col = 0; col < cols; ++col) {
        for (std::size_t row = 0; row < rows; ++row) {
            std::size_t digits = get_width(matrix[row][col]);
            if (digits > width[col]) {
                width[col] = digits;
            }
        }
    }

    // pretty print with right-aligned columns
    os << std::endl;
    for (std::size_t row = 0; row < rows; ++row) {
        os << "|";
        for (std::size_t col = 0; col < cols; ++col) {
            os << " " << std::setw(width[col]) << matrix[row][col];
        }
        os << " |" << std::endl;
    }

    delete[] width;
}

#endif
c++ matrix multidimensional-array segmentation-fault dynamic-arrays
1个回答
0
投票

您的horzcat函数破坏了传递给它的A矩阵。然后,它会创建一个新的矩阵,也称为A(永远不要这样做!),这可能会使您感到困惑,认为它仍在操纵原始的A矩阵。

Matrix A = create_matrix(rows_A, cols_A);

这将创建一个称为Matrixnew A,该图像会遮盖原始图像。您想修改现有的。此时,您有两个都称为A的矩阵-一个通过销毁的引用传递给您的矩阵,以及在此处创建的新矩阵。]

您想要:

A = create_matrix(rows_A, cols_A);

您的编译器应该给您有关阴影参数的警告。如果您不理it它,可耻的是您。如果没有,请学习如何使编译器发出警告或使用更好的编译器。

我希望这不是C ++类,因为用这种方法编码绝对没有任何借口。原始指针的行为不像普通值那样,并且极难使用。每当不需要它们时都应避免使用它们,并且在此绝对不需要它们。将它们隐藏在typedef后面是无法防御的。

© www.soinside.com 2019 - 2024. All rights reserved.