What do I want to do?
我在做一个关于动态矩阵乘法的项目.我想从用户那里输入他/她想要执行乘法的矩阵数,并基于此创建一个 struct ,如下所示:
typedef struct
{
size_t rows, columns;
int table[];
} Matrix;
然后,判断矩阵的有效性,乘以(using very simple maths).
然后创建一个包含Matrix
种类型的数组,并根据用户想要乘法的矩阵数量为其分配内存.
+---------------------------------------------------------------------------------------------------+
| +------------------------------+ +---------------------------------------------------------+ |
| | Matrix struct type array | | ..... More arrays depending on the number of matrices. | |
| +------------------------------+ +---------------------------------------------------------+ |
+---------------------------------------------------------------------------------------------------+
Eg. 2 Matrices [2][2] & [2][1]
+----------------> rows <-------------+
| |
| +------------> columns <-----------|--+
| | | |
| | +------------------------+ | | +------------------+
{ { 2, 2, | { { 1, 2 }, { 2, 1 } } | }, { 2, 1, | { { 1 }, { 3 } } | } }
+------------------------+ +------------------+
| |
| |
| |
v v
| 1 2 | | 1 |
| | | |
| 2 1 | | 3 |
Reasons for creating an array of struct type
有一件事对我的一些读者来说可能很奇怪,那就是,为什么我要创建一个类型为struct Matrix
的数组,而不是创建两个不同的类型对象并在"user_defined_matrix"->table
上执行乘法.原因如下:
-
Scalability.由于每个约束都是用户定义的,我希望事情尽可能灵活.考虑这一点的一种方法是,假设用户想要15个矩阵之间的乘法,那么您不想声明15个类型为
struct Matrix
的对象. - Accessibility,在for-loop的帮助下,访问每个矩阵将变得非常容易.
现在回到主题,在分配内存之后,我希望用户填充矩阵的每个插槽,然后对它们执行乘法并生成结果.
What I have done so far
101 I know that you cannot declare a true 2d VLA inside a struct, you have to first declare a 1d array which later becomes a mangled version of a 2d array and before using it typecast it to a 2d array as shown in this 100.
我制作了一个真正的2d数组来存储用户输入的行和列.
int dimensions[NUMBER_OF_MATRIX][2];
然后用这dimensions
个,我计算了我需要分配多少内存.
int total_matrix_size = 0;
for (uint i = 0; i < NUMBER_OF_MATRIX; i++)
{
total_matrix_size += (dimensions[i][0] * dimensions[i][1]);
}
然后使用total_matrix_size
为struct Martix
类型的数组分配内存.
Matrix *matrix = malloc(((sizeof *matrix) * NUMBER_OF_MATRIX) + sizeof(int[total_matrix_size]));
在那之后,我要求用户填充矩阵,在填充矩阵之前,我在下面代码中的宏的帮助下,将数组转换为2darray.
100 I'll be referring to the below code block many times so for the sake of simplicity, let's name this 101.
#define get_array(arr) \
_Generic((arr), \
Matrix \
: (int(*)[(arr).columns])(arr).table)
for (uint i = 0; i < NUMBER_OF_MATRIX; i++)
{
matrix[i].rows = dimensions[i][0];
matrix[i].columns = dimensions[i][1];
for (uint x = 0; x < matrix[i].rows; x++)
{
for (uint y = 0; y < matrix[i].columns; y++)
{
printf("Enter values of matrix %d a[%dx%d] : ", i + 1, x + 1, y + 1);
scanf("%d", &get_array(matrix[i])[x][y]);
printf("%d\n", get_array(matrix[i])[x][y]); // print statement 1
}
}
}
为了测试,我打印了所有的矩阵.
100 I'll be referring to the below code block many times so for the sake of simplicity, let's name this 101.
for (uint i = 0; i < NUMBER_OF_MATRIX; i++)
{
printf("Matrix %d\n", i+1);
for (uint x = 0; x < matrix[i].rows; x++)
{
for (uint y = 0; y < matrix[i].columns; y++)
{
printf("%d ", get_array(matrix[i])[x][y]); // print statement 2
}
printf("\n");
}
}
So, where is the problem?
正如你所见,我在上面的两个代码块input和output中写了两个完全相同的print语句.
printf("%d ", get_array(matrix[i])[x][y]);
但它们都产生了不同的输出.
Enter the rows of matrix 1 : 2 2
Enter the rows of matrix 2 : 2 2
Enter values of matrix 1 a[1x1] : 1
1
Enter values of matrix 1 a[1x2] : 0
0
Enter values of matrix 1 a[2x1] : 1
1
Enter values of matrix 1 a[2x2] : 0
0
Enter values of matrix 2 a[1x1] : 2
2
Enter values of matrix 2 a[1x2] : 3
3
Enter values of matrix 2 a[2x1] : 2
2
Enter values of matrix 2 a[2x2] : 3
3
按预期打印所有内容.
但output block人的情况不一样.
Matrix 1
2 2
2 3
Matrix 2
2 3
2 3
What do I expect from the answers?
只不过是一个深入的解释:
- 为什么打印报表在input block&;为什么不进来
- 如果这不是分配内存的正确方法,那么是什么?
- 如果我的方法完全错误,那应该是什么?
请保持answer的格式.
这是全部代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// TODO Preprocessors
#define get_array(arr) \
_Generic((arr), \
Matrix \
: (int(*)[(arr).columns])(arr).table)
// TODO Custom types
typedef unsigned int uint;
// TODO Structs
typedef struct
{
uint rows, columns;
int table[];
} Matrix;
// TODO Function Declarations
void flushBuffer(void);
int main(void)
{
int NUMBER_OF_MATRIX = 2;
int dimensions[NUMBER_OF_MATRIX][2];
for (uint i = 0; i < NUMBER_OF_MATRIX; i++)
{
printf("Enter the rows of matrix %d : ", i + 1);
scanf("%d %d", &dimensions[i][0], &dimensions[i][1]);
flushBuffer();
}
if (dimensions[0][1] != dimensions[1][0])
{
printf("Matrix multiplication not possible.");
}
else
{
int total_matrix_size = 0;
for (uint i = 0; i < NUMBER_OF_MATRIX; i++)
{
total_matrix_size += (dimensions[i][0] * dimensions[i][1]);
}
Matrix *matrix = malloc(((sizeof *matrix) * NUMBER_OF_MATRIX) + sizeof(int[total_matrix_size]));
for (uint i = 0; i < NUMBER_OF_MATRIX; i++)
{
matrix[i].rows = dimensions[i][0];
matrix[i].columns = dimensions[i][1];
for (uint x = 0; x < matrix[i].rows; x++)
{
for (uint y = 0; y < matrix[i].columns; y++)
{
printf("Enter values of matrix %d a[%dx%d] : ", i + 1, x + 1, y + 1);
scanf("%d", &get_array(matrix[i])[x][y]);
printf("%d\n", get_array(matrix[i])[x][y]);
}
}
}
for (uint i = 0; i < NUMBER_OF_MATRIX; i++)
{
printf("Matrix divider\n");
for (uint x = 0; x < matrix[i].rows; x++)
{
for (uint y = 0; y < matrix[i].columns; y++)
{
printf("%d ", get_array(matrix[i])[x][y]);
}
printf("\n");
}
}
}
return 0;
}
// TODO Function Definitions
void flushBuffer(void)
{
int c;
while ((c = getchar()) != '\n' && c != EOF)
;
}