fscanf()和realloc() - 将文件读取到矩阵

时间:2016-08-19 02:05:53

标签: c file malloc scanf realloc

我有一个动态读取文件到2D数组的问题。我已经阅读了很长时间但我仍然不知道如何强制我的代码工作。

我的代码:http://codepaste.net/3hcbtn

#include <stdio.h>
#include <stdlib.h>
int main(){
//This program reads a file consisting of 5 columns of numbers.
//We assume that we don't know the number of rows of that file. 
double **x,**t;    
int i,j,COL=5;

x=malloc(COL*sizeof(double*));
        for(i=0;i!=COL;i++){x[i]=calloc(1,sizeof(double));}

t=malloc(COL*sizeof(double*));

FILE *f;    
f=fopen("realloc2.dat","r");

j=0;
        for(;;){
                for(i=0;i!=COL-1;i++){
                        fscanf(f,"%lf, ",&x[i][j]);
                        t[i]=realloc(x[i],sizeof(x[i]+1));
                        x[i]=t[i];
                }
                fscanf(f,"%lf\n",&x[COL-1][j]);
                        if(feof(f)!=0){break;}
                t[COL-1]=realloc(x[COL-1],sizeof(x[COL-1]+1));
                x[COL-1]=t[COL-1];

                j++;
        }

for(i=0;i!=COL;i++){
        free(x[i]);
}
free(x);
free(t);
fclose(f);

return 0;
}

输出:

*** Error in `./realloc2_2': realloc(): invalid next size: 0x0000000001d9d040 ***
[...]
Segmentation fault

我有一个包含COL列的文件,但我们不知道它有多少行,这就是我尝试使用realloc()的原因。我花了很多时间来修理它......你能帮助我吗?

谢谢。

2 个答案:

答案 0 :(得分:0)

这个想法并不错,但你有点不对劲:

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

#define REALLOC_GROW 10

    // ALL CHECKS OMMITTED!

int main()
{
//This program reads a file consisting of 5 columns of numbers.
//We assume that we don't know the number of rows of that file. 
  int i, COL = 5;
  double *row, **table, **cp;
  int allocated = 0, needed = 0;

  // one row, just as the name suggests
  // I would have choosen a simple array on the stack
  // e.g.: double row[5] = {0.0};
  // but it is your choice.
  row = malloc(COL * sizeof(double));

  // set pointer to NULL to avoid initial malloc
  table = NULL;

  FILE *f;
  f = fopen("realloc2.dat", "r");

  for (;;) {
    // check if we have enough rows preallocated
    // this is also the case in the very beginning
    if (needed >= allocated) {
      // reserve memory for ten (more) pointers
      cp = realloc(table, (needed + REALLOC_GROW) * sizeof(double *));
      table = cp;
      // allocate memory for the ten rows
      for (i = 0; i < REALLOC_GROW; i++) {
        table[needed + i] = malloc(COL * sizeof(double));
      }
      // keep the amount of rows pre-allocated
      allocated += REALLOC_GROW;
    }
    // read one row (assuming one row is on one line ending with '\n')
    fscanf(f, "%lf, %lf, %lf, %lf, %lf\n", &row[0], &row[1], &row[2], &row[3],
           &row[4]);
    // copy result into table
    memcpy(table[needed], row, COL * sizeof(double));
    // prepare for next row;
    needed++;
    // check if we are done
    // could (and should!) have been tested already with fscanf
    // but I ommitted all tests including the tests of the
    // return of fscanf
    if (feof(f)) {
      break;
    }
  }
  // print it to check it
  for (i = 0; i < needed; i++) {
    printf("%f, %f, %f, %f, %f\n", table[i][0], table[i][1], table[i][2],
           table[i][3], table[i][4]);
  }
  // clean up
  free(row);
  for (i = 0; i < allocated; i++) {
    free(table[i]);
  }
  free(table);
  fclose(f);

  exit(EXIT_SUCCESS);
}

使用shell one-liner的可憎创建的输入文件:

for i in `seq 1 1 33`;do c1=$(shuf -i 10-99 -n 1);c2=$(shuf -i 10-99 -n 1);c3=$(shuf -i 10-99 -n 1);c4=$(shuf -i 10-99 -n 1);c5=$(shuf -i 10-99 -n 1); echo "$c1.32, $c2.32, $c3.32, $c4.23, $c5.23" >> realloc2.dat;done

答案 1 :(得分:0)

像这样解决:

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

int main(void){
    double **x;
    int ROW = 5;//Provisional value
    int COL = 5;
    int c, r = 0, rows;

    FILE *fp = fopen("realloc2.dat","r");
    if(fp == NULL){
        perror("file can't open");
        exit(EXIT_FAILURE);
    }

    x = malloc(ROW * sizeof(double*));//malloc(ROW * sizeof(*x));
    for(;;++r){
        if(r == ROW){
            ROW += 5;//fitly size expansion. e.g ROW *= 2
            if((x = realloc(x, ROW * sizeof(*x))) == NULL){
                perror("failed realloc");
                exit(EXIT_FAILURE);
            }
        }
        if((x[r] = malloc(COL * sizeof(double))) == NULL){
            perror("failed malloc");
            exit(EXIT_FAILURE);
        }
        for(c = 0; c < COL; ++c){
            if(1 != fscanf(fp, "%lf", &x[r][c]))
                goto readend;
        }
    }
readend:
    rows = r;
    if(c != 0){
        puts("data are insufficient.");
    } else {
        //test print
        for(r = 0; r < rows; ++r){
            for(c = 0; c < COL; ++c){
                if(c)
                    putchar(' ');
                printf("%5.2f", x[r][c]);
            }
            puts("");
        }
    }
    fclose(fp);
    //deallocate
    for(r = 0; r <= rows; ++r){
        free(x[r]);
    }
    free(x);

    return 0;
}