C - Read matrix of unknown size from file - c

I have file that has 30 matrices and each matrix has unknown size of rows and columns(with a max size of 1000). For instance:
0 5 2
5 0 2
1 6 0
0 9 7 4
3 0 9 1
9 1 0 4
9 4 1 0
I need to read each matrix into a 2d array. What would be the most efficient way of doing this?
This is what I have so far:
int** mat=malloc(1000000*sizeof(int*));
for(i=0;i<1000000;++i)
mat[i]=malloc(4*sizeof(int));
while(!feof(file))
{
for(i=0;i<1000;i++)
{
for(j=0;j<1000;j++){
fscanf(file,"%d%*[^\n]%*c",&mat[i][j]);
printf("%d\n", mat[i][j]);
}
}
}

Well the most efficient way is definitely not that. First figure out how big an array you need, then allocate it.

Apparently some matrices are small, so there is no need to allocate the maximum size 1000x1000. One way is to put the matrix in a structure to make it easier to keep track of size:
struct s_matrix
{
int **matrix;
int N; //one side of the square matrix N x N
};
typedef struct s_matrix Matrix;
Then allocate and free the matrix
void allocate_matrix(Matrix *m, int N)
{
m->N = N;
m->matrix = (int**)malloc(N * sizeof(int*));
*m->matrix = (int*)malloc(N * N * sizeof(int));
for (int i = 0; i < N; i++)
m->matrix[i] = *m->matrix + i * N;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
m->matrix[i][j] = 0;
}
void free_matrix(Matrix *m)
{
if (!m) return;
if (!m->matrix) return;
free(*m->matrix);
free(m->matrix);
}
Now we can declare how many matrices we need. It looks like this number is fixed at 30, so I don't think we need dynamic allocation.
int main()
{
const int max_count = 30;
Matrix list[max_count];
for (int i = 0; i < max_count; i++)
list[i].matrix = NULL;
allocate_matrix(&list[0], 3);//allocate 3x3 matrix
allocate_matrix(&list[1], 1000);//1000x1000
allocate_matrix(&list[2], 4000);//4000x4000
int **m;
m = list[0].matrix;
m[0][0] = 0;
m[0][1] = 1;
m[0][2] = 2;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
printf("%02d %s", m[i][j], (j == 2) ? "\n" : "");
//...
for (int i = 0; i < max_count; i++)
free_matrix(&list[i]);
printf("hey it worked, or maybe it didn't, or it did but there is memory leak\n");
return 0;
}

Related

Slice variable length char array

I have a variable string, that I need to slice into smaller strings, the main string should be treated as a bidimensional array with a certain width and height MxM, and the smaller strings should be cut in blocks of NxN size. So for example, if I have the following string, char source[17] = "ABCDEFGHIJKLMNS0" and his bidimensional size is 4x4, and the size of the smaller blocks are 2x2, the smaller blocks should be ABEF, CDGH, IJMN, KLSO.
In other words, the string should be seeing as
ABCD
EFGH
IJKL
MNSO
and NxN should be cut from it, like:
AB
EF
Always with the constraint that these blocks should be linear arrays as the main string.
I have tried with 3 nested for, with the following code, but I didn't know how to calc the index of the main array in order to cut the blocks that way
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
char pixelsSource[17] = "ABCDEFGHIJKLMNS0";
char pixelsTarget[4][5];
int Y = 0;
int X = 0;
for (int block = 0; block < 4; block++)
{
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
pixelsTarget[block][(i * 2) + j] = pixelsSource[(i * 2) + j];
printf("[%d][%d] = [%d] \n", block, (i * 2) + j, (i * 2));
}
}
}
for (int block = 0; block < 4; block++)
{
printf("%s\n", pixelsTarget[block]);
}
}
I broke this down into a more piece-by-piece way and generalized it for M & N. Here's the code, with inline comments:
#include <stdio.h>
#define M 4
#define N 2
int main(void)
{
// source data is an M * M string(plus null terminator)
char pixelsSource[M * M + 1] = "ABCDEFGHIJKLMNSO";
// destination is an array of N*N strings; there are M*M/N*N of them
char pixelsTarget[(M*M)/(N*N)][N*N + 1];
// iterate over the source array; blockX and blockY are the coordinate of the top-left corner
// of the sub-block to be extracted
for (int blockX = 0; blockX < M; blockX += N)
{
for (int blockY = 0; blockY < M; blockY += N)
{
int dstWord = blockX/N + blockY;
// for each letter in the sub-block, copy that letter over to the destination array
for (int y = 0; y < N; y++)
{
for (int x = 0; x < N; x++)
{
int dstIndex = y*N + x;
int srcIndex = (blockY + y)*M + blockX + x;
printf("[%d][%d] = [%d]\n", dstWord, dstIndex, srcIndex);
pixelsTarget[dstWord][dstIndex] = pixelsSource[srcIndex];
}
}
// null-terminate destination word
pixelsTarget[dstWord][N*N] = '\0';
}
}
// output
for (int block = 0; block < (M * M) / (N * N); block++)
{
printf("%s\n", pixelsTarget[block]);
}
}

