initialization of arrays while operating with mallocs - arrays

Given the following piece of code, I don't understand why do we have to initialize every single row of the matrix when we have already created enough space in the stack.
#include <stdio.h>
#include <stdlib.h>
main() {
int **w;
int i, j;
int m, n;
printf("Number of rows in the matrix: ");
scanf("%d", &m);
printf("Number of columns in the matrix: ");
scanf("%d", &n);
w = (int **)malloc(m * n * sizeof(int));
for (i = 0; i < m; i++)
w[i] = (int *)malloc(n * sizeof(int));
for (i = 0; i < m; i++)
for (j = 0; j < n; j++) {
printf("Element [%d][%d]: ", i + 1, j + 1);
scanf("%d", &w[i][j]);
}
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("Element [%d][%d]: %d\n", i + 1, j + 1, w[i][j]);
}

There are many issues in your code:
space is not allocated on the stack, but from the heap.
in both cases, memory allocated for the objects is uninitialized, which means it is not initialized to anything in particular and can have any value whatsoever. Relying on any particular contents is undefined behavior.
the matrix dimensions and all the matrix elements are read from standard input with scanf(). Yet you do not check for scanf() failure to convert integers from the characters read from stdin, so any invalid or missing input is going to cause undefined behavior at some point in the program.
your matrix is actually structured as an array of pointers to arrays of int, which is fine, but inconsistent with the size arguments used to allocate the first array: w = (int **)malloc(m * n * sizeof(int)); should be
w = malloc(m * sizeof(*w));
you could easily get objects pre-initialized to 0 by using calloc() instead of malloc():
for (i = 0; i < m; i++)
w[i] = calloc(n, sizeof(int));
you should also check for malloc() failure and exit with an appropriate diagnostic message.
main() is an obsolete prototype for the main function. You should either use int main(), int main(void) or int main(int argc, char *argv[])...
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int get_int(void) {
int n;
if (scanf("%d", &n) != 1) {
printf("invalid input\n");
exit(EXIT_FAILURE);
}
return n;
}
void xalloc(size_t size) {
void *p = calloc(size, 1);
if (p == NULL) {
printf("out of memory for %zu bytes\n", size);
exit(EXIT_FAILURE);
}
return p;
}
int main() {
int **w;
int i, j;
int m, n;
printf("Number of rows in the matrix: ");
m = get_int();
printf("Number of columns in the matrix: ");
n = get_int();
w = xalloc(m * sizeof(*w));
for (i = 0; i < m; i++) {
w[i] = xalloc(n * sizeof(int));
}
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
printf("Element [%d][%d]: ", i + 1, j + 1);
w[i][j] = get_int();
}
}
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
printf("Element [%d][%d]: %d\n", i + 1, j + 1, w[i][j]);
}
}
for (i = 0; i < m; i++) {
free(w[i]);
}
free(w);
return 0;
}

Related

How to use a pointer (to a Matrix) as an argument in a Function in C?

