如何从文件中读取矩阵?

时间:2021-10-04 04:48:54

I know this same question has been asked a hundred times before, but they either don't help me or they aren't answered.

我知道同样的问题之前已被问过一百次,但他们要么不帮助我,要么他们没有回答。

I want to read a text file which has some integers in a format like this:

我想读取一个文本文件,其中包含一些整数,格式如下:

1;50
2;40
3;180

this file can go forever so I can't create an array with a fixed size. So far the summarized part of what I have done (full code isn't like this, I have checked if files aren't null, made file pointers, put them in different functions etc.) :

这个文件可以永远存在,所以我不能创建一个固定大小的数组。到目前为止,我所做的总结部分(完整代码不是这样的,我检查过文件是否为空,制作文件指针,将它们放在不同的函数中等):

int **mymatrix;
mymatrix =(int **) malloc(sizeof(int*)*1);
fscanf(file, "%d", &mymatrix[0]);
fscanf(file, ";%d", &mymatrix[1]);

and to print that:

并打印:

printf("%d",  *mymatrix[0]);
printf(" %d", *mymatrix[0]);

I have looked some similar questions and learned the malloc line from them. I have tried doing fscanf(file, "%d;%d", something) and replaced something with every possible combination of *, **, &, && and also tried [0], [1] but still can't read anything.

我看了一些类似的问题,并从中学到了malloc系列。我已经尝试过fscanf(文件,“%d;%d”,某些东西)并用*,**,&,&&的每种可能组合替换了一些东西,并尝试了[0],[1]但仍然无法读取任何东西。

I don't need that print part on my code (also tried every possible combinations but no luck). I had placed breakpoints after scanf's but Visual Studio shows mymatrix as < unable to read memory >.

我不需要在我的代码上打印部分(也尝试了所有可能的组合,但没有运气)。我在scanf之后放置了断点,但Visual Studio将mymatrix显示为 <无法读取内存> 。

So, there should be a combination of scanf that I haven't tried. If anyone can help me on that part, I greatly appreciate it.

所以,应该有一个我没试过的scanf的组合。如果有人可以帮助我,我非常感激。

6 个解决方案

#1


1  

Like this:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    FILE *fp = fopen("matrix.txt", "r");
    if(!fp){
        perror("fopen");
        return 1;
    }

    int d1, d2, rows = 0;
    while(2 == fscanf(fp, "%d;%d", &d1, &d2))
        ++rows;
    int **matrix = malloc(rows * sizeof(*matrix));

    rewind(fp);
    rows = 0;
    while(2 == fscanf(fp, "%d;%d", &d1, &d2)){
        matrix[rows] = malloc(2 * sizeof(**matrix));
        matrix[rows][0] = d1;
        matrix[rows++][1] = d2;
    }
    fclose(fp);
    //print and free'd
    for(int r = 0; r < rows; ++r){
        printf("%d %d\n", matrix[r][0], matrix[r][1]);
        free(matrix[r]);
    }
    free(matrix);
    return 0;
}

realloc version.

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    FILE *fp;
    int **matrix = NULL;
    int d1, d2, r, rows = 0;

    fp = fopen("data.txt", "r");
    if(!fp){
        perror("fopen");
        return 1;
    }

    while(2 == fscanf(fp, "%d;%d", &d1, &d2)){
        matrix = realloc(matrix, (rows+1)*sizeof(*matrix));//In the case of large files increase the size that you want to extend. It must have control of the timing.
        matrix[rows] = malloc(2 * sizeof(**matrix));
        matrix[rows][0] = d1;
        matrix[rows][1] = d2;
        ++rows;
    }
    fclose(fp);
    //print and free'd
    for(r = 0; r < rows; ++r){
        printf("%d %d\n", matrix[r][0], matrix[r][1]);
        free(matrix[r]);
    }
    free(matrix);
    return 0;
}

#2


2  

First, int **mymatrix; is not a matrix/2D array and cannot represent one.

首先,int ** mymatrix;不是矩阵/ 2D数组,不能代表一个。

Said that, you should use a pointer to a 1D array/matrix:

说,你应该使用指向1D数组/矩阵的指针:

// avoid magic numbers!
#define COLS 2

// Points to the matrix. Starts without matrix
int (*mymatrix)[COLS] = NULL;