Create a matrix with elements taken by another matrix

I have to implement a function which, given a matrix of 0s and 1s, returns a new matrix that contains the coordinates of the 1s. For example: if matrix is 3x3 and the output is:
1 0 1
0 1 1
0 0 1
New matrix will be 5x2 and the output will be:
0 0
0 2
1 1
1 2
2 2
Some advice? My method would be this:
int matrix[3][3];
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
if (matrix[i][i] == 1){
//Code i need
}
}
}
The solution really depends on the requirement:
Is it allowed to allocate result matrix with the maximum size possible (in this case 9 x 2).
If point 1 is not allowed, is it strictly required to use fixed size array (no dynamic allocation). If this is the case then may need to pass the matrix twice to allocate the right size of array.
Other solution is of course by using dynamic allocation (using malloc etc).
The simplified version of option 1 & 2 is shown below:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int matrix[3][3];
matrix[0][0] = 1;
matrix[0][1] = 0;
matrix[0][2] = 1;
matrix[1][0] = 0;
matrix[1][1] = 1;
matrix[1][2] = 1;
matrix[2][0] = 0;
matrix[2][1] = 0;
matrix[2][2] = 1;
//Solution 1 - If allowed to allocate matrix with size more than the result,
//i.e. if input is 3x3 matrix, then the maximum size of result matrix is 9 x 2
int resultMatrix1[9][2];
int usedCount1=0;
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++) {
if (matrix[i][j] == 1) {
resultMatrix1[usedCount1][0] = i;
resultMatrix1[usedCount1][1] = j;
usedCount1++;
} //end if
} //end for
} //end for
//Print the result
printf("\nSolution 1\n");
for (int i = 0; i < usedCount1; i++){
printf("%d %d\n", resultMatrix1[i][0], resultMatrix1[i][1]);
} //end for
//Solution 2 - strictly allocate matrix with size equal to the result.
//Without using dynamic allocation, meaning we need to have two passes.
//1st pass is to count the element which satisfy the criteria
int usedCount2=0;
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++) {
if (matrix[i][j] == 1) {
usedCount2++;
} //end if
} //end for
} //end for
int resultMatrix2[usedCount2][2]; //allocate the right size
int idx=0;
//2nd pass is to fill in the result matrix
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++) {
if (matrix[i][j] == 1) {
resultMatrix2[idx][0] = i;
resultMatrix2[idx][1] = j;
idx++;
} //end if
} //end for
} //end for
//Print the result
printf("\nSolution 2\n");
for (int i = 0; i < usedCount2; i++){
printf("%d %d\n", resultMatrix2[i][0], resultMatrix2[i][1]);
} //end for
return 0;
}
Results are the same for both solution:
Solution 1
0 0
0 2
1 1
1 2
2 2
Solution 2
0 0
0 2
1 1
1 2
2 2
If matrix[i][j] == 1 what do you know about the coordinates [i,j] ? That they are the coordinates of a 1 :)
Secondly, will the input matrix always be 3x3? If not, you'll want to store the dimensions of the matrix in variables, and use theses variables for your for loops.

