【问题标题】:C dynamic 2d Matrices struct frustrationC动态二维矩阵结构挫败
【发布时间】:2021-03-03 10:28:11
【问题描述】:

我在整个互联网上搜索并观看了大量视频,但没有人这样做: 创建一个可以直接从 main 动态更改其 KxN 的结构矩阵,例如 我会用java:

Matrix(int k , int n){
int Mat[k][n];
}
main(){
Matrix a = new Matrix (2,3);
a.Mat[0][0] = 1;
syso(a.Mat[0][0]);
}

我开始认为这是不可能的,我试图从 main 分配内存并且它起作用了,我就是这样做的

int** arr = malloc(sizeof(int*)*n)
for (int i = 0 ; i < k ; i=+){
arr[i] = malloc(sizeof(int)*3);
}

但问题是由于某种原因我无法在结构中执行此操作.. 我需要保持我的 main 清洁,所以我的所有工作都应该在 main 之上完成,

这是我的 C 程序不起作用:

//__________________HEADER_________________________________________________//

#include <stdio.h>
#include <stdlib.h>
//__________________________________________________________________________//
//__________________OBJECTS______________________________________________________//

typedef struct { 
int n , k ;
int** Mat;
}Matrix;
//______________________________________________________________________________//

//___________________MAIN_____________________________________________________//

int main (void) {
printf("Start..\n\n");


Matrix aqq = {2,5} ;

aqq.Mat[0][0] = 5 ;

printf("\n  size : %dx%d    first element : %d \n",aqq.n , aqq.k , aqq.Mat[0][0]);


printf("\n\nEnd\n");
}
//______________________________________________________________________________//

我需要让所有的 getter 和 setter 转置所有的矩阵函数,包括线性复制高斯消除 .. 一切,我想收到一些指南甚至一本书的链接,我不在乎只要我能从中学习,因为它真的很难像那样工作,涉及记忆的规则太多,而且没有一个可靠的信息来源,因为每个人都在做教程上的简单事情

综上所述,最终目标是完全通过main来控制每一个功能

【问题讨论】:

  • 不清楚“不能在结构中执行”是什么意思。您当然可以使用结构来做到这一点——您需要将指向结构的指针传递给函数,以便函数可以根据需要修改内容。你必须决定如何设计你的“构造函数”,并编码“析构函数”。例如,您可以使用int matrix_constructor(Matrix *mtx, int n, int m);void matrix_destructor(Matrix *mtx);。或者你可以使用Matrix matrix_constructor(int n, int m); 作为构造函数;甚至Matrix *matrix_constructor(size_t n, size_t m);。一切都可以正常工作。

标签: arrays c matrix struct dynamic


【解决方案1】:

这里的代码可以分成三个文件——matrix.hmatrix.ctest.matrix.c

  1. 标头 matrix.h 声明了一个不透明类型 Matrix 和一些操作该类型的函数 - 构造函数(我的 comment 中的第三个选项)、析构函数、获取和设置元素值的例程以及用于获取数组维度。

  2. 实现文件matrix.c 定义了函数。它使用断言来确保参数的有效性——懒惰但有效,只要你从不使用-DNDEBUG 编译。如果您确实禁止断言,则需要将适当的错误处理放入函数中。决定如何处理由损坏的数据结构检测到的错误是一个项目范围的决策。如果在构造矩阵期间分配失败,代码会小心释放任何已分配的内存。它定义了struct Matrix,但在此源文件之外无法访问该类型。

  3. 测试文件test.matrix.c 提供了一些代码来使用matrix.h 中声明的所有函数,并演示了正方形和矩形矩阵的工作原理。该文件中的代码不能取消引用矩阵结构;它必须使用访问函数。

生成的代码相当大,但它完成了工作并证明您确实可以使用结构来存储矩阵。编写一个矩阵乘法例程是一个简单的练习。

/* SOF - matrix.h */
#ifndef MATRIX_H_INCLUDED
#define MATRIX_H_INCLUDED

#include <stddef.h>     /* size_t */

enum { MATRIX_MAX_SIZE = 1000 };

typedef struct Matrix Matrix;   /* Opaque type */

extern Matrix *matrix_constructor(size_t rows, size_t cols);
extern void matrix_destructor(Matrix *mtx);
extern int matrix_get_element(const Matrix *mtx, size_t r, size_t c);
extern void matrix_set_element(Matrix *mtx, size_t r, size_t c, int v);
extern size_t matrix_get_cols(const Matrix *mtx);
extern size_t matrix_get_rows(const Matrix *mtx);

