I have a task where I'm supposed to multiply two quadratic matrices of size n in C, using pointers as function parameters and return value. This is the given function head: int** multiply(int** a, int** b, int n). Normally, I would use three arrays (the two matrices and the result) as parameters, but since I had to do it this way, this is what I came up with:
#include <stdio.h>
#include <stdlib.h>
int** multiply(int** a, int** b, int n) {
int **c = malloc(sizeof(int) * n * n);
// Rows of c
for (int i = 0; i < n; i++) {
// Columns of c
for (int j = 0; j < n; j++) {
// c[i][j] = Row of a * Column of b
for (int k = 0; i < n; k++) {
*(*(c + i) + j) += *(*(a + i) + k) * *(*(b + k) + j);
}
}
}
return c;
}
int main() {
int **a = malloc(sizeof(int) * 2 * 2);
int **b = malloc(sizeof(int) * 2 * 2);
for (int i = 0; i < 2; i++) {
for (int j = 0; i < 2; j++) {
*(*(a + i) + j) = i - j;
*(*(b + i) + j) = j - i;
}
}
int **c = multiply(a, b, 2);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
printf("c[%d][%d] = %d\n", i, j, c[i][j]);
}
}
free(a);
free(b);
free(c);
return 0;
}
I have not worked much with pointers before, and am generally new to C, so I have no idea why this doesn't work or what I'd have to do instead. The error I'm getting when trying to run this program is segmentation fault (core dumped). I don't even know exactly what that means... :(
Can someone please help me out?
There's lots of fundamental problems in the code. Most notably, int** is not a 2D array and cannot point at one.
i<2 typo in the for(int j... loop.
i < n in the for(int k... loop.
To allocate a 2D array you must do: int (*a)[2] = malloc(sizeof(int) * 2 * 2);. Or if you will malloc( sizeof(int[2][2]) ), same thing.
To access a 2D array you do a[i][j].
To pass a 2D array to a function you do void func (int n, int arr[n][n]);
Returning a 2D array from a function is trickier, easiest for now is just to use void* and get that working.
malloc doesn't initialize the allocated memory. If you want to do += on c you should use calloc instead, to set everything to zero.
Don't write an unreadable mess like *(*(c + i) + j). Write c[i][j].
I fixed these problems and got something that runs. You check if the algorithm is correct from there.
#include <stdio.h>
#include <stdlib.h>
void* multiply(int n, int a[n][n], int b[n][n]) {
int (*c)[n] = calloc(1, sizeof(int[n][n]));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
c[i][j] += a[i][k] * b[k][j];
}
}
}
return c;
}
int main() {
int (*a)[2] = malloc(sizeof(int[2][2]));
int (*b)[2] = malloc(sizeof(int[2][2]));
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
a[i][j] = i - j;
b[i][j] = j - i;
}
}
int (*c)[2] = multiply(2, a, b);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
printf("c[%d][%d] = %d\n", i, j, c[i][j]);
}
}
free(a);
free(b);
free(c);
return 0;
}
From the updated requirement, the actual function prototype is int *multiply(int *a, int *b, int n); so the code should use a "flattened" matrix representation consisting of a 1-D array of length n * n.
Using a flattened representation, element (i, j) of the n * n matrix m is accessed as m[i * n + j] or equivalently using the unary * operator as *(m + i * n + j). (I think the array indexing operators are more readable.)
First, let us fix some errors in the for loop variables. In multiply:
for (int k = 0; i < n; k++) {
should be:
for (int k = 0; k < n; k++) {
In main:
for (int j = 0; i < 2; j++) {
should be:
for (int j = 0; j < 2; j++) {
The original code has a loop that sums the terms for each element of the resulting matrix c, but is missing the initialization of the element to 0 before the summation.
Corrected code, using the updated prototype with flattened matrix representation:
#include <stdio.h>
#include <stdlib.h>
int* multiply(int* a, int* b, int n) {
int *c = malloc(sizeof(int) * n * n);
// Rows of c
for (int i = 0; i < n; i++) {
// Columns of c
for (int j = 0; j < n; j++) {
// c[i][j] = Row of a * Column of b
c[i * n + j] = 0;
for (int k = 0; k < n; k++) {
c[i * n + j] += a[i * n + k] * b[k * n + j];
}
}
}
return c;
}
int main() {
int *a = malloc(sizeof(int) * 2 * 2);
int *b = malloc(sizeof(int) * 2 * 2);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
a[i * 2 + j] = i - j;
b[i * 2 + j] = j - i;
}
}
int *c = multiply(a, b, 2);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
printf("c[%d][%d] = %d\n", i, j, c[i * 2 + j]);
}
}
free(a);
free(b);
free(c);
return 0;
}
You need to fix multiple errors here:
1/ line 5/24/28: int **c = malloc(sizeof(int*) * n )
2/ line 15: k<n
3/ Remark: use a[i][j] instead of *(*(a+i)+j)
4/ line 34: j<2
5/ check how to create a 2d matrix using pointers.
#include <stdio.h>
#include <stdlib.h>
int** multiply(int** a, int** b, int n) {
int **c = malloc(sizeof(int*) * n );
for (int i=0;i<n;i++){
c[i]=malloc(sizeof(int) * n );
}
// Rows of c
for (int i = 0; i < n; i++) {
// Columns of c
for (int j = 0; j < n; j++) {
// c[i][j] = Row of a * Column of b
for (int k = 0; k < n; k++) {
c[i][j] += a[i][k] * b[k][j];
}
}
}
return c;
}
int main() {
int **a = malloc(sizeof(int*) * 2);
for (int i=0;i<2;i++){
a[i]=malloc(sizeof(int)*2);
}
int **b = malloc(sizeof(int) * 2);
for (int i=0;i<2;i++){
b[i]=malloc(sizeof(int)*2);
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
a[i][j] = i - j;
b[i][j] = i - j;
}
}
int **c = multiply(a, b, 2);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
printf("c[%d][%d] = %d\n", i, j, c[i][j]);
}
}
free(a);
free(b);
free(c);
return 0;
}
Related
I'm trying to solve Gaussian Elimination and Back Substitution in C.
But I've got Segmentation fault(Core dumped) error in shell.
this is the part of main code.
float **a = (float **) malloc(sizeof(float*) *n);
for (int i = 0; i < n; i++)
a[i] = (float*) malloc(sizeof(float) *n);
float *b = (float*) malloc(sizeof(float) *n);
float *x = (float*) malloc(sizeof(float) *n);
Gaussian(n, &a, &b);
BackSubstitution(n, &a, &b, &x);
and below is gaussian.c . I think there is some problem with gaussian.c
#include <math.h>
void Gaussian(int n, float ***arr, float **arr2)
{
for (int l = 0; l < n - 1; l++)
{
for (int i = l + 1, j = 1; i < n && j < n; i++, j++)
{ (*arr)[i][j] = (*arr)[i][j] - ((*arr)[i][l] / (*arr)[l][l]) * (*arr)[l][j];
(*arr2)[i] = (*arr2)[i] - ((*arr)[i][l] / (*arr)[l][l]) * (*arr2)[l];
}
}
}
void BackSubstitution(int n, float ***arr, float **arr2, float **result)
{
for (int i = n - 1; i > 0; i--)
{
(*result)[i] = (*arr2)[i] / (*arr)[i][i];
for (int j = 0; j < i; j++)
{ (*arr2)[j] = (*arr2)[j] - (*result)[i] * (*arr)[j][i];
(*arr)[j][i] = 0;
}
}
}
Is there something wrong that generate segmentation fault?
A few things:
You have no reason to pass your arrays by pointer reference. So your functions gets much easier by eliminating one extra reference:
void Gaussian(int n, float** arr, float* arr2) {
for (int l = 0; l < n - 1; l++) {
for (int i = l + 1, j = 1; i < n && j < n; i++, j++) {
arr[i][j] = arr[i][j] - arr[i][l] / arr[l][l] * arr[l][j];
arr2[i] = arr2[i] - arr[i][l] / arr[l][l] * arr2[l];
}
}
}
void BackSubstitution(int n, float** arr, float* arr2, float* result) {
for (int i = n - 1; i > 0; i--) {
result[i] = arr2[i] / arr[i][i];
for (int j = 0; j < i; j++) {
arr2[j] = arr2[j] - result[i] * arr[j][i];
arr[j][i] = 0;
}
}
}
Second, you aren't actually initializing the contents of your arrays with valid data. Some of your array initializations are missing initializations to actual floating point data. Without this, your arrays have garbage data - which won't play well with floating point.
So aside from initializing your arrays correctly, you don't have to pass them in by pointer (because arrays degrade to pointers in function calls)
int n = 10;
float** a = (float**)malloc(n * sizeof(float*));
for (int i = 0; i < n; i++)
{
a[i] = (float*)malloc(n * sizeof(float));
for (int j = 0; j < n; j++)
{
a[i][j] = 0.0f; // you initialize a[i][j] with your data
}
}
float* b = (float*)malloc(n * sizeof(float));
float* x = (float*)malloc(n * sizeof(float));
for (int i = 0; i < n; i++)
{
b[i] = 0.0f;
x[i] = 0.0f;
}
Gaussian(n, a, b);
BackSubstitution(n, a, b, x);
I'm trying to transpose and multiply some matrices, basically
I get 2 matrices, matrixA and matrixB the action to be performed is trace(transpose(matrixA)*matrixB).
I managed to get this working for nxn matrices but I can't get it to work with mxn where (n>m or m>n).
I've looked online for solutions but I can't implement theirs solution into mine.
I removed almost all the code to simplify reading, if you prefer the entire code I linked it here.
If you do want to run the entire code, to recreate the problem use the following commands:
zeroes matrixA 2 3
zeroes matrixB 2 3
set matrixA
1 2 3 4 5 6
set matrixB
6 5 4 3 2 1
frob matrixA matrixB
The above commands should return Sum 56 but instead I get Sum 18
int* matrixATransposed = (int*) malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
for (int i = 0; i < matrixARowLenght; i++)
{
for (int j = 0; j < matrixAColLenght; j++)
{
*(matrixATransposed + i * matrixAColLenght + j) = *(matrixA + j * matrixAColLenght + i);
}
}
// Multiply
int* mulRes = (int*)malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
for (int i = 0; i < matrixAColLenght; i++) {
for (int j = 0; j < matrixBColLenght; j++) {
*(mulRes + i * matrixARowLenght + j) = 0;
for (int k = 0; k < matrixARowLenght; k++)
*(mulRes + i * matrixAColLenght + j) += *(matrixATransposed + i * matrixAColLenght + k) * *(matrixB + k * matrixBColLenght + j);
}
}
// Sum the trace
int trace = 0;
for (int i = 0; i < matrixARowLenght; i++) {
for (int j = 0; j < matrixAColLenght; j++) {
if (i == j) {
trace += *(mulRes + i * matrixAColLenght + j);
}
}
}
printf_s("Sum: %d\n", trace);
Your array indices for calculating the transpose, multiplication, and the trace seem to be incorrect. I've corrected them in the following program:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
int matrixARowLenght = 2;
int matrixAColLenght = 3;
int matrixA[] = {1,2,3,4,5,6};
int matrixBRowLenght = 2;
int matrixBColLenght = 3;
int matrixB[] = {6,5,4,3,2,1};
// Transpose
int* matrixATransposed = (int *) malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
for (int i = 0; i < matrixAColLenght; i++) {
for (int j = 0; j < matrixARowLenght; j++) {
*(matrixATransposed + i * matrixARowLenght + j) = *(matrixA + j * matrixAColLenght + i);
}
}
// Multiply
int *mulRes = (int *) malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
for (int i = 0; i < matrixAColLenght; ++i) {
for (int j = 0; j < matrixAColLenght; ++j) {
*(mulRes + (i * matrixAColLenght) + j) = 0;
for (int k = 0; k < matrixARowLenght; ++k) {
*(mulRes + (i * matrixAColLenght) + j) += *(matrixATransposed + (i * matrixARowLenght) + k) * *(matrixB + (k * matrixAColLenght) + j);
}
}
}
free(matrixATransposed);
// Sum the trace
int trace = 0;
for (int i = 0; i < matrixAColLenght; i++) {
for (int j = 0; j < matrixAColLenght; j++) {
if (i == j) {
trace += *(mulRes + i * matrixAColLenght + j);
}
}
}
printf("Sum: %d\n", trace);
free(mulRes);
return 0;
}
The above program will output your expected value:
Sum: 56
** UPDATE **
As pointed by MFisherKDX, the above code will not work if the result matrix is not a square matrix. The following code fixes this issue:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
int matrixARowLenght = 2;
int matrixAColLenght = 3;
int matrixA[] = {1,2,3,4,5,6};
int matrixBRowLenght = 2;
int matrixBColLenght = 4;
int matrixB[] = {8,7,6,5,4,3,2,1};
// Transpose
int* matrixATransposed = (int *) malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
for (int i = 0; i < matrixAColLenght; i++) {
for (int j = 0; j < matrixARowLenght; j++) {
*(matrixATransposed + i * matrixARowLenght + j) = *(matrixA + j * matrixAColLenght + i);
}
}
// Multiply
int *mulRes = (int *) malloc(matrixAColLenght * matrixBColLenght * sizeof(int));
for (int i = 0; i < matrixAColLenght; ++i) {
for (int j = 0; j < matrixBColLenght; ++j) {
*(mulRes + (i * matrixBColLenght) + j) = 0;
for (int k = 0; k < matrixARowLenght; ++k) {
*(mulRes + (i * matrixBColLenght) + j) += *(matrixATransposed + (i * matrixARowLenght) + k) * *(matrixB + (k * matrixBColLenght) + j);
}
}
}
free(matrixATransposed);
// Sum the trace
int trace = 0;
for (int i = 0; i < matrixAColLenght; i++) {
for (int j = 0; j < matrixBColLenght; j++) {
if (i == j) {
trace += *(mulRes + i * matrixBColLenght + j);
}
}
}
printf("Sum: %d\n", trace);
free(mulRes);
return 0;
}
This code will output the following as expected:
Sum: 83
Can't increase rows in 2d array, but columns is ok.
#include <stdio.h>
#include <stdlib.h>
it is working:
void increasecolumn(int ** mas, int* n, int m){
for (int i = 0; i < m; i++){
int* tmp = realloc(mas[i], sizeof (*mas[i]) * ((*n) + 1));
if (tmp){
mas[i] = tmp;
}
}
(*n) = (*n) + 1;
}
but increasing rows failed
void increaserow(int ** mas, int n, int* m){
int ** tmp = realloc(mas, sizeof(*mas) * ((*m) + 1));
if (tmp){
mas = tmp;
for (int i = 0; i < 1; i++){
mas[(*m) + i] = malloc(sizeof(*mas[(*m) + i]) * n);
}
}
(*m) = (*m) + 1;
}
int main(int argc, char * argv[]) {
int n = 3; // columns
int m = 2; // rows
int** mas = malloc(m*sizeof(*mas));
for(int i = 0; i < m; i++){
mas[i] = malloc(n*sizeof(*(mas[i])));
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
mas[i][j] = 0;
printf("%d ", mas[i][j]);
}
printf("\n");
}
printf("\n");
increasecolumn(mas, &n, m);
for (int i = 0; i < m; i++){
mas[i][n-1] = 1;
}
increaserow(mas, n, &m); // problem is here
for (int j = 0; j < n; j++){
mas[m-1][j] = 0;
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
printf("%d ", mas[i][j]);
}
printf("\n");
}
system("pause");
return 0;
}
I use this answer Resizing 2D Arrays in C like an example, something wrong.
The GNU Project Debugger on Windows:
warning: FTH: (9152): * Fault tolerant heap shim applied to current process. This is usually due to previous crashes. *
0 0 0
0 0 0
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401821 in main (argc=1, argv=0x7f1990) at D:\III Курс! II СЕМЕСТР\МатМодДослОп\stud\Untitled2.c:47
47: mas[m-1][j] = 0;
I am trying to multiply a 1D matrix as a 2D matrix in C.
Here is one example of what result I get with a 2D loop:
(the + should be a * I miss typed)
So I get a matrix C with the values
{
{2,3},
{6,11}
};
Here is the code for the 2D array in C:
void multiply(int n, double ** a, double ** b, double ** c) {
int i, j, k;
for (i = 1; i < n; i++){
for (j = 1; j < n; j++){
for (k = 1; k < n; k++){
c[i][j] += a[i][k] * b[k][j];
}
}
}
}
Now, I am trying to do the same, but for a 1D matrix, like in the picture:
(the + should be a * I miss typed)
And here is the code for the 1D array:
void multiply(int n, double * a, double * b, double * c) {
int i, j, k;
for (i = 0; i < n*n; i++) {
for (j = 0; j < n*n; j++) {
for (k = 0; k < n*n; k++) {
c[i]+= a[j]*b[k];
}
}
}
}
After running it, I get the result {14400, 14400,14400,14400} instead of {2,3,6,11}
It looks like you just want to do matrix multiplication while working with one-D arrays instead of 2-d. Not sure why you'd want to do that but you could do something like this:
void multiply(int n, double *a, double *b, double *c) {
int i, j, k;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
for (k = 0; k < n; k++) {
c[i * n + j] += a[i * n + k] * b[k * n + j];
}
}
}
}
I've presented the codes below only while executing the first loop it works fine but as soon as i uncomment the second loop it starts to throw segmentation fault. My code is as below.
// Write a program to add two m*n matrices using pointer.
#include <stdio.h>
#define m 2
#define n 2
int main() {
int (*a)[n];
int (*b)[n], i, j; //, *(sum)[n], i, j;
printf("Enter first matrix:\n");
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
scanf("%d", *(a + i) + j);
}
}
printf("Enter second matrix:\n");
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
scanf("%d", *(b + i) + j);
}
}
// printf("The Sum of matrix is:\n");
// for (i = 0; i < m; i++) {
// for (j = 0; j < n; j++) {
// // *(*(sum + i) + j) = *(*(a + i) + j) + *(*(b + i) + j);
// // printf("\t%d", *(*(sum + i) + j));
// }
// printf("\n");
// }
}
You are not defining a and b as 2D arrays, but as uninitialized pointers to 2D arrays. passing addresses into these invokes undefined behavior. You must make these pointers point to an actual array, either static, automatic or allocated from the heap.
You can define 2D arrays this way:
int a[m][n], b[m][n];
If you are required to use pointers, you can allocate the 2D arrays with malloc:
int (*a)[n] = malloc(sizeof(*a) * m);
int (*b)[n] = malloc(sizeof(*b) * m);
In your program, it is more readable to use the [] syntax, even for pointers:
#include <stdio.h>
#include <stdlib.h>
#define m 2
#define n 2
int main(void) {
int (*a)[n] = malloc(sizeof(*a) * m);
int (*b)[n] = malloc(sizeof(*b) * m);
int (*sum)[n] = malloc(sizeof(*sum) * m);
printf("Enter first matrix:\n");
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &a[i][j]);
}
}
printf("Enter second matrix:\n");
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &b[i][j]);
}
}
printf("The Sum of matrices is:\n");
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
sum[i][j] = a[i][j] + b[i][j];
printf("\t%d", sum[i][j]);
}
printf("\n");
}
return 0;
}