Despite its type, it can point to a 2D array. As a general rule, a "pointer to an array of N dimensions" can be used to address an "array of N+1 dimensions.

尽管它的类型,它可以指向2D阵列。作为一般规则,“指向N维数组的指针”可用于解决“N + 1维数组”。

// the amount to grow the array (min. 1, but that is inefficient)
#define GROW_LENGTH 10

// this holds the total number of rows in the array
size_t length = 0;

// row to store next entry
size_t row = 0;

// buffer for input data
int buffer[COLS];

// read data until failure
while ( scanf("%d;%d", &buffer[0], &buffer[1]) == 2 ) {

    if ( row >= length ) {

        // enlarge the array for another block
        int (*p)[COLS] = realloc(mymatrix,
                sizeof(*mymatrix) * (length + GROW_LENGTH));

        if ( p == NULL ) {
            // realloc failed

            // release the matrix and terminate (can be changed to more inteligent behaviour)
            free(mymatrix);
            exit(1);
        }

        // update variables
        mymatrix = p;
        length += GROW_LENGTH;
    }

    // store the data into the matrix
    mymatrix[row][0] = buffer[0];
    mymatrix[row][1] = buffer[1];

    // next position in buffer
    row++;
}

if ( mymatrix == NULL ) {
    // nothing has been read
}

// process the data. 
// `row` contains the number of rows with data

Don't forget to release the array when done:

完成后不要忘记释放数组:

free(mymatrix);

The code above is a fragment. It requires some standard headers and a function, of course. Best is to wrap the reading part into its own function with a clean interface to the caller. It also reads from stdin; change to fscanf is simple.

上面的代码是一个片段。当然,它需要一些标准的标题和功能。最好的方法是将读取部分包装到自己的函数中,并为调用者提供一个干净的接口。它也从stdin读取;改为fscanf很简单。

Also the printing part is straight-forward, just loop over all rows. and print each column.

打印部件也是直接的,只是在所有行上循环。并打印每列。

Note that this code will allocate at most GROW_LENGTH - 1 unused rows. Set to 1 to have no overhead at all, but that is less efficient, as realloc is called fore every row. The best balance depends on the application, OS, etc.

请注意,此代码最多将分配GROW_LENGTH - 1个未使用的行。设置为1以完全没有开销,但效率较低,因为每行调用realloc。最佳平衡取决于应用程序,操作系统等。

#3


1  

First, your arguments to fscanf don't match the format string. mymatrix[0] is an int *, so &mymatrix[0] is an int **. Compiling with -Wall -Wextra will warn you of this.

首先,您对fscanf的参数与格式字符串不匹配。 mymatrix [0]是一个int *,所以&mymatrix [0]是一个int **。使用-Wall -Wextra进行编译将警告您这一点。

Also, you allocate space for a 1 element array of int *, but then you don't populate that pointer.

此外,您为int *的1个元素数组分配空间,但之后您不会填充该指针。

You need to allocate an array of 2 int to assign to the first element of mymatrix, then pass the address of each of those to fscanf:

你需要分配一个2 int的数组来分配给mymatrix的第一个元素,然后将每个元素的地址传递给fscanf:

int **mymatrix;
mymatrix = malloc(sizeof(int*)*1);    // don't cast the return value of malloc
mymatrix[0] = malloc(sizeof(int)*2);  // same here
fscanf(file, "%d", &mymatrix[0][0]);
fscanf(file, ";%d", &mymatrix[0][1]);

Then you print them like this:

然后你打印出来像这样:

printf("%d",  mymatrix[0][0]);
printf(" %d", mymatrix[0][1]);

When reading each subsequent line, you'll need to realloc instead of malloc and keep track of how many lines you have and which line you're on.

在阅读每个后续行时,您需要重新分配而不是malloc并跟踪您拥有的行数以及您所在的行。

#4


0  

If mymatrix were defined as int mymatrix[3][2], you could read the first line doing:

如果mymatrix被定义为int mymatrix [3] [2],你可以阅读第一行:

fscanf(file, "%d;%d", &mymatrix[0][0], &mymatrix[0][1]);

The same code would work with mymatrix defined as int **mymatrix, if it would point to a dynamically initialized array of pointers to arrays of int as follows:

相同的代码可以使用定义为int ** mymatrix的mymatrix,如果它指向一个动态初始化的int数组指针数组,如下所示:

mymatrix=(int**)calloc(lines, sizeof(int*)); // intialize the array of array
for (inti=0; i<lines; i++) 
    mymatrix[i]=(int*)calloc(cols, sizeof(int));  //intialise each array  

The number of lines and cols of the matrix could then be defined at runtinme.

然后可以在runtinme中定义矩阵的行数和列数。

#5


0  

In addition to all of the other fine answers, why not use a pointer to array of int 2 (or whatever the size of your elements are)? In your circumstance, this is an optimal approach. There is no need to use a pointer to pointer to int. That complicates allocation and freeing of the memory. A pointer to array gives you single allocation of blocks, single freeing of all allocated memory and the 2D indexing you desire.

除了所有其他精细答案之外,为什么不使用指向int 2数组的指针(或者你的元素的大小是什么)?在您的情况下,这是一种最佳方法。没有必要使用指向int的指针。这使得分配和释放内存变得复杂。指向数组的指针为您提供单个块分配,单个释放所有已分配的内存以及所需的2D索引。

If you are reading from your file and storing a collection of integer pairs, you need only use a pointer to array, e.g.

如果您正在从文件中读取并存储整数对的集合,则只需使用指向数组的指针,例如

    int (*arr)[2] = NULL;

That makes allocation with either malloc or calloc a single call to allocate storage an initial number of pairs, and makes freeing the memory a single call. For example, if you have a variable maxn of 64, then to allocate a block of memory to hold the first 64 pairs of integers read from the file, you need only:

这使得使用malloc或calloc进行单次调用分配存储初始数量的对,并使内存释放一次。例如,如果您的变量maxn为64,那么要分配一块内存来保存从文件中读取的前64对整数,您只需要:

     arr = calloc (maxn, sizeof *arr);

There is no need for a separate call to allocate storage for every 2-integers, when your reach your initial limit of 64, you simply realloc your array and keep going. The following uses a constant MAXN to realloc for an additional 64 pairs each time the current index idx reaches the limit maxn (the new block of memory is also zeroed):

没有必要单独调用为每个2整数分配存储,当你达到初始限制64时,你只需重新分配你的数组并继续。每次当前索引idx达到极限maxn时,以下使用常量MAXN重新分配另外64对(新的内存块也归零):

    if (++idx == maxn) {
        printf ("\n  reallocating %zu to %zu\n", maxn, maxn + MAXN);
        size_t szelem = sizeof *arr;
        void *tmp = realloc (arr, (maxn + MAXN) * szelem);
        if (!tmp) {
            fprintf (stderr, "realloc() error: virtual memory exhausted.\n");
            exit (EXIT_FAILURE);                
        }
        arr = tmp;
        memset (arr + maxn * szelem, 0, MAXN * szelem);
        maxn += MAXN;
    }

Putting all the pieces together and using a few simply error checking functions for convenience, you could do something similar to the following:

为了方便起见,将所有部分放在一起并使用一些简单的错误检查功能,您可以执行类似于以下操作:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* constants for number of columns, buffer chars, and initial allocation */
enum { NCOL = 2, MAXC = 32, MAXN = 64 };

void *xcalloc (size_t nmemb, size_t sz);
void *xrealloc (void *ptr, size_t psz, size_t *nelem);
FILE *xfopen (const char *fn, const char *mode);

int main (int argc, char **argv) {

    char buf[MAXC] = {0};
    char *fmt = "%d;%d";
    int (*arr)[NCOL] = NULL;
    size_t i, idx = 0, maxn = MAXN;
    FILE *fp = argc > 1 ? xfopen (argv[1], "r") : stdin;

    /* alloc mem for array of MAXN elements */
    arr = xcalloc (maxn, sizeof *arr);

    while (fgets (buf, MAXC, fp)) {     /* read each line of input */
        int a, b;                       /* parse line for values */
        if (sscanf (buf, fmt, &a, &b) != NCOL) continue;
        arr[idx][0] = a, arr[idx][1] = b;
        if (++idx == maxn)              /* realloc as needed  */
            arr = xrealloc (arr, sizeof *arr, &maxn);
    }
    if (fp != stdin) fclose (fp);       /* close if not stdin */

    for (i = 0; i < idx; i++)
        printf (" array[%3zu][0] : %4d    [1] : %d\n",
                i, arr[i][0], arr[i][1]);

    free (arr);     /* free allocated memory */

    return 0;
}