I'm trying to write a code in C that sum two 4x4 matrix.
But I want my function to have a pointer as my arguments. The only error I'm getting is the time I'm trying to sum up in the function. Could someone help me?
#include <stdio.h>
#include <locale.h>
int i = 0, j = 0;
void calc_soma(int* mat_A, int* mat_B, int* mat_C)
{
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
mat_C[i][j] = mat_A[i][j] + mat_B[i][j];
printf("%d", mat_C[i][j]);
}
}
}
int main()
{
setlocale(LC_ALL, "Portuguese");
int i=0, j=0;
int mA[4][4], mB[4][4], mC[4][4];
int *mat_A, *mat_B, *mat_C;
for(i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
printf("Type in the value for Matrix A [%d][%d]: ", i, j);
scanf_s("%d", &mA[i][j]);
}
}
i, j = 0;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
printf("Type in the value for Matrix B [%d][%d]: ", i, j);
scanf_s("%d", &mB[i][j]);
}
}
*mat_A = &mA;
*mat_B = &mB;
return 0;
}
The types of pointers for the arguments are wrong. You want to pass (the pointer to the first elements of) arrays like int mA[4][4];, so they should be pointers to int[4].
void calc_soma(int (*mat_A)[4], int (*mat_B)[4], int (*mat_C)[4])
{
/* same as original */
}
They can simply be written like this:
void calc_soma(int mat_A[][4], int mat_B[][4], int mat_C[][4])
{
/* same as original */
}
Then the function can be called like:
calc_soma(mA, mB, mC);
The purpose of mat_A and mat_B are unclear, but if you want to get pointers to the matrice like &mA, it should be int(*)[4][4]. Note that dereferencing (like *mat_A) uninitialized pointers will invoke undefined behavior.
int main()
{
setlocale(LC_ALL, "Portuguese");
int i=0, j=0;
int mA[4][4], mB[4][4], mC[4][4];
int (*mat_A)[4][4], (*mat_B)[4][4], (*mat_C)[4][4];
/* omit */
mat_A = &mA;
mat_B = &mB;
return 0;
}
To use functions like
void calc_soma(int* mat_A, int* mat_B, int* mat_C)
you should express the matrice by 1D array to match with the format. It will be like this:
#include <stdio.h>
#include <locale.h>
#define ROWS 4
#define COLS 4
int i = 0, j = 0;
void calc_soma(int* mat_A, int* mat_B, int* mat_C)
{
for (i = 0; i < ROWS; i++)
{
for (j = 0; j < COLS; j++)
{
mat_C[i * COLS + j] = mat_A[i * COLS + j] + mat_B[i * COLS + j];
printf("%d", mat_C[i * COLS + j]);
}
}
}
int main()
{
setlocale(LC_ALL, "Portuguese");
int i=0, j=0;
int mA[ROWS * COLS], mB[ROWS * COLS], mC[ROWS * COLS];
for(i = 0; i < ROWS; i++)
{
for (j = 0; j < COLS; j++)
{
printf("Type in the value for Matrix A [%d][%d]: ", i, j);
scanf_s("%d", &mA[i * COLS + j]);
}
}
i, j = 0;
for (i = 0; i < ROWS; i++)
{
for (j = 0; j < COLS; j++)
{
printf("Type in the value for Matrix B [%d][%d]: ", i, j);
scanf_s("%d", &mB[i * COLS + j]);
}
}
calc_soma(mA, mB, mC);
return 0;
}

Error in a C program using dynamic memory allocation and array

Programming in C for finding maximum in 2D array using dynamic memory allocation.
int main() {
int i, arr[m][n], j, m, n;
int max = 0;
int *ptr;
printf("enter the value m");
scanf("%d", m);
printf("enter the vaue of n");
scanf("%d", n);
ptr = (int*) malloc(m * n * 4);
printf("enter the values\n");
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
scanf("%d", ((ptr + i * n) + j));
}
}
max = arr[0][0];
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
if (max < *((ptr + i * n) + j));
max = *((ptr + i * n) + j);
}
}
printf("%d", max);
}
I made changes to your code to remove the error you are getting. I commented the changes that I have made.
int main()
{
/*int i, arr[][], j, m, n;*/
/* Because arr is allocated dynamically, you have to declare as a pointer to int. */
int i, *arr, j, m, n;
int max = 0;
int *ptr;
printf("enter the value m");
scanf("%d", m);
printf("enter the vaue of n");
scanf("%d", n);
/*ptr = (int*)malloc(m * n * 4);*/
/* It is better to use sizeof(int) because int does not have the same length of all computers. */
ptr = (int*)malloc(m * n * sizeof(int));
printf("enter the values\n");
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
scanf("%d", ((ptr + i * n) + j));
}
}
/*max = arr[0];*/
/* To get the first int at arr, you could also use arr[0], but not arr[0][0] because */
/* this would require that arr be an array of pointers to array of int's, which is not the case. */
max = *arr;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
if (max < *((ptr + i * n) + j));
max = *((ptr + i * n) + j);
}
}
printf("%d", max);
}
You must learn the algorithms and programming language C.
So you can find some courses in this site :
learn-c
try this code is functioned:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[]) {
int i, j, m, n;
int max;
int **ptr;
printf("enter the value m: ");
scanf("%d", &m);
printf("enter the vaue of n: ");
scanf("%d", &n);
ptr = (int **)malloc(n * sizeof(int *));
for (i = 0; i < m; i++) {
*(ptr + i) = (int *)malloc(m * sizeof(int));
for (j = 0; j < n; j++) {
scanf("%d", (*(ptr + i) + j));
}
}
max = **ptr;
printf("\n\nMatrix:\n");
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
printf("%d ", *(*(ptr + i) + j));
if (max < *(*(ptr + i) + j))
max = *(*(ptr + i) + j);
}
printf("\n");
}
printf("\nthe max is %d \n", max);
return 0;
}

Dynamic matrix inside struct, C programming

