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}