/** xcalloc allocates memory using calloc and validates the return. */
void *xcalloc (size_t nmemb, size_t sz)
{   register void *memptr = calloc (nmemb, sz);
    if (!memptr) {
        fprintf (stderr, "xcalloc() error: virtual memory exhausted.\n");
        exit (EXIT_FAILURE);
    }
    return memptr;
}

/** realloc 'ptr' to array of elements of 'psz' to 'nelem + MAXN' elements */
void *xrealloc (void *ptr, size_t psz, size_t *nelem)
{   void *tmp = realloc ((char *)ptr, (*nelem + MAXN) * psz);
    if (!tmp) {
        fprintf (stderr, "realloc() error: virtual memory exhausted.\n");
        exit (EXIT_FAILURE);                
    }
    memset (tmp + *nelem * psz, 0, MAXN * psz);  /* zero new memory */
    *nelem += MAXN;
    return tmp;
}

/** fopen with error checking - short version */
FILE *xfopen (const char *fn, const char *mode)
{   FILE *fp = fopen (fn, mode);
    if (!fp) {
        fprintf (stderr, "xfopen() error: file open failed '%s'.\n", fn);
        // return NULL;      /* choose appropriate action */
        exit (EXIT_FAILURE);
    }
    return fp;
}

Example Input

With an initial allocation for 64 pairs, reallocation is forces in order to read the entire file. (you can set the initial size at 1 and realloc on every iteration, but that is highly inefficient -- the initial size for MAXN must be at least 1, and should be set to some reasonably anticipated number of elements given your data)

对于64对的初始分配,重新分配是强制读取整个文件。 (您可以将初始大小设置为1并在每次迭代时重新分配,但效率非常低 - MAXN的初始大小必须至少为1,并且应该设置为给定数据的某些合理预期的元素数)

$ cat dat/2d_data.txt
1;354
2;160
3;205
4;342
...
98;464
99;130
100;424

Example Use/Output

$ ./bin/array_ptr2array_realloc <dat/2d_data.txt
 array[  0][0] :    1    [1] : 354
 array[  1][0] :    2    [1] : 160
 array[  2][0] :    3    [1] : 205
 array[  3][0] :    4    [1] : 342
...
 array[ 97][0] :   98    [1] : 464
 array[ 98][0] :   99    [1] : 130
 array[ 99][0] :  100    [1] : 424

Memory Use/Error Check

内存使用/错误检查

In any code your write that dynamically allocates memory, you have 2 responsibilites regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.

在你的动态分配内存的任何代码中,你有2个责任关于任何分配的内存块:(1)总是保留一个指向内存块起始地址的指针,所以,(2)它可以在没有时被释放需要更久。

It is imperative that you use a memory error checking program to insure you haven't written beyond/outside your allocated block of memory, attempted to read or base a jump on an unintitialized value and finally to confirm that you have freed all the memory you have allocated. For Linux valgrind is the normal choice.

您必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,尝试读取或基于未初始化的值跳转,并最终确认您已释放所有内存分配了。对于Linux,valgrind是正常的选择。

$ valgrind ./bin/array_ptr2array_realloc <dat/2d_data.txt
==2796== Memcheck, a memory error detector
==2796== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==2796== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==2796== Command: ./bin/array_ptr2array_realloc
==2796==
 array[  0][0] :    1    [1] : 354
 array[  1][0] :    2    [1] : 160
 array[  2][0] :    3    [1] : 205
 array[  3][0] :    4    [1] : 342
...
 array[ 97][0] :   98    [1] : 464
 array[ 98][0] :   99    [1] : 130
 array[ 99][0] :  100    [1] : 424
==2796==
==2796== HEAP SUMMARY:
==2796==     in use at exit: 0 bytes in 0 blocks
==2796==   total heap usage: 2 allocs, 2 frees, 1,536 bytes allocated
==2796==
==2796== All heap blocks were freed -- no leaks are possible
==2796==
==2796== For counts of detected and suppressed errors, rerun with: -v
==2796== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)