I need help. I want to learn how to create and use dynamic matrix which is element of structure, I want to fill matrix with zeros (0) and print it out, I tried many ways but no luck. Here is the code
#include <stdio.h>
#include <stdlib.h>
typedef struct matrica
{
int **mat;
int dim; //this is dimension of squared matrix
}MATRICA;
void form_matrix(MATRICA *matrica);
int main()
{
MATRICA matrix;
form_matrix(&matrix);
return 0;
}
void form_matrix(MATRICA *matrica)
{
int i, j;
MATRICA *br;
do
{
printf("Size of matrix ");
scanf("%d", &br->dim);
}while(br->dim < 4 || br->dim > 6);
matrica->mat = (int **) calloc(br->dim, sizeof(int *));
for(i = 0; i < br->dim; i++)
{
matrica->mat[i] = (int *) calloc(br->dim, sizeof(int));
for(j = 0; j < br->dim; j++)
{
matrica->mat[i][j] = 0;
}
}
for(i = 0; i < br->dim; i++)
for(j = 0; j < br->dim; j++)
printf("%d ", matrica->mat[i][j]);
}
what am I doing wrong, my loop inside function goes only once, can someone explain to me why?
Your program exhibits undefined behavior because you are dereferencing an uninitialized pointer br. You don't need it, you simply need a variable to store your dimension input.
int i, j, dim;
do
{
printf("Size of matrix ");
if (scanf("%d", &dim) != 1) {
printf("scan failed\n");
exit(EXIT_FAILURE);
}
}while(dim < 4 || dim > 6);
matrica->dim = dim;
/* ... replace all instances of br->dim with dim */

Code doesn't read input file correctly

