2.2.7. 行列の例

  1// s007: dynamically allocated matrix held on a struct
  2// along with the data count.
  3//
  4#include <iostream>
  5#include <cassert>
  6
  7const int NUM_ROWS = 10;
  8const int NUM_COLS = 5;
  9
 10// parrayとn_sizeという項目を持つ構造体を宣言する。
 11// Array型の変数を後で使えるようになる。
 12struct Matrix {
 13    double *parray;
 14    int num_rows;
 15    int num_cols;
 16};
 17
 18void set_mat_elem(Matrix *pmat, int row, int col, double value)
 19{
 20    pmat->parray[row*pmat->num_cols + col] = value;
 21}
 22
 23double get_mat_elem(const Matrix *pmat, int row, int col)
 24{
 25    return pmat->parray[row*pmat->num_cols + col];
 26}
 27
 28// function to set dummy data to the array
 29void set_dummy_data_struct(Matrix *pmat)
 30{
 31    for (int i = 0; i < pmat->num_rows; i++) {
 32        for (int j = 0; j < pmat->num_cols; j++) {
 33            double value = static_cast<double>(i*pmat->num_cols + j) / static_cast<double>(pmat->num_cols*pmat->num_rows);
 34            set_mat_elem(pmat, i, j, value);
 35        }
 36    }
 37}
 38
 39void copy_data_struct(Matrix *pdest, const Matrix *psrc)
 40{
 41    assert(pdest->num_rows == psrc->num_rows);
 42    assert(pdest->num_cols == psrc->num_cols);
 43    for (int i = 0; i < pdest->num_rows; i++) {
 44        for (int j = 0; j < pdest->num_cols; j++) {
 45            set_mat_elem(pdest, i, j, get_mat_elem(psrc, i, j));
 46        }
 47    }
 48}
 49
 50void print_data_struct(const Matrix *pmat)
 51{
 52    std::cout << "[";
 53    for (int i = 0; i < pmat->num_rows; i++) {
 54        for (int j = 0; j < pmat->num_cols; j++) {
 55            std::cout << get_mat_elem(pmat, i, j);
 56            if (i < pmat->num_cols - 1) {
 57                std::cout << ", ";
 58            }
 59        }
 60        std::cout << "\n";
 61    }
 62    std::cout << "]\n";
 63}
 64
 65void print_data(const double *d, int n)
 66{
 67    // 上記 os の手前の "&" は参照型であることを示すC++特有の記号で、C言語には存在しない。
 68    // & には参照型の宣言と、アドレス演算子の二つの意味がある。
 69    std::cout << "[";
 70    for (int i = 0; i < n; i++) {
 71        std::cout << d[i];
 72        if (i < n - 1) {
 73            std::cout << ", ";
 74        }
 75    }
 76    std::cout << "]\n";
 77}
 78
 79// allocate an array.
 80// returns true on success, false on failure.
 81bool allocate_matrix_struct(int num_rows, int num_cols, Matrix **ppmat) {
 82    assert(ppmat != nullptr);
 83    Matrix *pmat = new Matrix;
 84    if (pmat == nullptr) {
 85        // could not allocate memory for the struct.
 86        return false;
 87    }
 88    pmat->parray = new double[num_rows * num_cols];
 89    if (pmat->parray == nullptr) {
 90        // could not allocate memory for the array, but succeeded for the struct.
 91        delete pmat;
 92        return false;
 93    }
 94    // success.
 95    pmat->num_rows = num_rows;
 96    pmat->num_cols = num_cols;
 97    *ppmat = pmat;
 98    return true;
 99}
100
101void free_matrix_struct(Matrix *pmat) {
102    delete [] pmat->parray;
103    delete pmat;
104}
105
106int main(int argc, const char *argv[])
107{
108    std::cout << "s001\n";
109
110    // allocate array dynamically on the heap area.
111    Matrix *pmat1;
112    Matrix *pmat2;
113    if (! allocate_matrix_struct(NUM_ROWS, NUM_COLS, &pmat1)) {
114        return EXIT_FAILURE;
115    }
116    if (! allocate_matrix_struct(NUM_ROWS, NUM_COLS, &pmat2)) {
117        free_matrix_struct(pmat1);
118        return EXIT_FAILURE;
119    }
120
121    // 静的領域のメモリの初期値は 0
122    // ただし自分で初期値を入れることが推奨される。
123    std::cout << "Before initialization\n";
124    print_data_struct(pmat1);
125
126    // 配列を直接受け取る関数を呼ぶ例
127    print_data(pmat1->parray, pmat1->num_rows * pmat1->num_cols);
128
129    // 配列の名前のデータ型は配列要素のアドレス。
130    // 受ける側のdoubleのポインタに代入できる。
131    set_dummy_data_struct(pmat1);
132    std::cout << "After initialization\n";
133    print_data_struct(pmat1);
134
135    copy_data_struct(pmat2, pmat1);
136    std::cout << "After array copy\n";
137    print_data_struct(pmat2);
138
139    // return allocated memory to OS
140    // new に成功した場合にのみ delete を呼ぶこと。
141    free_matrix_struct(pmat1);
142    free_matrix_struct(pmat2);
143
144    return EXIT_SUCCESS; // exit status code 0
145}

Download the source code