#endif /* MATRIX_H_INCLUDED */
/* EOF - matrix.h */

/* SOF - matrix.c */
/*#include "matrix.h"*/
#include <assert.h>
#include <stdlib.h>

struct Matrix
{
    size_t   rows;
    size_t   cols;
    int    **data;
};

/* It is important to prevent memory leaks on allocation failure */
Matrix *matrix_constructor(size_t rows, size_t cols)
{
    assert(rows <= MATRIX_MAX_SIZE && rows > 0);
    assert(cols <= MATRIX_MAX_SIZE && cols > 0);
    Matrix *mtx = malloc(sizeof(*mtx));
    if (mtx == NULL)
        return NULL;
    mtx->data = malloc(sizeof(*mtx->data) * rows);
    if (mtx->data == NULL)
    {
        free(mtx);
        return NULL;
    }
    for (size_t i = 0; i < rows; i++)
    {
        mtx->data[i] = malloc(sizeof(*mtx->data[i]) * cols);
        if (mtx->data[i] == NULL)
        {
            while (i > 0)
                free(mtx->data[--i]);
            free(mtx);
            return NULL;
        }
    }
    mtx->rows = rows;
    mtx->cols = cols;
    return mtx;
}

void matrix_destructor(Matrix *mtx)
{
    assert(mtx != NULL && mtx->data != NULL);
    assert(mtx->rows <= MATRIX_MAX_SIZE && mtx->rows > 0);
    assert(mtx->cols <= MATRIX_MAX_SIZE && mtx->cols > 0);
    for (size_t i = 0; i < mtx->rows; i++)
        free(mtx->data[i]);
    free(mtx->data);
    free(mtx);
}

int matrix_get_element(const Matrix *mtx, size_t r, size_t c)
{
    assert(mtx != NULL && mtx->data != NULL);
    assert(mtx->rows <= MATRIX_MAX_SIZE && mtx->rows > 0);
    assert(mtx->cols <= MATRIX_MAX_SIZE && mtx->cols > 0);
    return mtx->data[r][c];
}

void matrix_set_element(Matrix *mtx, size_t r, size_t c, int v)
{
    assert(mtx != NULL && mtx->data != NULL);
    assert(mtx->rows <= MATRIX_MAX_SIZE && mtx->rows > 0);
    assert(mtx->cols <= MATRIX_MAX_SIZE && mtx->cols > 0);
    mtx->data[r][c] = v;
}

size_t matrix_get_rows(const Matrix *mtx)
{
    assert(mtx != NULL && mtx->data != NULL);
    assert(mtx->rows <= MATRIX_MAX_SIZE && mtx->rows > 0);
    assert(mtx->cols <= MATRIX_MAX_SIZE && mtx->cols > 0);
    return mtx->rows;
}

size_t matrix_get_cols(const Matrix *mtx)
{
    assert(mtx != NULL && mtx->data != NULL);
    assert(mtx->rows <= MATRIX_MAX_SIZE && mtx->rows > 0);
    assert(mtx->cols <= MATRIX_MAX_SIZE && mtx->cols > 0);
    return mtx->cols;
}
/* EOF - matrix.c */

/* SOF - test.matrix.c */
/*#include "matrix.h"*/
#include <errno.h>
#include <stdarg.h>
#include <stdint.h>     /* intmax_t */
#include <stdio.h>
/*#include <stdlib.h>*/
#include <string.h>
#include <time.h>

/* Cannot dereference Matrix pointers here! */

static void matrix_print(const char *tag, const Matrix *mtx, int width)
{
    size_t rows = matrix_get_rows(mtx);
    size_t cols = matrix_get_cols(mtx);
    printf("%s (%zux%zu):\n", tag, rows, cols);
    for (size_t r = 0; r < rows; r++)
    {
        const char *pad = "";
        for (size_t c = 0; c < cols; c++)
        {
            printf("%s%*d", pad, width, matrix_get_element(mtx, r, c));
            pad = ", ";
        }
        putchar('\n');
    }
}

static void matrix_random(Matrix *mtx)
{
    size_t rows = matrix_get_rows(mtx);
    size_t cols = matrix_get_cols(mtx);
    for (size_t r = 0; r < rows; r++)
    {
        for (size_t c = 0; c < cols; c++)
            matrix_set_element(mtx, r, c, (rand() % (rows * cols) + 1));
    }
}