Always confirm All heap blocks were freed -- no leaks are possible and equally important ERROR SUMMARY: 0 errors from 0 contexts.

始终确认释放所有堆块 - 不可能发生泄漏,同样重要的错误摘要:0个上下文中的0个错误。

Look over all the answers and let me know if you have any further questions. Using a pointer to array makes a whole lot of sense in a number of situations such as this. It simplifies allocation and freeing of memory and preserves your 2D indexing as well.

查看所有答案,如果您有任何其他问题,请告诉我。在许多情况下使用指向数组的指针非常有意义。它简化了内存的分配和释放,并保留了您的2D索引。

#6


-1  

You will have to malloc the memory to mymatrix[0].

你必须将内存malloc到mymatrix [0]。

mymatrix[0]= (int *) malloc ( sizeof (int) *2);

Also, in mymatrix malloc, 1 actually means the maximum number of rows you will have. So you can at max have 1 row as per that.

此外,在mymatrix malloc中,1实际上表示您将拥有的最大行数。所以你最多可以有1行。

#1


1  

Like this:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    FILE *fp = fopen("matrix.txt", "r");
    if(!fp){
        perror("fopen");
        return 1;
    }

    int d1, d2, rows = 0;
    while(2 == fscanf(fp, "%d;%d", &d1, &d2))
        ++rows;
    int **matrix = malloc(rows * sizeof(*matrix));

    rewind(fp);
    rows = 0;
    while(2 == fscanf(fp, "%d;%d", &d1, &d2)){
        matrix[rows] = malloc(2 * sizeof(**matrix));
        matrix[rows][0] = d1;
        matrix[rows++][1] = d2;
    }
    fclose(fp);
    //print and free'd
    for(int r = 0; r < rows; ++r){
        printf("%d %d\n", matrix[r][0], matrix[r][1]);
        free(matrix[r]);
    }
    free(matrix);
    return 0;
}

realloc version.

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    FILE *fp;
    int **matrix = NULL;
    int d1, d2, r, rows = 0;

    fp = fopen("data.txt", "r");
    if(!fp){
        perror("fopen");
        return 1;
    }

    while(2 == fscanf(fp, "%d;%d", &d1, &d2)){
        matrix = realloc(matrix, (rows+1)*sizeof(*matrix));//In the case of large files increase the size that you want to extend. It must have control of the timing.
        matrix[rows] = malloc(2 * sizeof(**matrix));
        matrix[rows][0] = d1;
        matrix[rows][1] = d2;
        ++rows;
    }
    fclose(fp);
    //print and free'd
    for(r = 0; r < rows; ++r){
        printf("%d %d\n", matrix[r][0], matrix[r][1]);
        free(matrix[r]);
    }
    free(matrix);
    return 0;
}

#2


2  

First, int **mymatrix; is not a matrix/2D array and cannot represent one.

首先,int ** mymatrix;不是矩阵/ 2D数组,不能代表一个。

Said that, you should use a pointer to a 1D array/matrix:

说,你应该使用指向1D数组/矩阵的指针:

// avoid magic numbers!
#define COLS 2

// Points to the matrix. Starts without matrix
int (*mymatrix)[COLS] = NULL;

Despite its type, it can point to a 2D array. As a general rule, a "pointer to an array of N dimensions" can be used to address an "array of N+1 dimensions.

尽管它的类型,它可以指向2D阵列。作为一般规则,“指向N维数组的指针”可用于解决“N + 1维数组”。

// the amount to grow the array (min. 1, but that is inefficient)
#define GROW_LENGTH 10

// this holds the total number of rows in the array
size_t length = 0;

// row to store next entry
size_t row = 0;

// buffer for input data
int buffer[COLS];

// read data until failure
while ( scanf("%d;%d", &buffer[0], &buffer[1]) == 2 ) {

    if ( row >= length ) {

        // enlarge the array for another block
        int (*p)[COLS] = realloc(mymatrix,
                sizeof(*mymatrix) * (length + GROW_LENGTH));

        if ( p == NULL ) {
            // realloc failed

            // release the matrix and terminate (can be changed to more inteligent behaviour)
            free(mymatrix);
            exit(1);
        }

        // update variables
        mymatrix = p;
        length += GROW_LENGTH;
    }

    // store the data into the matrix
    mymatrix[row][0] = buffer[0];
    mymatrix[row][1] = buffer[1];

    // next position in buffer
    row++;
}

