0
votes

void read_matrices(int **A, int **B, int **C, int *m, int *n, int *p, char *file)

I want to read in two matrices from an external file that reads like this:

 3 
 2 
 4 
 1 2 
 3 4 
 5 6 
 7 8 9 10 
 11 12 13 14

Where the first line is the number is the number of rows for Matrix A, number 2 is the number of columns for Matrix A and number of rows for Matrix B, and the third number is the number of columns for matrix B. I've tried this to get the m, n, and p but get a seg fault

FILE * fp = fopen(file, "r");
char a, b, d;
char c = getc(fp);
int i = 0;
while (c != EOF) {
    if (i == 0) {
        a = c;
        i++;
    }
    else if (i == 1) {
        b = c;
        i++;
    }
    else if (i == 2) {
        d = c;
        i++;
    }
    else
        break;
}
fclose(fp);
2
Where does this code try to get m, n and p?SleuthEye
Well for starters you only try to get one char. There is no getc or fgetc inside the while loop...might want to rewrite the while statement to something like while ( (c = fgetc(fp)) != EOF ). As far as the seg fault, I'm assuming it happens somewhere in this code or is it in parts that you haven't posted? Have you tried to run gdb and see where it fails?James H
If you're reading just two arrays, why does the function take three int ** parameters? What layout are you planning to use for the arrays? Are they going to be 2D arrays or 1D arrays that you index appropriately? (It matters because if they're to be 2D arrays, you need int *** parameters, most probably.)Jonathan Leffler
Passing unused parameters should have been caught by the compiler. Are you passing the necessary flags to the compiler to show all warnings, etc?user3629249

2 Answers

0
votes

It is obvious you need a bit of help. Here is an example that is only 1 way of many to do this. Note: instead of complicating the example reading a variable number of elements in B, it is simply coded to read 4 elements as they exist in the data file. Also, fscanf is used to read from the file since you have a variable number and differing data to read in each line. This simplifies the code compared to reading the file character by character since the type of information read is int. Read through the example (comments inline) and let me know if you have questions:

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

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

    int *A, *B, *C, m, n, p;  /* note *C is unused */
    char *file;

    /* test for required filename */
    if (argc < 2) {
        fprintf (stderr, "\n Error: insufficient input. usage: %s filename\n\n", argv[0]);
        return 1;
    }

    /* assign filename, open file, validate opening */
    file = argv[1];  /* you don't need 'file', you can simply use argv[1] */

    FILE *fp = fopen (file, "r");
    if (!fp) {
        fprintf (stderr, "\n Error: file open failed for file '%s'\n\n", argv[0]);
        return 1;
    }

    /* read & output m, n, p */
    fscanf (fp, "%d\n%d\n%d\n", &m, &n, &p);
    printf ("\n m: %d\n n: %d\n p: %d\n\n", m, n, p);

    /* allocate memory for A and set values to null */
    A = calloc (m * 2, sizeof(int));

    /* read A */
    int i = 0;
    for (i = 0; i < m; i++)
        fscanf (fp, "%d %d\n", &A [i*2], &A[i*2 + 1]);

    /* output A */
    printf ("Array A\n");
    for (i = 0; i < m; i++)
        printf (" [ %d  %d ]\n", A [i*2], A[i*2 + 1]);

    /* allocate memory for B and set values null */
    B = calloc (n * p, sizeof(int));

    /* read B */
    for (i = 0; i < n; i++)
        fscanf (fp, "%d %d %d %d\n", &B [i*p], &B[i*p + 1], &B[i*p + 2], &B[i*p + 3]);

    /* output B */
    printf ("\nArray B\n");
    for (i = 0; i < n; i++)
        printf (" [ %2d %2d %2d %2d ]\n", B [i*p], B[i*p + 1], B[i*p + 2], B[i*p + 3]);

    printf ("\n");

    /* close FP & free allocated memory */
    fclose (fp);
    if (A) free (A);
    if (B) free (B);

    return 0;
}

output:

$ ./bin/rmf dat/array.dat

m: 3
n: 2
p: 4

Array A
 [ 1  2 ]
 [ 3  4 ]
 [ 5  6 ]

Array B
 [  7  8  9 10 ]
 [ 11 12 13 14 ]
0
votes
for the bit of code you provided, 
which fails to set the m, n, p variables 
and fails to read/set the contents of the matrices A, B
and fails to read/set the contents of matrix C.

It is also very dangerous to pass parameters pointing to predefined matrix sizes
as there is no guarantee that the size values read from the file
will fit into the pre-allocated areas.

Much better to only pass a pointer to each matrix pointer,
then malloc the matrix sizing after the actual values are read
and set the passed matrix pointer A,B,C to point to the malloc'd areas
and read the matrix data into the malloc'd areas.


void read_matrices(int **A, int **B, int **C, int *m, int *n, int *p, char *file)
{
    FILE * fp = fopen(file, "r");
    if( NULL == fp ) // then handle fopen() error
    else
    {
        int aRows = getc(fp);
        int aCols = getc(fp);
        int bRows = aCols;
        int bCols = getc(fp);

        // need to add code to read the A, B matrix contents
        // need to add code to read the C matrix contents
        // need to add code to set m,n,p 

        fclose(fp);
    }
}