在C中动态分配未知矩阵 [英] Dynamic allocation of an unknown matrix in C

查看:105
本文介绍了在C中动态分配未知矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to take a file that is inputted by the user and multiply it by another file. That much I know how to do.

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

The problem is one file is an array and the other is a matrix.

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

I need to scan in the first line of the matrix to find the size of the matrix and I then need to dynamically allocate the matrix and array from the files.

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

This is what I have so far:

#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;
} 

由于某些成员在评论中分享了我正在钓鱼的情况,因此我似乎在发布问题后才离开,也感到遗憾.我不是;我只是没有意识到这个社区有多活跃.到目前为止,感谢您的输入.

Also sorry for seeming like I just left after posting my question as some members have shared in the comments saying that I was code fishing. I'm not; I just didn't realize how active this community is. Thanks for the input so far.

这是到目前为止我所拥有的所有屏幕截图,包括将要读取的文件

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

Thanks for the suggestions. I was able to figure out the "fgets" function and I used that to pull in the size of the matrix from the first file. After I had that, dynamically allocating that was easy.

推荐答案

我的建议是考虑您的矩阵具有一些

My recommendation is to consider your matrix as having some abstract data type that you want to implement.

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

A common way might be to use an array of pointers (to arrays representing rows of your matrix). But I feel it is confusing and inefficient.

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

So what are the operations you want on your matrixes?

  • 创建给定尺寸的矩阵

  • create a matrix of given dimensions

销毁先前创建的矩阵

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

access some element in a given matrix with given row and column indexes

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

change the value of an element in a given matrix with given row and column indexes

等....

顺便说一句,您可能有几个变种.例如,您可以进行错误检查(例如拒绝否定索引),或者具有不安全(但速度稍快)的功能,这些功能可以吓人).当然,您可以定义更多的操作(使用其他操作),例如矩阵乘法等.

BTW, you might have several variants of them. For example, you could do error checking (e.g. reject a negative index) or you could have unsafe (but slightly faster) functions capable of undefined behavior (and this is very scary). Of course you could define more operations (using other ones), for example matrix multiplication etc.

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

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

I usually recommend keeping the dimensions with the matrix (unless you know that some of the dimension is a constant). A common way of implementing abstract data types in C is to encapsulate them in some struct and use pointers to these.

因此,我建议使用灵活数组成员(作为 last 元素).这是我的matrix_st结构:

So I suggest to use a flexible array member (as the last element of your struct). Here is my matrix_st structure:

  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
  };

所以我的抽象数据类型只是指向

so my abstract data type is just pointers to

  typedef struct matrix_st Matrix;

以下是实现我的抽象数据类型的函数的声明:

Here are the declarations of the functions implementing my abstract data type:

  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);

以下是一些实现(由于我不想处理病理上巨大的矩阵,因此我定义了一些最大尺寸;计算机资源始终是有限的!):

Here are some implementations (since I don't want to deal with pathologically huge matrixes, I define some maximal dimension; computer resources are always finite!):

  #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,因为我真的想要一些零位内存.因此,返回的矩阵包含全零.顺便说一句,在某些计算机(不是我的PC/Linux/Debian/x86-64台式机)上,height*width*sizeof(double)可能会溢出.

I am using calloc not malloc because I really want some zero-ed memory. So the returned matrix contains all zeros. BTW on some computers (not mine, a PC/Linux/Debian/x86-64 desktop) the height*width*sizeof(double) could overflow.

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

Here is the function to access some element. It does some error checking.

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,所以破坏很容易编写:

Since I made only one calloc the destruction is simple to code:

  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语句原则上是无用的(它们检查应始终为 的内容).但是我喜欢防御性编程(这将帮助我捕捉一些 other 中的错误 em>误用了我的Matrix).可以在以下位置禁用它们(阅读 assert(3))编译时间.

The assert statements are in principle useless (they check something which should always be true). But I love defensive programming (this would help me catching bugs in some other places misusing my Matrix). They could be disabled (read assert(3)) at compilation time.

顺便说一句,您可以将这些函数声明为inlinestatic inline(并在某些附带的头文件中定义它们). 优化编译器可能会产生有效的代码(例如,编译

BTW, you could declare these functions as inline or static inline (and define them in some included header file). An optimizing compiler is likely to produce efficient code (e.g. compile with gcc -O2 -Wall -march=native when benchmarking).

由于您正在从某个文件中读取矩阵,因此应定义您的文件格式(在文档中使用一些 EBNF 表示法来描述该语法该文件很有用),您可以定义和实现一个函数,并从打开的文件句柄中读取并创建一个矩阵.

Since you are reading a matrix from some file, you should define your file format (using, in your documentation, some EBNF notation to describe the syntax in that file is useful) and you could define and implement a function reading and creating a matrix from some opened file handle.

编码其他功能留给读者练习.

Coding the other functions is left as an exercise to the reader.

别忘了用所有警告和调试来编译信息,因此gcc -Wall -Wextra -g带有 GCC . 使用调试器 gdb (还有 valgrind 来寻找文档(例如,您的代码不检查的返回计数 scanf ,但确实如此).运行几个测试用例.尝试让自己相信您的代码是好的(通过证明部分代码).也许使用一些静态源代码分析器(例如 ACSL ).如果您需要基准您的程序,请启用

Don't forget to compile with all warnings and debug info, so gcc -Wall -Wextra -g with GCC. Use the debugger gdb (and also valgrind to hunt memory leaks). Read the documentation of every used function (for example your code don't check the return count of scanf but it really should). Run several test cases. Try to convince yourself that your code is good (by proving parts of it). Perhaps use some static source code analyzer (e.g. Frama-C, which wants extra annotations in ACSL). If you need to benchmark your program, enable optimizations at compile time (e.g. by passing -O2 -march=native to gcc ....).

在代码注释中,您要求:

In a code comment you are asking:

 // I need to now dynamically allocate the input files

您不分配输入文件( C动态内存分配的信息.请注意,内存分配可能会失败(例如,如 malloc(3)<中所述/a>),因为您的虚拟地址空间不能无限期增长.

You don't allocate input files (the operating system is managing them), you allocate some memory zone. Read about C dynamic memory allocation. Notice that memory allocation can fail (e.g. as documented in malloc(3)), because your virtual address space cannot grow indefinitely.

顺便说一句,调用堆栈受限制(通常为兆字节或其中的几个字节)在台式机上),因此您通常要避免使用较大的自动变量,因此这是另一个好处避免在调用框架中放置矩阵,而倾向于为其分配动态内存的原因.

BTW, the call stack is limited (typically to a megabyte or a few of them on desktop computers), so you generally want to avoid large automatic variables, so that is another good reason to avoid putting matrixes in your call frame and to prefer dynamic memory allocation for them.

这篇关于在C中动态分配未知矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