-1

I am trying to read in numbers from a text file for an NxN matrix and 1xN matrix using fscanf. I know this question has been asked here before, but I have tried the solutions and simply cannot understand why my method does not work. The NxN matrix is:

1 1 1
3 1 0
-1 0 1

and the 1xN matrix is:

6 
11 
-2

The numbers in the rows are separated by one space and the columns are separated by \n. This is my code:

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

int countlines(FILE *f);
void reduce_mat(double **matrix, double *vector, int row, int column);
void swapping(double **matrix, double *vector, int row, int column);
int main()
{
  FILE *f1=fopen("matrix.txt","r");
  FILE *f2=fopen("vector.txt","r");
  int dim_matrix=countlines(f1);
  int dim_vector=countlines(f2);

  //allocate memory for matrix and vector
  double **Mat_A=(double **) malloc(dim_matrix*sizeof(double));
  for(int j=0; j<dim_matrix; j++)
    Mat_A[j]=(double *) malloc(dim_matrix*sizeof(double));

  double *Vec_B=(double *) malloc(dim_vector*sizeof(double));

  //read in numbers from file
  for(int i=0; i<dim_matrix; i++)
  for(int j=0; j<dim_matrix; j++)
  {
    fscanf(f1,"%lf",&Mat_A[i][j]);
    printf("Mat_A[%d][%d]=%lf\n",i,j,Mat_A[i][j]);
  }
  for(int k=0; k<dim_vector; k++)
  {
    fscanf(f2, "%lf", &Vec_B[k]);
    printf("Vec_B[%d]=%lf\n",k,Vec_B[k]);
  }

 int countlines(FILE *f)
 {
 //check if file exists
  if (f==NULL)
  {
    printf("File does not exist");
    return 0;
  }
  int count=0; //intialize the count
  char c; //place to store characters from file
  for (c=getc(f); c!=EOF; c=getc(f))
  {
    if (c=='\n')
    {
      count+=1;
    }
  }
  return count;
 }

And it just prints out zeroes for every value. I have tried to use "%lf%[\n]%", "%lf%", etc. I simply can't figure out where I am going wrong, as this implementation seems to work for other people.

Hannah
  • 165
  • 2
  • 3
  • 13
  • 2
    check the return value of `fopen` and `malloc`. – user2736738 Nov 10 '17 at 05:29
  • 2
    `double **Mat_A=(double **) malloc(dim_matrix*sizeof(double));` may be a wrong size allocation. Use `double **Mat_A= malloc(sizeof *Mat_A * dim_matrix);` to allocate the correct size. – chux - Reinstate Monica Nov 10 '17 at 05:32
  • 1
    And check the return value of `fscanf`. Also this is semantically wrong even though it might work: `double **Mat_A=(double **) malloc(dim_matrix*sizeof(double));`. You want `sizeof(double *)` – MFisherKDX Nov 10 '17 at 05:33
  • Is this also wrong? `for(int j=0; j – Hannah Nov 10 '17 at 05:36
  • 1
    Don't cast the return value of `malloc` – user2736738 Nov 10 '17 at 05:36
  • @coderredoc I'm sorry, I don't understand what you mean. – Hannah Nov 10 '17 at 05:37
  • `Mat_A[j]= malloc(dim_matrix*sizeof(double));` – user2736738 Nov 10 '17 at 05:39
  • Ok, I'm sorry, but I'm very confused. I used malloc exactly the way my professor told me to and I don't have any deeper understanding here. If I take away the for loop over j and use just `double **Mat_A= malloc(sizeof *Mat_A * dim_matrix);` I get a segmentation fault. – Hannah Nov 10 '17 at 05:44
  • 1
    Yeah, you had it right. You have to do the allocation "inside your for loop over j" in order to allocate memory for each of your arrays. But your professor is wrong about casting the return value of malloc. It is not necessary in C. https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – MFisherKDX Nov 10 '17 at 05:51
  • @MFisherKDX i really don't know how to write the inside of the loop then. I believe all of you it's just that my implementation as written seems to have worked for other members of the course and I don't understand what is happening with mine. – Hannah Nov 10 '17 at 05:55
  • 1
    the [mcve]! What is the definition of `countlines`?! Does it rewind the file pointer? – Antti Haapala -- Слава Україні Nov 10 '17 at 05:59
  • @AnttiHaapala it counts how many lines are in the files, hence, giving you the dimensions of the matrices. In this case, it returns 3. – Hannah Nov 10 '17 at 06:01
  • 1
    @Hannah that much I had guessed. What we need is the **definition**, meaning **its code**, in the question itself. The definition is the piece of code from `int countlines(FILE *f) {` up to the closing `}`. A comment describing vaguely its behaviour is not the function definition. Your question is *unanswerable* without its definition. If the function reads all of the file without seeking to the beginning, then there is nothing for the `fscanf`s to read, right? – Antti Haapala -- Слава Україні Nov 10 '17 at 06:05
  • @AnttiHaapala I will edit it and add the definition – Hannah Nov 10 '17 at 06:08
  • As @AnttiHaapala surmised your problem is that `countlines` is consuming the entire stream and there is nothing left for `fscanf` to read. If you check your `fscanf` return value you would have seen this. Also change `char c;` to `int c;` in `countlines`. `fgetc` returns a char promoted to int *precisely* so it can return EOF. You can't compare a char against EOF. – MFisherKDX Nov 10 '17 at 06:20

1 Answers1

2

Counting lines reads the file and consumes the data. You must rewind it to the beginning to read it again in order to read values. So just add a rewind(f) at the end of the countlinesfunction.

 int countlines(FILE *f)   
 {
     //check if file exists
     if (f==NULL)
     {
         printf("File does not exist");
         return 0;
     }
     int count=0; //intialize the count
     int c; //place to store characters from file
     for (c=fgetc(f); c!=EOF; c=fgetc(f))
     {
         if ((char)c=='\n')
             count++;
     }
     rewind(f); // file is now ready to be read again  
     return count;
 }
Joël Hecht
  • 1,766
  • 1
  • 17
  • 18