如何从文件中读取矩阵?

时间:2016-05-10 19:59:06

标签: c file matrix

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

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

1;50
2;40
3;180

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

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

并打印出来:

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

我看了一些类似的问题并从中学到了malloc系列。 我尝试过做fscanf(file, "%d;%d", something)并用*,**,&,&&并尝试[0],[1]但仍然无法读取任何内容。

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

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

6 个答案:

答案 0 :(得分:2)

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

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

// avoid magic numbers!
#define COLS 2

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

尽管它的类型,但它可以指向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

完成后不要忘记释放阵列:

free(mymatrix);

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

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

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

答案 1 :(得分:1)

首先,您对git config diff.dummy "dummy line"的参数与格式字符串不匹配。 fscanfmymatrix[0],因此int *&mymatrix[0]。使用int **进行编译会警告您。

此外,您为{1}}的1个元素数组分配空间,但是您不会填充该指针。

您需要分配一个2 -Wall -Wextra的数组来分配给int *的第一个元素,然后将每个元素的地址传递给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]); 代替printf("%d", mymatrix[0][0]); printf(" %d", mymatrix[0][1]); 并跟踪您拥有的行数以及您所在的行。

答案 2 :(得分:1)

像这样:

print data[data.artist.isnull()]
  artist
0    NaN

realloc版本。

svnadmin dump

答案 3 :(得分:1)

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

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

    int (*arr)[2] = NULL;

这使得用malloccalloc分配一次调用来分配存储的初始对数,并使内存释放一次。例如,如果变量maxn64,那么要分配一块内存来保存从文件中读取的第一对64整数,只需:

     arr = calloc (maxn, sizeof *arr);

无需单独调用为每个2位整数分配存储空间,当您达到64的初始限制时,只需realloc数组并继续运行即可。每当当前索引MAXN达到限制realloc时,以下使用常量64idx对另外的maxn对(新的内存块是也归零):

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

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

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

示例输入

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

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

示例使用/输出

$ ./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

内存使用/错误检查

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

必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,尝试读取或基于未初始化的值跳转,最后确认您已释放所有内存你分配的记忆。对于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)

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

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

答案 4 :(得分:0)

如果将 float x, y, r, g, b, radius; void setup() { size(800, 700); smooth(); frameRate(15); } void draw() { handleRedBox(); } void handleRedBox() { background(255); stroke(255, 0, 0); color from = color(100, random(255), 2); color to = color(0, 200, 0); color interA = lerpColor (to, from, .44); int x = 100; while (x < width/2 || x> width/2 ) { int y = 100; while (y <height/2 || y > height/2) { blendMode(DIFFERENCE); noStroke(); fill(interA); quadstuff(); strokeWeight(5); stroke(0, random(255), 0); line(width/2, height/2, mouseY, mouseX); translate(width, height); rotate(radians(frameCount)); y = y + 50; } x = x + 50; } ghostcirc(); ghostcirc2(); } void ghostcirc() { int w = 0; while (w < width) { int q = 0; while (q <height) { blendMode(ADD); fill(random(61), random(90), random(250)); ellipse(255, 255, 100, 100); ; noStroke(); translate(width, height); rotate(radians(frameCount)); q = q + 100; } w = w + 50; } } void ghostcirc2() { for (int w= 0; w < width; w+=10) { blendMode(ADD); fill(random(61), random(90), random(250)); ellipse(50, 50, 75, 75); ; noStroke(); translate(width, height); rotate(radians(frameCount)); //if (keyPressed == true){ // fill(random(100), random(90), random(250)); } } void quadstuff() { int rad = 60; // Width of the shape float xpos, ypos; // Starting position of shape float xspeed = 2.8; // Speed of the shape float yspeed = 2.2; // Speed of the shape xpos = width/2; ypos = height/2; //ellipse(mouseX+x, mouseY+y, 100,100); quad(xpos, ypos, rad, rad, mouseX+rad, mouseY+rad, xspeed, yspeed); stroke(0); strokeWeight(5); } 定义为mymatrix,您可以阅读第一行:

int mymatrix[3][2]

相同的代码适用于定义为fscanf(file, "%d;%d", &mymatrix[0][0], &mymatrix[0][1]); 的{​​{1}},如果它指向动态初始化的mymatrix数组指针数组,如下所示:

int **mymatrix

然后可以在runtinme中定义矩阵的intmymatrix=(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 的数量。

答案 5 :(得分:-1)

您必须malloc将记忆转移到mymatrix[0]

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

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