if ( mymatrix == NULL ) {
    // nothing has been read
}

// process the data. 
// `row` contains the number of rows with data

Don't forget to release the array when done:

完成后不要忘记释放数组:

free(mymatrix);

The code above is a fragment. It requires some standard headers and a function, of course. Best is to wrap the reading part into its own function with a clean interface to the caller. It also reads from stdin; change to fscanf is simple.

上面的代码是一个片段。当然,它需要一些标准的标题和功能。最好的方法是将读取部分包装到自己的函数中,并为调用者提供一个干净的接口。它也从stdin读取;改为fscanf很简单。

Also the printing part is straight-forward, just loop over all rows. and print each column.

打印部件也是直接的,只是在所有行上循环。并打印每列。

Note that this code will allocate at most GROW_LENGTH - 1 unused rows. Set to 1 to have no overhead at all, but that is less efficient, as realloc is called fore every row. The best balance depends on the application, OS, etc.

请注意,此代码最多将分配GROW_LENGTH - 1个未使用的行。设置为1以完全没有开销,但效率较低,因为每行调用realloc。最佳平衡取决于应用程序,操作系统等。

#3


1  

First, your arguments to fscanf don't match the format string. mymatrix[0] is an int *, so &mymatrix[0] is an int **. Compiling with -Wall -Wextra will warn you of this.

首先,您对fscanf的参数与格式字符串不匹配。 mymatrix [0]是一个int *,所以&mymatrix [0]是一个int **。使用-Wall -Wextra进行编译将警告您这一点。

Also, you allocate space for a 1 element array of int *, but then you don't populate that pointer.

此外,您为int *的1个元素数组分配空间,但之后您不会填充该指针。

You need to allocate an array of 2 int to assign to the first element of mymatrix, then pass the address of each of those to fscanf:

你需要分配一个2 int的数组来分配给mymatrix的第一个元素,然后将每个元素的地址传递给fscanf:

int **mymatrix;
mymatrix = malloc(sizeof(int*)*1);    // don't cast the return value of malloc
mymatrix[0] = malloc(sizeof(int)*2);  // same here
fscanf(file, "%d", &mymatrix[0][0]);
fscanf(file, ";%d", &mymatrix[0][1]);

Then you print them like this:

然后你打印出来像这样:

printf("%d",  mymatrix[0][0]);
printf(" %d", mymatrix[0][1]);

When reading each subsequent line, you'll need to realloc instead of malloc and keep track of how many lines you have and which line you're on.

在阅读每个后续行时,您需要重新分配而不是malloc并跟踪您拥有的行数以及您所在的行。

#4


0  

If mymatrix were defined as int mymatrix[3][2], you could read the first line doing:

如果mymatrix被定义为int mymatrix [3] [2],你可以阅读第一行:

fscanf(file, "%d;%d", &mymatrix[0][0], &mymatrix[0][1]);

The same code would work with mymatrix defined as int **mymatrix, if it would point to a dynamically initialized array of pointers to arrays of int as follows:

相同的代码可以使用定义为int ** mymatrix的mymatrix,如果它指向一个动态初始化的int数组指针数组,如下所示:

mymatrix=(int**)calloc(lines, sizeof(int*)); // intialize the array of array
for (inti=0; i<lines; i++) 
    mymatrix[i]=(int*)calloc(cols, sizeof(int));  //intialise each array  

The number of lines and cols of the matrix could then be defined at runtinme.

然后可以在runtinme中定义矩阵的行数和列数。

#5


0  

In addition to all of the other fine answers, why not use a pointer to array of int 2 (or whatever the size of your elements are)? In your circumstance, this is an optimal approach. There is no need to use a pointer to pointer to int. That complicates allocation and freeing of the memory. A pointer to array gives you single allocation of blocks, single freeing of all allocated memory and the 2D indexing you desire.

除了所有其他精细答案之外,为什么不使用指向int 2数组的指针(或者你的元素的大小是什么)?在您的情况下,这是一种最佳方法。没有必要使用指向int的指针。这使得分配和释放内存变得复杂。指向数组的指针为您提供单个块分配,单个释放所有已分配的内存以及所需的2D索引。