How to print values down a column in a 2D array in C?

I have the following 2D array:
int censusData[4][3] = {{87290, 77787, 55632},
{83020, 78373, 62314},
{95588, 87934, 705421},
{112456, 97657, 809767}};
I want to print values column-wise in that, after 3 passes of a loop, it would print:
87290 83020 95588 112456
77787 78373 87934 97657
55632 62314 705421 809767
Notice how it's the first element from each sub-array, then the 2nd, then the third..etc
I can easily access each subarray when going row-wise using this:
int* averageCityIncome(int size, int size_2, int arr[][size_2]){
int* t_arr = malloc(4 * sizeof(int));
for (int i = 0; i < size; i++){
int avg = 0;
for (int j = 0; j < size_2; j++){
avg += arr[i][j];
}
avg /= size_2;
t_arr[i] = avg;
}
return t_arr;
}
But now I'm trying to read column-wise as stated above and I so far have this:
int* averageIncome(int size, int size_2, int arr[][size_2]){
int* t_arr = malloc(4 * sizeof(int));
for (int i = 0; i < size_2; i++){
for (int j = 0; j < size; j++){
printf("%d\n", arr[i][j]);
}
printf("-----\n");
}
return t_arr;
}
But it doesn't seem to be working. I'm still pretty new to C, and it's difficult to wrap my mind around 2D arrays still. Any help would be greatly appreciated.
You simply need to swap i and j for the dimensions when addressing a certain element of the array in the caller.
int* averageIncome(int size, int size_2, int arr[][size_2]) {
int* t_arr = calloc(4, sizeof(int)); // calloc to initialize the array elements to 0.
if ( t_arr == NULL )
{
fputs("Error at memory allocation for t_arr!", stderr);
exit(1);
}
int avg = 0; // definition of avg placed outside of the loop.
for (int i = 0; i < size_2; i++) {
for (int j = 0; j < size; j++) {
printf("%d\n", arr[j][i]); // j swapped with i.
avg += arr[j][i]; // same here too.
}
printf("-----\n");
t_arr[i] = avg / size;
avg = 0;
}
return t_arr;
}
Example (Online):
#include <stdio.h>
#include <stdlib.h>
#define ROWS 4
#define COLS 3
int* averageIncome(int size, int size_2, int arr[][size_2]) {
int* t_arr = calloc(4, sizeof(int)); // calloc to initialize the array elements to 0.
int avg = 0; // definition of avg placed outside of the loop.
for (int i = 0; i < size_2; i++) {
for (int j = 0; j < size; j++) {
printf("%d\n", arr[j][i]); // j swapped with i.
avg += arr[j][i]; // same here too.
}
printf("-----\n");
t_arr[i] = avg / size;
avg = 0;
}
return t_arr;
}
int main (void)
{
int censusData[ROWS][COLS] = {
{87290, 77787, 55632},
{83020, 78373, 62314},
{95588, 87934, 705421},
{112456, 97657, 809767}
};
int* p = averageIncome(ROWS, COLS, censusData);
for ( int i = 0; i < COLS; i++ )
{
printf("Average Income of %d. column is: %d\n", i + 1, p[i]);
}
return 0;
}
Output:
87290
83020
95588
112456
-----
77787
78373
87934
97657
-----
55632
62314
705421
809767
-----
Average Income of 1. column is: 94588
Average Income of 2. column is: 85437
Average Income of 3. column is: 408283
Side notes:
Always check the returned pointer from a memory-management for a null pointer if the allocation failed.
I used calloc() instead of malloc() to initialize all elements of the dynamically allocated array to 0.
The definition of avg should be placed before the nested loops, not within. Reset avg to 0 at the end of the outer loop.
avg /= size_2; t_arr[i] = avg; should be avg /= size; t_arr[i] = avg;. Note the replacement of size_2 with size.
avg /= size; t_arr[i] = avg; can be simplified by t_arr[i] = avg / size;.
#include <stdio.h>
int censusData[4][3] = {{87290, 77787, 55632},
{83020, 78373, 62314},
{95588, 87934, 705421},
{112456, 97657, 809767}};
int main() {
int* t_arr = malloc(3 * sizeof(int));
for(int i=0;i<3;i++){
int avg = 0;
for(int j=0;j<4;j++){
//Keep the I fixed here now J is varying and its position of column
//So you are reading all column values for ith row.
avg+=censusData[j][i];
}
avg/=4;
t_arr[i] = avg;
}
for(int i=0;i<3;i++){
printf("%d,",t_arr[i]);
}
return 0;
}
You can loop over the columns first and then print the corresponding element of each row:
for (int col = 0; col < 3; ++col)
{
for (int row = 0; row < 4; ++row)
{
printf("%d\n", censusData[row][col]);
// Do other stuff here
}
printf("-----\n");
}
For each row, the colth element is printed. So for col = 0, censusData[0][0], censusData[1][0], censusData[2][0], censusData[3][0] will be printed.
In your code, you can just swap the positions of the two for loops to iterate over the columns first.