static int i_log10(size_t n)
{
    if (n < 10)
        return 1;
    int c = 1;
    while (n >= 10)
    {
        n /= 10;
        c++;
    }
    return c;
}

static int i_pow10(int n)
{
    int r = 1;
    while (n-- > 0)
        r *= 10;
    return r;
}

static void matrix_ordered(Matrix *mtx)
{
    size_t rows = matrix_get_rows(mtx);
    size_t cols = matrix_get_cols(mtx);
    int mul = i_pow10(i_log10(cols));
    for (size_t r = 0; r < rows; r++)
    {
        for (size_t c = 0; c < cols; c++)
            matrix_set_element(mtx, r, c, (r + 1) * mul + c + 1);
    }
}

static void err_exit(const char *fmt, ...)
{
    va_list args;
    int errnum = errno;
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    if (errnum != 0)
        fprintf(stderr, " (%d: %s)", errnum, strerror(errnum));
    putc('\n', stderr);
    exit(EXIT_FAILURE);
}

static Matrix *matrix_checked_constructor(const char *tag, size_t rows, size_t cols)
{
    Matrix *mp = matrix_constructor(rows, cols);
    if (mp == NULL)
        err_exit("Failed to construct matrix %s", tag);
    return mp;
}

int main(void)
{
    Matrix *mi5 = matrix_checked_constructor("MI5", 5, 5);
    Matrix *mi6 = matrix_checked_constructor("MI6", 6, 6);
    Matrix *ks69 = matrix_checked_constructor("KS69", 6, 9);
    Matrix *bw1815 = matrix_checked_constructor("BW1815", 18, 15);

    time_t now = time(0);
    srand(now);
    printf("Seed: %jd\n", (intmax_t)now);

    matrix_random(mi5);
    matrix_random(mi6);
    matrix_ordered(ks69);
    matrix_ordered(bw1815);

    matrix_print("MI5", mi5, 2);
    matrix_print("MI6", mi6, 2);
    matrix_print("KS69", ks69, 3);
    matrix_print("BW1815", bw1815, 4);

    matrix_destructor(mi5);
    matrix_destructor(mi6);

    return 0;
}
/* EOF - test.matrix.c */

示例输出:

Seed: 1605897737
MI5 (5x5):
14, 22,  5, 21, 11
23,  5, 23,  7,  2
10,  9,  9,  2, 24
10,  6, 21,  6, 11
 5, 11,  5, 18,  3
MI6 (6x6):
25, 33,  4, 18, 24, 19
 6,  1, 23, 19,  6, 24
17,  2, 26,  3,  2, 32
 7, 34,  8,  5, 11, 33
 6,  7, 34, 13, 21, 14
15, 25, 32, 11, 28, 28
KS69 (6x9):
 11,  12,  13,  14,  15,  16,  17,  18,  19
 21,  22,  23,  24,  25,  26,  27,  28,  29
 31,  32,  33,  34,  35,  36,  37,  38,  39
 41,  42,  43,  44,  45,  46,  47,  48,  49
 51,  52,  53,  54,  55,  56,  57,  58,  59
 61,  62,  63,  64,  65,  66,  67,  68,  69
BW1815 (18x15):
 101,  102,  103,  104,  105,  106,  107,  108,  109,  110,  111,  112,  113,  114,  115
 201,  202,  203,  204,  205,  206,  207,  208,  209,  210,  211,  212,  213,  214,  215
 301,  302,  303,  304,  305,  306,  307,  308,  309,  310,  311,  312,  313,  314,  315
 401,  402,  403,  404,  405,  406,  407,  408,  409,  410,  411,  412,  413,  414,  415
 501,  502,  503,  504,  505,  506,  507,  508,  509,  510,  511,  512,  513,  514,  515
 601,  602,  603,  604,  605,  606,  607,  608,  609,  610,  611,  612,  613,  614,  615
 701,  702,  703,  704,  705,  706,  707,  708,  709,  710,  711,  712,  713,  714,  715
 801,  802,  803,  804,  805,  806,  807,  808,  809,  810,  811,  812,  813,  814,  815
 901,  902,  903,  904,  905,  906,  907,  908,  909,  910,  911,  912,  913,  914,  915
1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015
1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115
1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215
1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315
1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415
1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515
1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615
1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715
1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815

【讨论】:

    猜你喜欢
    • 2020-10-16
    • 2023-03-06
    • 2016-08-13
    • 2014-11-24
    • 1970-01-01
    • 2012-01-22
    • 2011-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多