C中未知矩阵的动态分配

问题描述 投票:-3回答:2

我需要获取用户输入的文件,然后乘以另一个文件。我知道该怎么办。

问题是一个文件是一个数组,另一个是矩阵。

我需要在矩阵的第一行中扫描以找到矩阵的大小,然后从文件中动态分配矩阵和数组。

这是我到目前为止所拥有的:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
int main()
{       
    int row1, col1;
        //These values need to be pulled from the first file//
    char filename1[100];
        //Setting the file name for entry and setting the limit to 100//
    FILE* fp1;
        //FILE must be set as a pointer (FILE must also be capitalized)//

    printf("Enter file name including file extension: \n");
        //This will pull in the name entered by the user//
    scanf("%s", filename1);
        //Scans in the name of the first file//

    fp1 = fopen(filename1, "r");
        //This will open the file as entered by the user//
    if (fp1 == NULL)
    {
        printf("\nError, file not found\n");
        exit(0);
    }
        //This is for the first file//

    char filename2[100];
        //Setting the file name for entry and setting the limit to 100//
    FILE* fp2;
        //FILE must be set as a pointer (FILE must also be capitalized)//

    printf("Enter file name including file extension: \n");
        //This will pull in the name entered by the user//
    scanf("%s", filename2);
        //Scans in the name of the first file//

    fp2 = fopen(filename2, "r");
        //This will open the file as entered by the user//
    if (fp2 == NULL)
    {
        printf("\nError, file not found\n");
        exit(0);
    }
        //This is for the second file//

        //**I need to now dynamically allocate the input files**//

    return 0;
} 

[也感到抱歉,我似乎在发布问题后才离开,因为一些成员在评论中分享了我在钓鱼的信息。我不是;我只是没有意识到这个社区有多活跃。到目前为止,感谢您的输入。

Here is the screenshot of all I have so far including the files that are going to be read in.

感谢您的建议。我能够找出“ fgets”函数,并用它从第一个文件中提取矩阵的大小。有了这些之后,动态分配就很容易了。

c arrays matrix memory-management dynamic-memory-allocation
2个回答
2
投票

我的建议是考虑您的矩阵具有要实现的某些abstract data type

一种常见的方法可能是使用一个指针数组(用于表示矩阵行的数组)。但我感到这很混乱且效率低下。

那么,您要对矩阵执行哪些操作?

  • 创建给定尺寸的矩阵

  • 销毁先前创建的矩阵

  • 使用给定的行和列索引访问给定矩阵中的某些元素

  • 用给定的行和列索引更改给定矩阵中元素的值

  • etc ....

BTW,您可能有几种变体。例如,您可以进行错误检查(例如拒绝否定索引),或者具有不安全(但速度稍快)的功能,可以undefined behavior(并且非常scary)。当然,您可以定义更多的操作(使用其他操作),例如矩阵乘法等。

您应该在纸上或板上列出-[[all您要在矩阵上进行的操作,并在文档(或评论)中进行解释。实际上,您可能会对抽象数据类型进行数十甚至数百次操作。还要记录错误情况下的情况。

我通常建议将尺寸与矩阵保持一致(除非您知道某些尺寸为常数)。在C中实现抽象数据类型的一种常见方法是将它们封装在某些struct中,并使用指向它们的指针。

所以我建议使用flexible array member(作为struct

last

元素)。这是我的matrix_st结构: struct matrix_st { unsigned m_h, m_w; // height and width of matrix double m_v[]; // values inside the matrixes, there are m_h*m_w of them };
所以我的抽象数据类型只是指向]的指针>

typedef struct matrix_st Matrix;

这里是实现我的抽象数据类型的函数的声明:

Matrix* matrix_create(unsigned height, unsigned width); void matrix_destroy(Matrix*mat); double matrix_access(Matrix*mat, unsigned i, unsigned j); void matrix_change_element(Matrix*mat, unsigned i, unsigned j,double v);

这里有一些实现(因为我不想处理病理上巨大的矩阵,所以我定义了一些最大的维;计算机资源总是有限的!):

#define MATRIX_MAXDIM 10000000 /* ten millions */ Matrix* matrix_create(unsigned height, unsigned width) { if (height>MATRIX_MAXDIM || width>MATRIX_MAXDIM) { fprintf(stderr, "too huge matrix height=%u width=%u\n", height, width); exit(EXIT_FAILURE); }; Matrix* res = calloc(1, sizeof(Matrix) + height*width*sizeof(double)); if (!res) { perror("matrix calloc"); exit(EXIT_FAILURE); }; res->m_h = height; res->m_w = width; return res; } // end matrix_create

我使用calloc而不是malloc,因为我确实想要一些零位内存。因此,返回的矩阵包含全零。 BTW在某些计算机(不是我的PC / Linux / Debian / x86-64台式机)上,height*width*sizeof(double)可能溢出。

这里是访问某些元素的功能。它进行一些错误检查。

double matrix_access(Matrix*mat, unsigned i, unsigned j) { if (!mat) { fprintf(stderr, "no matrix to access\n"); exit(EXIT_FAILURE; }; unsigned h = mat->m_h; unsigned w = mat->m_w; if (i >= h || j >= w) { fprintf(stderr, "out-of-bound matrix access\n"); exit(EXIT_FAILURE); }; return mat->m_v [i*h + j]; }

因为我只制作了一个calloc,所以破坏很容易编写代码:

void matrix_destroy(Matrix*mat) { if (!mat) { fprintf(stderr, "no matrix to destroy\n"); exit(EXIT_FAILURE); }; assert (mat->m_h < MATRIX_MAXDIM); assert (mat->m_w < MATRIX_MAXDIM); free (mat); }

assert语句原则上是无用的(它们检查应该[[始终
为真的内容)。但是我喜欢defensive programming(这将有助于我在某些[[other
地方滥用Matrix的地方捕获错误)。可以在编译时将其禁用(读取assert(3))。

顺便说一句,您可以将这些函数声明为inlinestatic inline(并在某些附带的头文件中定义它们)。 optimizing compiler可能会产生有效的代码(例如,基准测试时编译with gcc -O2 -Wall -march=native)。由于正在从某个文件中读取矩阵,因此应定义file format(在文档中使用一些EBNF表示法来描述该文件中的语法很有用),并且可以定义并实现函数读取并从一些打开的文件句柄创建一个矩阵。

编码其他功能作为练习留给读者。

不要忘记编译with所有警告和调试信息,因此gcc -Wall -Wextra -gGCC一起编译。


使用调试器gdb(还有gdb搜索valgrind)。读取每个使用的函数的valgrind(例如,您的代码不检查memory leaks的返回计数,但实际上应该这样做)。运行多个documentation。尝试说服自己代码是好的(通过证明部分代码)。也许使用一些scanf(例如scanf,需要在test cases中添加额外的注释)。如果您需要static source code analyzer您的程序,请在编译时启用Frama-C(例如,将ACSL传递给benchmark...。)。

在代码注释中,您要求的是:


optimizations

您没有分配输入-O2 -march=nativegcc正在管理它们),而是分配了一些

内存区域。了解有关 // I need to now dynamically allocate the input files 的信息。请注意,内存分配可能会失败(例如files中记录的内容),因为operating system不能无限增长。
BTW,C dynamic memory allocation受限制(通常在台式计算机上为一兆字节或其中的几个字节),因此您通常要避免使用大的malloc(3),因此这是另一个避免在调用帧中放置矩阵的好理由并倾向于为其分配动态内存。

我看不到您实际在哪里读取行/列计数,但是一旦获得它们,分配就很简单:


2
投票
© www.soinside.com 2019 - 2024. All rights reserved.