0

I've been given a txt file with 5 lines. The first two lines are number values indicating the dimensions of a matrix, and the next 3 are the subsequent values in the matrix.

Ex:

3
4
0.0 1.0 2.0 3.0
10.1 11.1 12.1 13.1
200.2 210.2 220.2 230.2

So far, all I was trying to do was see if I could create a matrix by fscanf the first two lines and get the number of rows and columns like so:

/*Matrix reading*/
matrix_t mat_frd(char* fname){

    int r,c;
    r = 0;
    c = 0;
    matrix_t mfile;
    FILE * matrix_file;
    matrix_file = fopen(fname, "r");
    rewind(matrix_file);
    fscanf(matrix_file, "%d", r);
    printf("%d",r);
    printf("%d",c);
    mfile = mat_new[r][c];

    return mfile;

}

I was trying to just see if I could even print those two values if see if I got them, but I think I am scanning through the file wrong. The ultimate goal is to be able to create the matrix with the specifications in the file, and then use another method to print it, but I am still stuck here.

2
  • What went wrong when you tried? Was matrix_file NULL? Commented Sep 7, 2014 at 1:59
  • Code never reads c, so it remains with a value of 0. Commented Sep 7, 2014 at 3:05

4 Answers 4

1

You need to check the return values from fopen() and fscanf(). You don't need the rewind(); files opened for reading are opened at the start. You need to use &r to get the number of rows; you need to have a second fscanf() to read the number of columns (or you need to use one call to read both rows and columns). Which comes first, the number of rows or the number of columns? It wouldn't be a bad idea to check that the number of rows and number of columns are each at least 1. You need to close the file before you return from the function.

Since matrix_t is not a standard type, we can't comment usefully on that. The mfile = mat_new[r][c]; line is extremely dubious, though — I'd be surprised indeed if that is correct. (Using mfile = mat_new(r, c); would make some sense.)

Note that fscanf() won't care if all the values are on a single line, or if there are fifty blank lines between each number. If you really want to enforce lines as shown, you need to use fgets() and sscanf().

Sign up to request clarification or add additional context in comments.

1 Comment

answer is down below!
0
#include<stdio.h>
#include<stdlib.h>

typedef struct matrix {
    int rows;
    int cols;
    double **mat;
} matrix_t;
#define SCN_MAT "lf"
#define PRN_MAT "f"

matrix_t mat_new(int r, int c){
    matrix_t m = { r, c, NULL };
    m.mat = malloc(r*sizeof(*m.mat));
    for(int i=0;i<c;++i)
        m.mat[i] = calloc(c, sizeof(**m.mat));
    return m;
}

matrix_t mat_frd(char* fname){
   int r = 0, c = 0;
    matrix_t mfile;
    FILE * matrix_file = fopen(fname, "r");
    fscanf(matrix_file, "%d %d", &r, &c);
    mfile = mat_new(r, c);
    for(r = 0; r < mfile.rows; ++r)
        for(c = 0; c< mfile.cols; ++c)
            fscanf(matrix_file, "%" SCN_MAT, &mfile.mat[r][c]);
    fclose(matrix_file);

    return mfile;
}
int main(void){
    int r, c;
    matrix_t m = mat_frd("data.txt");
    for(r = 0; r < m.rows; ++r){
        for(c = 0; c < m.cols; ++c)
            printf("%5.1" PRN_MAT " ", m.mat[r][c]);
        printf("\n");
    }
    //mat_delete(m);
    return 0;
}

12 Comments

