Home > Software design >  How to transpose a matrix and return pointer?
How to transpose a matrix and return pointer?

Time:12-19

I have to do this exercise: given a matrix, write a function to transpose that matrix. It has to return a pointer to that matrix.

These are key points: (1) Write a matrix constructor function.

(2) Create the function with the help of the matrix constructor.

(3) Transpose the matrix.

(4) Print the matrix.

(5) Free the allocated memory.

(6) Close the file.

(For the moment, let's ignore steps 4, 5 and 6)

(1), and (2) the matrix constructor function is pretty simple, because it takes 3 parameters: "pointer to matrix", "rows" and "columns". Here's my code:

void matrix_constructor(struct matrix* mat, size_t rows, size_t cols) {
    mat->rows = rows; mat->cols = cols; 
    mat->data = calloc(rows * cols, sizeof(double)); 
}

it works.

(3) (This is the critical point). Here's my code:

struct matrix* mat_transpose(const struct matrix* mat) {
    struct matrix* out;

The error is located here. It's a warning (green squiggle): the debugger warned me I'm using uninitialized memory. But I've initialized it in the next lines. Why do I have this warning? This warning stops me from running the program; this is strange because a warning could be ignored, right?

    out->rows = mat->cols; 
    out->cols = mat->rows; 
    out->data = mat->data; 
    for (size_t r = 0; r < out->rows;   r) {
        for (size_t c = 0; c < out->cols;   c) {
            out->data[r * out->cols   c] = mat->data[r * mat->rows   c]; 
        }
    }
    return out; 
}

.....

This is the reproducible example:

matrix.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h> 
#include <stdio.h>
struct matrix {
    size_t rows, cols;
    double* data;
};
extern struct matrix* mat_transpose(const struct matrix* mat);

matrix.c

#include "matrix.h"

struct matrix* mat_transpose(const struct matrix* mat) {
    struct matrix* out; 
    out->rows = mat->cols; 
    out->cols = mat->rows; 
    out->data = mat->data; 
    for (size_t r = 0; r < out->rows;   r) {
        for (size_t c = 0; c < out->cols;   c) {
            out->data[r * out->cols   c] = mat->data[r * mat->rows   c]; 
        }
    }
    return out; 
} 

.....

To sum up:

Why do I have this warning? Could you give me a detailed explanation about that?

EDIT: I've edited matrix_transpose function and it works. Here's the code:

struct matrix* mat_transpose(const struct matrix* mat) {
    struct matrix* out = calloc(mat->rows * mat->cols, sizeof(double));
    if (out == NULL) {
        return NULL; 
    }
    out->rows = mat->cols; 
    out->cols = mat->rows; 
    out->data = mat->data; 
    for (size_t r = 0; r < out->rows;   r) {
        for (size_t c = 0; c < out->cols;   c) {
            out->data[r * out->cols   c] = mat->data[r * mat->rows   c]; 
        }
    }
    return out; 
}

Now, the mat_fprint function:

void matrix_fprint(const struct matrix *m, FILE *f) {
    size_t rows = m->rows; 
    size_t cols = m->cols; 
    double* data = m->data; 

    for (size_t r = 0; r < rows;   r) {
        for (size_t c = 0; c < cols;   c) {
            double value = 0; 
            value = data[r * cols   c]; 
            fprintf(f, "%.4f", value); 
        }
    }
}

It doesn't have errors; but when I compile it, in the file I don't see anything (only one line of code, but it's not the entire matrix) I don't know why.

EDIT 2: I've added \t and \n and I got the same result

void matrix_fprint(const struct matrix *m, FILE *f) {
    size_t rows = m->rows; 
    size_t cols = m->cols; 
    double* data = m->data; 

    for (size_t r = 0; r < rows;   r) {
        for (size_t c = 0; c < cols;   c) {
            double value = 0; 
            value = data[r * cols   c]; 
            fprintf(f, "%.4f\t", value); 
        }
        fprintf(f, "\n"); 
        
    }
    
}

The output on file is the same.

3rd EDIT: This is hopefully, the final reproducible example.

// matrix.h 

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h> 
#include <stdio.h>
struct matrix {
    size_t rows, cols;
    double* data;
};
extern struct matrix* mat_transpose(const struct matrix* mat);

// matrix.c


#include "matrix.h"

void matrix_constructor(struct matrix* mat, size_t rows, size_t cols) {
    mat->rows = rows; mat->cols = cols;
    mat->data = calloc(rows * cols, sizeof(double));
}

struct matrix* mat_transpose(const struct matrix* mat) {
    // allocate the matrix structure
    struct matrix* out = calloc(sizeof(*out), 1);
    if (out == NULL) {
        return NULL;
    }
    // construct the transposed matrix with rows and cols arguments swapped
    matrix_constructor(out, mat->cols, mat->rows);
    if (out->data == NULL) {
        free(out);
        return NULL;
    }
    // set the transposed data
    for (size_t r = 0; r < mat->rows;   r) {
        for (size_t c = 0; c < mat->cols;   c) {
            out->data[c * out->rows   r] = mat->data[r * mat->rows   c];
        }
    }
    return out;
}

void matrix_fprint(const struct matrix *m, FILE *f) {
    size_t rows = m->rows; 
    size_t cols = m->cols; 
    double* data = m->data; 

    for (size_t r = 0; r < rows;   r) {
        for (size_t c = 0; c < cols;   c) {
            double value = 0; 
            value = data[r * cols   c]; 
            fprintf(f, "%.4f\t", value); 
        }
        fprintf(f, "\n"); 
        
    }
    
}



void matrix_destructor(struct matrix* mat) {
    free(mat->data); 
}



int main(void) {
    struct matrix A; 
    matrix_constructor(&A, 2, 3); 
    A.data[0] = 4.5678; A.data[1] = 78.9876; A.data[2] = 67.9876; 
    A.data[3] = 4.7896; A.data[4] = 2.6789; A.data[5] = 1.1122;
    
    mat_transpose(&A); 
    FILE* f = fopen("matrix transpose.txt", "w"); 
    matrix_fprint(&A, f); 

    matrix_destructor(&A); 
    fclose(f); 
    return 0; 
} 

The problem is that when I compile the code, I read in the file the original matrix (matrix A), and not the transpose matrix.

Hypothesis: this could happen because when matrix_transpose returns the value, it's not assigned to any struct variable.

But when I try to create, for example, struct matrix B it doesn't work as well. Why?

CodePudding user response:

struct matrix* out; 

This does not initialize a matrix, it initializes a pointer to a matrix. Since the pointer hasn't been initialized, it currently points to some arbitrary address in memory. (Which is probably memory that you don't own!)

That is why the compiler is giving you a warning; you are (probably) editing memory that you don't own!

If you want to allocate space for a matrix, you can use malloc from #include <stdlib.h>.

CodePudding user response:

You need to allocate both the matrix structure and the matrix data. You can use matrix_constructor for that:

struct matrix *mat_transpose(const struct matrix *mat) {
    // allocate the matrix structure
    struct matrix *out = calloc(sizeof(*out), 1);
    if (out == NULL) {
        return NULL; 
    }
    // construct the transposed matrix with rows and cols arguments swapped
    matrix_constructor(out, mat->cols, mat->rows);
    if (out->data == NULL) {
        free(out);
        return NULL;
    }
    // set the transposed data
    for (size_t r = 0; r < mat->rows;   r) {
        for (size_t c = 0; c < mat->cols;   c) {
            out->data[c * out->rows   r] = mat->data[r * mat->rows   c]; 
        }
    }
    return out; 
}

CodePudding user response:

  1. create the function with the help of the matrix constructor

You probably mean "create the MATRIX with help of the matrix constructor FUNCTION".


given a matrix, write a function to transpose that matrix. It has to return a pointer to that matrix.

This is badly formulated and unclear. Is there a second matrix or not?

  • Related