If you are reading from your file and storing a collection of integer pairs, you need only use a pointer to array, e.g.

如果您正在从文件中读取并存储整数对的集合,则只需使用指向数组的指针,例如

    int (*arr)[2] = NULL;

That makes allocation with either malloc or calloc a single call to allocate storage an initial number of pairs, and makes freeing the memory a single call. For example, if you have a variable maxn of 64, then to allocate a block of memory to hold the first 64 pairs of integers read from the file, you need only:

这使得使用malloc或calloc进行单次调用分配存储初始数量的对,并使内存释放一次。例如,如果您的变量maxn为64,那么要分配一块内存来保存从文件中读取的前64对整数,您只需要:

     arr = calloc (maxn, sizeof *arr);

There is no need for a separate call to allocate storage for every 2-integers, when your reach your initial limit of 64, you simply realloc your array and keep going. The following uses a constant MAXN to realloc for an additional 64 pairs each time the current index idx reaches the limit maxn (the new block of memory is also zeroed):

没有必要单独调用为每个2整数分配存储,当你达到初始限制64时,你只需重新分配你的数组并继续。每次当前索引idx达到极限maxn时,以下使用常量MAXN重新分配另外64对(新的内存块也归零):

    if (++idx == maxn) {
        printf ("\n  reallocating %zu to %zu\n", maxn, maxn + MAXN);
        size_t szelem = sizeof *arr;
        void *tmp = realloc (arr, (maxn + MAXN) * szelem);
        if (!tmp) {
            fprintf (stderr, "realloc() error: virtual memory exhausted.\n");
            exit (EXIT_FAILURE);                
        }
        arr = tmp;
        memset (arr + maxn * szelem, 0, MAXN * szelem);
        maxn += MAXN;
    }

Putting all the pieces together and using a few simply error checking functions for convenience, you could do something similar to the following:

为了方便起见,将所有部分放在一起并使用一些简单的错误检查功能,您可以执行类似于以下操作:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* constants for number of columns, buffer chars, and initial allocation */
enum { NCOL = 2, MAXC = 32, MAXN = 64 };

void *xcalloc (size_t nmemb, size_t sz);
void *xrealloc (void *ptr, size_t psz, size_t *nelem);
FILE *xfopen (const char *fn, const char *mode);

int main (int argc, char **argv) {

    char buf[MAXC] = {0};
    char *fmt = "%d;%d";
    int (*arr)[NCOL] = NULL;
    size_t i, idx = 0, maxn = MAXN;
    FILE *fp = argc > 1 ? xfopen (argv[1], "r") : stdin;

    /* alloc mem for array of MAXN elements */
    arr = xcalloc (maxn, sizeof *arr);

    while (fgets (buf, MAXC, fp)) {     /* read each line of input */
        int a, b;                       /* parse line for values */
        if (sscanf (buf, fmt, &a, &b) != NCOL) continue;
        arr[idx][0] = a, arr[idx][1] = b;
        if (++idx == maxn)              /* realloc as needed  */
            arr = xrealloc (arr, sizeof *arr, &maxn);
    }
    if (fp != stdin) fclose (fp);       /* close if not stdin */

    for (i = 0; i < idx; i++)
        printf (" array[%3zu][0] : %4d    [1] : %d\n",
                i, arr[i][0], arr[i][1]);

    free (arr);     /* free allocated memory */

    return 0;
}

/** xcalloc allocates memory using calloc and validates the return. */
void *xcalloc (size_t nmemb, size_t sz)
{   register void *memptr = calloc (nmemb, sz);
    if (!memptr) {
        fprintf (stderr, "xcalloc() error: virtual memory exhausted.\n");
        exit (EXIT_FAILURE);
    }
    return memptr;
}

/** realloc 'ptr' to array of elements of 'psz' to 'nelem + MAXN' elements */
void *xrealloc (void *ptr, size_t psz, size_t *nelem)
{   void *tmp = realloc ((char *)ptr, (*nelem + MAXN) * psz);
    if (!tmp) {
        fprintf (stderr, "realloc() error: virtual memory exhausted.\n");
        exit (EXIT_FAILURE);                
    }
    memset (tmp + *nelem * psz, 0, MAXN * psz);  /* zero new memory */
    *nelem += MAXN;
    return tmp;
}