Problems in generating random matrices in C

I wrote a serial program to generate 2 random matrices, multiply them and display the result. I wrote functions for each of the tasks, i.e. generating random matrix, multiplying the matrices and displaying the results. I cannot figure out why both the generated matrices are the same.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int **matrix_generator(int row,int col);
int **multiply_matrices(int **matrix_A,int **matrix_B,int rowsA, int colsA,int rowsB,int colsB);
void display_result(int **matrix,int cols,int rows);
void display_matrix(int **matrixA,int cols,int rows);
void main()
{
int **matrix_A,**matrix_B,**matrix_result,i,j,k,tid,rowsA,colsA,rowsB,colsB;
printf("Enter the dimensions of Matrix A:\n");
scanf("%d%d",&rowsA,&colsA);
printf("Enter the dimensions of Matrix B:\n");
scanf("%d%d",&rowsB,&colsB);
if(colsA==rowsB)
{
matrix_A = matrix_generator(rowsA,colsA);
matrix_B = matrix_generator(rowsB,colsB);
matrix_result = multiply_matrices(matrix_A,matrix_B,rowsA,colsA,rowsB,colsB);
printf("Matrix A:\n");
display_matrix(matrix_A,rowsA,colsA);
printf("\n\n");
printf("Matrix B:\n");
display_matrix(matrix_B,rowsB,colsB);
printf("\n\n");
display_matrix(matrix_result,rowsB,colsA);
}
else
{
printf("Check the dimensions of the matrices!\n");
exit(-1);
}
}
int **matrix_generator(int row, int col)
{
int i, j, **intMatrix;
intMatrix = (int **)malloc(sizeof(int *) * row);
srand(time(0));
for (i = 0; i < row; i++)
{
intMatrix[i] = (int *)malloc(sizeof(int *) * col);
for (j = 0;j<col;j++)
{
intMatrix[i][j]=rand()%10;
}
}
return intMatrix;
}
int **multiply_matrices(int **matrix_A,int **matrix_B,int rowsA, int colsA,int rowsB,int colsB)
{
int i, j, k, **resMatrix;
resMatrix = (int **)malloc(sizeof(int *) * rowsB);
for (i = 0; i < rowsA; i++)
{
resMatrix[i] = (int *)malloc(sizeof(int *) * colsA);
for (j = 0;j<colsB;j++)
{
for (k = 0; k < colsA; k++)
resMatrix[i][j] = resMatrix[i][j] + matrix_A[i][k] * matrix_B[k][j];
}
}
return resMatrix;
}
void display_matrix(int **matrix, int rows,int cols)
{
int i,j;
for (i = 0; i < rows; i = i + 1)
{
for (j = 0; j < cols; j = j + 1)
printf("%d ",matrix[i][j]);
printf("\n");
}
}
OUTPUT:
Enter the dimensions of Matrix A:
4
4
Enter the dimensions of Matrix B:
4
4
Matrix A:
8 7 8 4
9 8 3 9
1 2 0 4
6 0 2 3
Matrix B:
8 7 8 4
9 8 3 9
1 2 0 4
6 0 2 3
159 128 93 139
201 133 114 147
50 23 22 34
68 46 54 41
Can someone please help me understand where I'm going wrong? I have a pretty good idea that it's the matrix_generator() function but cannot seem to figure out what's wrong. Also, It's only multiplying square matrices, if the dimensions are different, like 4X5 and 5X4, I get a segmentation fault.
There are a few issues in your code:
1) You allocate memory incorrectly:
in multiply_matrices should be
resMatrix[i] = (int *)malloc(sizeof(int) * colsB);
and in matrix_generator
intMatrix[i] = (int *)malloc(sizeof(int) * col);
2) In main if you want to print matrix_result call
display_matrix(matrix_result,rowsA,colsB);
Dimensions of [rowsA,colsA] x [rowsB,colsB] is rowsA x colsB
3) malloc returns pointer to uninitialized memory, so you should set resMatrix elements to zero before summing
Content of 2-nd for loop in multiply_matrices should be
resMatrix[i][j] = 0;
for (k = 0; k < rowsB; k++) // CHANGED to rowsB
resMatrix[i][j] = resMatrix[i][j] + matrix_A[i][k] * matrix_B[k][j];
As pointed out in the comments: You need to seed the rand() function only once. Do srand(time(0)); at the start of your main() function and remove it from elsewhere.
Non-square matrices: There is a bug/typo in multiply_matrices
The line
for (k = 0; k < colsA; k++)
should be
for (k = 0; k < rowsA; k++)