My code doesn't seem to be able to read the input file correctly. It somehow only reads the first line of my matrix and then it inputs the second line under "right hand side" instead of making another line for the matrix under "coefficient matrix". Additionally, it prints the third line under "Initial Guesses" rather than the third line of the matrix.
I'm assuming the error is somewhere in the code that I have posted below but let me know if you believe the code below is correct and somewhere else in my code is where this problem is originating from.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define MAX_DIM 100
#define MAX_ITER 500
#define TOLERANCE 1.e-6
void gauss_seidel(double **a, double *b, double *x, int n);
void print_screen_A_b_x(double **a, double *b, double *x, int n);
void main()
{
int i, j, *ptr, n;
int violation_counter, answer;
int violation_rows[MAX_DIM];
double sum;
double **a;
double *b, *x;
FILE *input_Ptr; //pointer to input file
//Open the input file
input_Ptr = fopen ( "my_input.txt", "r" );
if (input_Ptr == NULL) {
puts("\nInput file was not opened succesfully.\n");
exit(-1);
}
//read size of the problem
fscanf(input_Ptr, "%d", &n);
//dynamic memory allocation
a = (double **) malloc (n * sizeof(double *));
for (i = 0; i < n; i++) {
a[i] = (double *) malloc (n * sizeof(double));
}
b = (double *) malloc (n * sizeof(double));
x = (double *) malloc (n * sizeof(double));
/* read in data */
//n = MAX_DIM + 1;
//while (n > MAX_DIM) {
//fscanf(input_Ptr, "%d", &n);
//}
printf("\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
fscanf(input_Ptr, "%lf", &a[i][j]);
}
for (i = 0; i < n; i++) {
fscanf(input_Ptr, "%lf", &b[i]);
}
for (i = 0; i < n; i++) {
fscanf(input_Ptr, "%lf", &x[i]);
}
printf("\n");
}
fclose(input_Ptr);
print_screen_A_b_x(a, b, x, n);
puts("Solution vector:");
for (i = 0; i < n; i++) {
printf("x[%d] = %10.5f \n", i, x[i]);
//free memory
for (i = 0; i < n; i++) {
free(a[i]);
}
free(a);
free(b);
free(x);
return 0;
}
/* test the convergence criterion */
violation_counter = 0;
for (i = 0; i < n; i++) {
sum = 0.0;
for (j = 0; j < n; j++)
if (i != j)
sum = sum + fabs(a[i][j]);
if (fabs(a[i][i]) < sum) {
violation_rows[violation_counter] = i;
violation_counter = violation_counter + 1;
}
if (a[i][i] == 0.0) {
printf("Found diagonal element equal to zero;
rearrange equations; exiting ...\n");
exit(0);
}
}
if (violation_counter > 0) {
printf("The Gauss-Seidel convergence criterion is violated in %d rows out of %d\n", violation_counter, n);
printf("Specifically, it was violated in rows:\n");
for (i = 0; i < violation_counter; i++)
printf("%d ", violation_rows[i]);
printf("\n");
printf("Enter 1 if you want to continue; any other number to abort : ");
scanf("%d", &answer);
if (answer != 1)
exit(1);
printf("Check results carefully\n\n");
}
/* initialize the solution vector -- initial guesses */
for (i = 0; i < n; i++) {
printf("Enter an initial guess for x[%d] of the solution vector : ", i);
scanf("%lf", &x[i]);
}
/* solve the system */
gauss_seidel(a, b, x, n);
/* output solution */
for (i = 0; i < n; i++)
printf("x[%d]=%f\n", i, x[i]);
printf("\n");
}
/* function to solve a system using Gauss-Seidel */
void gauss_seidel(double **a, double *b, double *x, int n)
{
double maxerror = 1.0e-7;
double iteration_error;
double e, sum, temp;
int i, j;
while (maxerror > 1.e-6) {
iteration_error = 0.0;
for (i = 0; i < n; i++) {
sum = 0.0;
for (j = 0; j < n; j++) {
if (i != j)
sum = sum + (a[i][j] * x[j]);
}
}
temp = (a[i][n] - sum) / a[i][i];
e = fabs((temp - x[i]) / x[i]);
x[i] = temp;
if (e > iteration_error)
iteration_error = e;
}
maxerror = iteration_error;
}
void print_screen_A_b_x(double **a, double *b, double *x, int n)
{
int i, j;
printf("\n Coefficient matrix:\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
printf("%10.2f", a[i][j]);
}
printf("\n");
}
printf("\n Right hand side vector:\n");
for (i = 0; i < n; i++) {
printf("%10.2f \n", b[i]);
}
printf("\n Initial guess:\n");
for (i = 0; i < n; i++) {
printf("%10.5f \n", x[i]);
}
return;
}
Add \r\n in your post loop if statement.
You show us:
void gauss_seidel(double a[][MAX_DIM], double b[], double x[], int n)
and:
void print_screen_A_b_x(double **a, double *b, double *x, int n)
You cannot pass the same object as the first argument to both functions; they are (radically) different types, even though you use double subscripts with both. Since you've not shown how the matrix is actually defined, there isn't anything more we can do to help you.
Your compiler should be shrieking at you about one (or both) calls. Heed your compiler. It knows more about C than you do at the moment. It won't object unless there's a serious problem. If by some mischance your compiler was not complaining, then you need to either turn on compilation warnings (and work with C11, or perhaps C99, as the version of the standard — definitely not C90) or get a better compiler.
Analysis of one update
One version of the updated code in the question has input code like this:
// read size of the problem
fscanf(input_Ptr, "%d", &n);
// dynamic memory allocation
a = (double **)malloc(n * sizeof(double *));
for (i = 0; i < n; i++)
{
a[i] = (double *)malloc(n * sizeof(double));
}
b = (double *)malloc(n * sizeof(double));
x = (double *)malloc(n * sizeof(double));
printf("\n");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
fscanf(input_Ptr, "%lf", &a[i][j]);
}
for (i = 0; i < n; i++)
{
fscanf(input_Ptr, "%lf", &b[i]);
}
for (i = 0; i < n; i++)
{
fscanf(input_Ptr, "%lf", &x[i]);
}
printf("\n");
}
The good news is that except for the absence of error checking, the memory allocation looks OK.
The bad news is that under most plausible inferences of what the data looks like, the main input loops are completely wrong. Assuming the value in n is N, the first iteration of the input loop reads N values into a[0] (which is fine), and then reads N values into b (which is fine as far as it goes), and then reads N values into x (which is also fine as far as it goes). The value of i is now n; when it is incremented by the outer loop, i is bigger than n, so the outer loop terminates, but you've only read one row of the main matrix.
Most likely, you should be using:
// read size of the problem
if (fscanf(input_Ptr, "%d", &n) != 1)
…report error and skedaddle…
// Check n for plausibility
if (n < 1 || n > 1000)
…report implausibility and skedaddle…
// dynamic memory allocation
…as before, except you should error check all the allocations…
printf("\n");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if (fscanf(input_Ptr, "%lf", &a[i][j]) != 1)
…report error and skedaddle…
}
}
for (i = 0; i < n; i++)
{
if (fscanf(input_Ptr, "%lf", &b[i]) != 1)
…report error and skedaddle…
}
for (i = 0; i < n; i++)
{
if (fscanf(input_Ptr, "%lf", &x[i]) != 1)
…report error and skedaddle…
}
The fact that you don't check for errors means you don't know when things go wrong. You can't afford not to know when things go wrong, so you can't afford not to check for errors.
skedaddle |skɪˈdad(ə)l|
verb [ no obj. ] informal —
depart quickly or hurriedly; run away.

While Performing 2D array representation in memory leads to Segmentation fault: 11

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;
}

Resources