/** fopen with error checking - short version */
FILE *xfopen (const char *fn, const char *mode)
{   FILE *fp = fopen (fn, mode);
    if (!fp) {
        fprintf (stderr, "xfopen() error: file open failed '%s'.\n", fn);
        // return NULL;      /* choose appropriate action */
        exit (EXIT_FAILURE);
    }
    return fp;
}

Example Input

With an initial allocation for 64 pairs, reallocation is forces in order to read the entire file. (you can set the initial size at 1 and realloc on every iteration, but that is highly inefficient -- the initial size for MAXN must be at least 1, and should be set to some reasonably anticipated number of elements given your data)

对于64对的初始分配,重新分配是强制读取整个文件。 (您可以将初始大小设置为1并在每次迭代时重新分配,但效率非常低 - MAXN的初始大小必须至少为1,并且应该设置为给定数据的某些合理预期的元素数)

$ cat dat/2d_data.txt
1;354
2;160
3;205
4;342
...
98;464
99;130
100;424

Example Use/Output

$ ./bin/array_ptr2array_realloc <dat/2d_data.txt
 array[  0][0] :    1    [1] : 354
 array[  1][0] :    2    [1] : 160
 array[  2][0] :    3    [1] : 205
 array[  3][0] :    4    [1] : 342
...
 array[ 97][0] :   98    [1] : 464
 array[ 98][0] :   99    [1] : 130
 array[ 99][0] :  100    [1] : 424

Memory Use/Error Check

内存使用/错误检查

In any code your write that dynamically allocates memory, you have 2 responsibilites regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.

在你的动态分配内存的任何代码中,你有2个责任关于任何分配的内存块:(1)总是保留一个指向内存块起始地址的指针,所以,(2)它可以在没有时被释放需要更久。

It is imperative that you use a memory error checking program to insure you haven't written beyond/outside your allocated block of memory, attempted to read or base a jump on an unintitialized value and finally to confirm that you have freed all the memory you have allocated. For Linux valgrind is the normal choice.

您必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,尝试读取或基于未初始化的值跳转,并最终确认您已释放所有内存分配了。对于Linux,valgrind是正常的选择。

$ valgrind ./bin/array_ptr2array_realloc <dat/2d_data.txt
==2796== Memcheck, a memory error detector
==2796== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==2796== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==2796== Command: ./bin/array_ptr2array_realloc
==2796==
 array[  0][0] :    1    [1] : 354
 array[  1][0] :    2    [1] : 160
 array[  2][0] :    3    [1] : 205
 array[  3][0] :    4    [1] : 342
...
 array[ 97][0] :   98    [1] : 464
 array[ 98][0] :   99    [1] : 130
 array[ 99][0] :  100    [1] : 424
==2796==
==2796== HEAP SUMMARY:
==2796==     in use at exit: 0 bytes in 0 blocks
==2796==   total heap usage: 2 allocs, 2 frees, 1,536 bytes allocated
==2796==
==2796== All heap blocks were freed -- no leaks are possible
==2796==
==2796== For counts of detected and suppressed errors, rerun with: -v
==2796== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)

Always confirm All heap blocks were freed -- no leaks are possible and equally important ERROR SUMMARY: 0 errors from 0 contexts.

始终确认释放所有堆块 - 不可能发生泄漏,同样重要的错误摘要:0个上下文中的0个错误。

Look over all the answers and let me know if you have any further questions. Using a pointer to array makes a whole lot of sense in a number of situations such as this. It simplifies allocation and freeing of memory and preserves your 2D indexing as well.

查看所有答案,如果您有任何其他问题,请告诉我。在许多情况下使用指向数组的指针非常有意义。它简化了内存的分配和释放,并保留了您的2D索引。

#6


-1  

You will have to malloc the memory to mymatrix[0].

你必须将内存malloc到mymatrix [0]。

mymatrix[0]= (int *) malloc ( sizeof (int) *2);

Also, in mymatrix malloc, 1 actually means the maximum number of rows you will have. So you can at max have 1 row as per that.

此外,在mymatrix malloc中,1实际上表示您将拥有的最大行数。所以你最多可以有1行。