Unexpected output at a particular row for a dynamic 2D array

I was solving a programing question for displaying Pascal triangle. In the code, I have set the last element of every row equal to zero. Still, the 6th row produces the output as 50 for the last element. I'm unable to figure out the reason for this. Kindly help. The code is attached.
int ** generate(int A, int *number_of_rows) {
*number_of_rows = A;
int i,j,nc=0;
int **result = (int**)malloc(A * sizeof(int *));
for(i=0;i<A;i++)
{
nc=i+1;
result[i]=(int)malloc(nc*sizeof(int));
result[i][0]=nc;
result[i][1] = 1;
for(j=2;j<nc;j++)
{
result[i][j]=result[i-1][j]+result[i-1][j-1];
}
}
return result;
}
Edit:
The first element of every row displays the number of columns in that row.
#include <stdio.h>
#include <stdlib.h>
int ** generate(int A, int *number_of_cols) {
int **result = malloc(A * sizeof(int *));
int nc;//number of columns
for(int i = 0; i < A; ++i){
number_of_cols[i] = nc = i + 1;
result[i] = malloc(nc * sizeof(int));
result[i][0] = result[i][nc-1] = 1;
if(i > 1)
for(int j = 1; j < nc -1; ++j){
result[i][j] = result[i-1][j-1] + result[i-1][j];
}
}
return result;
}
int main(void){
int n;
scanf("%d", &n);
int *number_of_cols = malloc(n * sizeof(int));
int **pascal_triangle = generate(n, number_of_cols);
for(int i = 0; i < n; ++i){
printf("%*s", 2 * (n-i-1), "");
for(int j = 0; j < number_of_cols[i]; ++j){
printf("%4d", pascal_triangle[i][j]);
}
puts("");
free(pascal_triangle[i]);
}
free(pascal_triangle);
free(number_of_cols);
return 0;
}
I can't understand the purpose of passing the *number_of_row just to assign it the other parameter address. However, I'd split your main for loop in 2:
one to allocate all memory and another to fill it.
for(i=0;i<A;i++)
result[i]=(int)malloc((i+1)*sizeof(int));
result[0][0]=1; //in your code, result[i-1] was accessed with i=0
for(i=1;i<A;i++) {
result[i][0] = i+1;
result[i][1] = 1;
for(j=2;j<i;j++)
result[i][j] = result[i-1][j] + result[i-1][j-1]; //when j reaches the last value,
//[i-1][j] won't work! So put j<i instead.
result[i][j] = 1;
}
The rest of code was OK, check if this is what you wanted. The resulting triangle shoud be:
1
2 1
3 1 1
4 1 2 1
5 1 3 3 1
6 1 4 6 4 1 etc.

Resources