BluePixy - I'm getting a strange runtime error with your code: *** Error in ./bin/mstruct: corrupted double-linked list: 0x000000000124a240 *** which occurs following assignment of mfile.mat[2][3]: 230.200000. I'm still debugging - any ideas off the top of your head?
@DavidC.Rankin: You're likely misusing the allocated memory. Can you use valgrind? If so, use it. But it depends on the details of the matrix_t type, the details of which I don't see in the question. What Blue Pixy suggested looks good, but there are many things that could be going wrong. The code above doesn't error check anything; that can be dangerous.
Looks good hear as well, the only thought was the function scope definition of matrix_t mfile; in mat_frd(char* fname). I'll run valgrind, you can see if you get the same results. I just compiled with: gcc -Wall -Wextra -Wno-sign-compare -Wno-long-long -std=c99 -g and got no warning.
@JonathanLeffler valgrind gives: Invalid read of size 4 at 0x4E9B86D: __isoc99_fscanf (in /usr/lib/libc-2.19.so) by 0x4007A5: mat_frd (mtrx_struct1.c:24) by 0x400853: main (mtrx_struct1.c:35) Address 0x0 is not stack'd, malloc'd or (recently) free'd
Reading into the null pointer is not a good idea. So you need to look hard at the mat_frd() function and work out why it passes a null pointer to fscanf().
|
0

An alternative to statically allocating the matrix_t types in mat_new and mat_frd is to dynamically allocate memory for the structure in mat_new returning a pointer to mat_frd. Using the same logic provided in the original answer but dynamically allocating space yields the following:

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

typedef struct matrix {
    int rows;
    int cols;
    double **mat;
} matrix_t;
#define SCN_MAT "lf"
#define PRN_MAT "f"

matrix_t *mat_new(int r, int c){
    matrix_t *m = malloc (sizeof (struct matrix));
    m->rows = r;
    m->cols = c;
    m->mat = malloc(r*sizeof(*m->mat));
    for(int i=0;i<c;++i)
        m->mat[i] = calloc(c, sizeof(**m->mat));
    return m;
}

matrix_t *mat_frd(char* fname){
    int r = 0, c = 0;
    matrix_t *mfile = NULL;
    FILE * matrix_file = fopen(fname, "r");
    fscanf(matrix_file, "%d %d", &r, &c);
    mfile = mat_new(r, c);
    for(r = 0; r < mfile->rows; ++r)
        for(c = 0; c< mfile->cols; ++c)
            fscanf(matrix_file, "%" SCN_MAT, &mfile->mat[r][c]);

    fclose(matrix_file);

    return mfile;
}

int main(void){
    int r, c;
    matrix_t *m = mat_frd("dat/mdata.txt");
    if (!m) {
        fprintf (stderr,"\n  mat_frd() returned NULL, read failed\n\n");
        return 1;
    }

    for(r = 0; r < m->rows; ++r){
        for(c = 0; c < m->cols; ++c)
            printf("%5.1" PRN_MAT " ", m->mat[r][c]);
        printf("\n");
    }

    //mat_delete(m);
    return 0;
}

output:

$ ./bin/mstruct
  0.0   1.0   2.0   3.0
 10.1  11.1  12.1  13.1
200.2 210.2 220.2 230.2

Comments

0

Sorry I haven't been able to post the answer sooner.

Here is the end result:

/Matrix reading/

matrix_t mat_frd(char* fname){

int r, c;
int i, j;
FILE * matrix_file;

matrix_file = fopen(fname, "r");

fscanf(matrix_file, "%d", &r);
fscanf(matrix_file, "%d", &c);

//create new matrix
matrix_t mfile = mat_new(r,c);

for(i = 0; i < r; i++){
    for (j = 0; j < c; j++){
        fscanf(matrix_file,"%lf", &mfile->mat[i][j]);
    }
}
fclose(matrix_file);
return mfile;
}

I was able to get this to work by calling the file name in the main method like so:

char* fname = "sample_matrix.txt";
matrix9 = mat_frd(fname);

sample_matrix.txt - being the txt file in my program matrix9 - random matrix I created to test it

I essentially first achieved the two numbers in the first two lines of the text file, which gave me the dimensions of the matrix (first number - rows, second number - columns). I then created the matrix with those parameters, and created the for loops that would call fscanf for every space in the matrix (able to do this bc everything else in the file was a double). My output after using this code is as follows (you would have to create a print statement for this, but with mine:

MATRIX: after file-read Type: 13 , Dims 3, 4

0.000 1.000 2.000 3.000
10.100 11.100 12.100 13.100
200.200 210.200 220.200 230.200

Hope this helps everyone and thanks for all the advice!

1 Comment

What was the print statement you used? If you showed your entire main() it would complete your answer for me. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.