I want to store a lower triangular matrix in memory, without storing all the zeros.
The way I have implemented it is by allocating space for i + 1 elements on the ith row.
However, I am new to dynamic memory allocation in C and something seems to be wrong with my first allocation.
int main ()
{
int i, j;
int **mat1;
int dim;
scanf("%d", &dim);
*mat1 = (int**) calloc(dim, sizeof(int*));
for(i = 0; i < dim; i++)
mat1[i] = (int*) calloc(i + 1, sizeof(int));
for(i = 0; i < dim; i++)
{
for(j = 0; j < i + 1; j++)
{
scanf("%d", &mat1[i][j]);
}
}
/* Print the matrix without the zeros*/
for(i = 0; i < dim; i++)
{
for(j = 0; j < (i + 1); j++)
{
printf("%d%c", mat1[i][j], j != (dim-1) ? ' ' : '\n');
}
}
return 0;
}
If you want to conserve space and the overhead of allocating every row of the matrix, you could implement a triangular matrix by using clever indexing of a single array.
A lower triangular matrix (including diagonals) has the following properties:
Dimension Matrix Elements/row Total elements
1 x . . . 1 1
2 x x . . 2 3
3 x x x . 3 6
4 x x x x 4 10
...
The total number of elements for a given dimension is:
size(d) = 1 + 2 + 3 + ... + d = (d+1)(d/2)
If you lay the rows out consecutively in a single array, you can use the formula above to calculate the offset of a given row and column (both zero-based) inside the matrix:
index(r,c) = size(r-1) + c
The formulas above are for the lower triangular matrix. You can access the upper matrix as if it was a lower matrix by simply reversing the indexes:
index((d-1)-r, (d-1)-c)
If you have concerns about changing the orientation of the array, you can devise a different offset calculation for the upper array, such as:
uindex(r,c) = size(d)-size(d-r) + c-r
Sample code:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#define TRM_SIZE(dim) (((dim)*(dim+1))/2)
#define TRM_OFFSET(r,c) (TRM_SIZE((r)-1)+(c))
#define TRM_INDEX(m,r,c) ((r)<(c) ? 0 : (m)[TRM_OFFSET((r),(c))])
#define TRM_UINDEX(m,r,c,d) ((r)>(c)?0:(m)[TRM_SIZE(d)-TRM_SIZE((d)-(r))+(c)-(r)])
#define UMACRO 0
int main (void)
{
int i, j, k, dimension;
int *ml, *mu, *mr;
printf ("Enter dimension: ");
if (!scanf ("%2d", &dimension)) {
return 1;
}
ml = calloc (TRM_SIZE(dimension), sizeof *ml);
mu = calloc (TRM_SIZE(dimension), sizeof *mu);
mr = calloc (dimension*dimension, sizeof *mr);
if (!ml || !mu || !mr) {
free (ml);
free (mu);
free (mr);
return 2;
}
/* Initialization */
srand (time (0));
for (i = 0; i < TRM_SIZE(dimension); i++) {
ml[i] = 100.0*rand() / RAND_MAX;
mu[i] = 100.0*rand() / RAND_MAX;
}
/* Multiplication */
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
for (k = 0; k < dimension; k++) {
mr[i*dimension + j] +=
#if UMACRO
TRM_INDEX(ml, i, k) *
TRM_UINDEX(mu, k, j, dimension);
#else
TRM_INDEX(ml, i, k) *
TRM_INDEX(mu, dimension-1-k, dimension-1-j);
#endif
}
}
}
/* Output */
puts ("Lower array");
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
printf (" %2d", TRM_INDEX(ml, i, j));
}
putchar ('\n');
}
puts ("Upper array");
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
#if UMACRO
printf (" %2d", TRM_UINDEX(mu, i, j, dimension));
#else
printf (" %2d", TRM_INDEX(mu, dimension-1-i, dimension-1-j));
#endif
}
putchar ('\n');
}
puts ("Result");
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
printf (" %5d", mr[i*dimension + j]);
}
putchar ('\n');
}
free (mu);
free (ml);
free (mr);
return 0;
}
Note that this is a trivial example. You could extend it to wrap the matrix pointer inside a structure that also stores the type of the matrix (upper or lower triangular, or square) and the dimensions, and write access functions that operate appropriately depending on the type of matrix.
For any non-trivial use of matrices, you should probably use a third-party library that specializes in matrices.
mat1 = calloc(dim,sizeof(int*));
mat1 is a double pointer.You need to allocate memory for your array of pointers and later you need to allocate memory to each of your pointers individually.No need to cast calloc()
You are dereferencing mat1 at line 8 before it has even been set to point anywhere. You are allocating an array of pointers to int, but you are not assigning that to mat1 but to the dereference of mat1, which is uninitialized, we don't know what it points to.
So this line:
// ERROR: You are saying an unknown memory location should have the value of calloc.
*mat1 = (int**)calloc(dim,sizeof(int*));
Should change to:
// OK: Now you are assigning the allocation to the pointer variable.
mat1 = (int**)calloc(dim,sizeof(int*));
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I can't understand what doing the row
*(m[i] + sizes[i] - 1) = n;
#include <stdio.h>
#include <stdlib.h>
#define MAXSTR 100
int main()
{
int i, j, k, n;
char str[MAXSTR];
printf("Enter amount of rows: ");
fgets(str, MAXSTR, stdin);
k = atoi(str);
int* sizes = (int * ) calloc(k, sizeof(int));
int* sum = (int * ) calloc(k, sizeof(int));
int** m = (int ** ) calloc(k, sizeof(int * ));
printf("Enter matrix:\n");
for (i = 0; i < k; i++)
{
fgets(str, MAXSTR, stdin);
char* sym = str;
while (1)
{
m[i] = (int * ) realloc(m[i], (++sizes[i]) * sizeof(int));
n = strtol(sym, & sym, 10);
sum[i] += n;
if (n)
{
*(m[i] + sizes[i] - 1) = n;
}
else
{
--sizes[i];
break;
}
}
}
printf("\nMatrix: \n");
for (i = 0; i < k; i++)
{
for (j = 0; j < sizes[i]; j++)
printf("%i ", *(m[i] + j));
printf("\n");
}
printf("\nSum of elements of row:\n");
for (i = 0; i < k; i++)
printf("#%i - %i\n", i + 1, sum[i]);
free(sizes);
free(sum);
free(m);
return 0;
m is the matrix. Or more formally, it appears to be an array of "rows". Where each row is an array of integers.
sizes[i] is the length of the row represented by m[i].
This expression
*(m[i] + sizes[i] - 1) = n;
Appears to assign the value n to the last index of the row identified by m[i]. Essentially, it's appending to the end of the reallocated array.
This entire block of code is a bit complex:
while (1)
{
m[i] = (int * ) realloc(m[i], (++sizes[i]) * sizeof(int));
n = strtol(sym, & sym, 10);
sum[i] += n;
if (n)
{
*(m[i] + sizes[i] - 1) = n;
}
else
{
--sizes[i];
break;
}
}
It could be simplified to just:
int rowsize = 0;
while (1)
{
n = strtol(sym, &sym, 10); // parse the next number in str
if (n == 0) // the row ends when 0 is read
{
break;
}
m[i] = (int *)realloc(m[i], (rowsize+1) * sizeof(int); // grow the row's size by 1
m[i][rowsize] = n;
sum[i] += n;
rowsize++;
}
sizes[i] = rowsize;
m[i] is a pointer to the first element in the i:th matrix row
sizes[i] is the current number of columns in row i
sizes[i] - 1 is the last element in row i
m[i] + sizes[i] - 1 is a pointer to the last element in row i
*(m[i] + sizes[i] - 1) is the last element in row i
When allocating memory in C the result should not be cast, so
int* sizes = (int * ) calloc(k, sizeof(int));
should be simply
int* sizes = calloc(k, sizeof(int));
Also, the rows of the matrix m are never freed; to free the entire matrix you would need
for (i = 0; i < k; i++) {
free(m[i]);
}
free(m);
To answer your question the statement *(m[i] + sizes[i] - 1) = n; assigns the value n to whatever m[i] + sizes[i] - 1 points to. m is a pointer to a pointer to an int, so m[i] is an address of an int pointer. sizes[i] - 1 is usually how you convert from a size to index, so it's an offset from that int pointer.
Here are some suggested changes (all but one implemented below):
Reduce variable scope but initialize sum to NULL before the first failure so it can be unconditionally deallocated
It is better user experience to just read the data and terminate with an empty line instead of asking for the user count upfront. Just update the count k as we go along. This eliminates atoi which does not do any error handling. If you want to crash the program due to being out of memory you have to provide the data not just large a count.
(not fixed) realloc of 1 element at a time, if the O(i^2) is a performance issue, keep track of size and capacity of sum. When size == capacity, realloc by some factor, say, 2. Optionally, realloc to size when when we finish reading data as we now have the actual number of lines k.
No point of printing the array you just entered, which means we can get rid of the m and sizes arrays
Deallocate sum if realloc fails by introducing a temporary sum2 variable that will be NULL on error, but sum will still point to previously allocated data
Check for under and overflow of n and sum
Use sizeof on variable instead of type so you can change type just one place if needed
Allow 0 values by passing in by using a separate pointer endptr than sym to strtol()
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#define CHECK(p, msg) if(!(p)) {\
printf("%s:%d %s\n", __FILE__, __LINE__, (msg));\
goto out;\
}
#define MAXSTR 100
int main() {
int k;
char str[MAXSTR];
int *sum = NULL;
printf("Enter matrix:\n");
for(int i = 0;; i++) {
fgets(str, MAXSTR, stdin);
char *sym = str;
int *sum2 = realloc(sum, (i + 1) * sizeof(*sum));
CHECK(sum2, "realloc failed");
sum = sum2;
int j;
for(j = 0;; j++) {
char *endptr;
long n = strtol(sym, &endptr, 10);
CHECK(n >= INT_MIN && n <= INT_MAX,\
"value truncated");
if(sym == endptr) {
break;
}
sym = endptr;
CHECK((n >= 0 && sum[i] <= INT_MAX - n) || \
(n < 0 && sum[i] >= INT_MIN - n),\
"sum truncated");
sum[i] += n;
}
if(!j) {
k = i;
break;
}
}
printf("Sum of elements of row:\n");
for (int i = 0; i < k; i++)
printf("#%i - %i\n", i + 1, sum[i]);
out:
free(sum);
return 0;
}
Example execution:
Enter matrix:
0 1 2
Sum of elements of row:
#1 - 3
I'm trying to create a 3D array of ints initialized to zeros each of fixed size denoted as "dim".
For example, for dim=3, it will have 27 cells for ints.
I tried this:
int ***board;
int **rows;
int *tried;
board = calloc(dim,sizeof(int**));
rows = calloc(dim*dim, sizeof(int*));
tried = calloc(dim*dim*dim, sizeof(int));
int i;
int j;
int k;
for (i=0 ; i<dim ; i++) {
board[i] = rows + i*dim*dim;
for (j=0 ; j<dim ; j++) {
board[i][j] = tried + j*dim + i*dim*dim;
}
}
for (i=0 ; i<dim ; i++) {
for (j=0 ; j<dim ; j++) {
for (k=0 ; k<dim ; k++) {
board[i][j][k] = 0;
}
}
}
Trying to debug it, I found that it works until:
board[1][1][0] = 0
And then the program gets stuck and i just can't find the reason.
Can someone explain this please?
Thanks!
First about the error in your code. Compare this:
rows = calloc(dim*dim, sizeof(int*));
to this:
for (i=0 ; i<dim ; i++) {
board[i] = rows + i*dim*dim;
The entire size of the array allocated to rows is dim*dim elements. So, already in the second iteration of this loop, you access it out of bounds. You probably meant:
for (i=0 ; i<dim ; i++) {
board[i] = rows + i*dim;
As I already mentioned in the comment, this is not a 3D array. It mimics the usage in code by using pointers and you're using a kind-of clever trick here, so you only need 3 allocations in total. This might be a good idea under the following conditions:
your dim is variable at runtime, so you can't know it in advance, and
you have to write code for compilers that don't support VLAs1) (variable-length-arrays).
If one of this conditions is not true, it's much better to use a real 3D array. If the array doesn't have to live after leaving your function and the size isn't huge, just use a simple variable with automatic storage duration like
int board[3][3][3] = { 0 }; // possibly #define the dimension
or, for a variable dim, requiring a compiler supporting VLAs
int board[dim][dim][dim] = { 0 };
If on the other hand, the array will be huge and/or you need to return it from your function, you indeed have to allocate it dynamically. Then just use the following:
int (*board)[3][3] = calloc(3, sizeof *board); // static size
int (*board)[dim][dim] = calloc(dim, sizeof *board); // dynamic case, with VLA suppport
Also note that calloc() already sets your allocated memory to 0, so no need for looping all over it.
Side notes:
with sizeof, prefer the expression form, so instead of writing
int *a = calloc(5, sizeof(int));
better write
int *a = calloc(5, sizeof *a);
this avoids errors when you later change the type of a.
always check the return value of malloc() and friends -- they might return a null pointer (e.g. when you're running out of memory).
1) VLAs don't exist in the oldest standards C89/C90 -- they were introduced in C99 as a mandatory feature, but later made optional in C11. This allows C11 compilers to omit them, which might make sense when e.g. targeting embedded systems. In practice, you can safely assume a C11 compliant compiler supports them if it isn't special purpose.
I rewrote your code to show how allocation of a 3D array could look like. And as pointed out in the comments, there's no need to initialize the array to 0 since calloc does that for you. Had you used malloc the array would not have been initialized.
#include <stdlib.h>
#include <stdio.h>
#define dim (3u)
int main() {
int x;
int y;
int z;
int ***cube;
cube = calloc(dim, sizeof(int**));
for (z = 0; z < dim; z++) {
cube[z] = calloc(dim, sizeof(int*));
for (y = 0; y < dim; y++) {
cube[z][y] = calloc(dim, sizeof(int));
}
}
for (z = 0; z < dim; z++) {
for (y = 0; y < dim; y++) {
for (x = 0; x < dim; x++) {
cube[z][y][x] = z + y + x;
}
}
}
for (z = 0; z < dim; z++) {
for (y = 0; y < dim; y++) {
for (x = 0; x < dim; x++) {
printf("%d ", cube[z][y][x]);
}
printf("\n");
}
printf("\n");
}
return 0;
}
What you want to store in it is up to you, in my example I wrote the sum of the counter to each index.
Code below is Unlicense.
I will suggest something different. Just create a 1D array and set some boundaries to interpret it as 3D. I added some test cases for you to better visualize how it works. Do not forget to look at how easy 'calloc' call is. Here is the code:
#include <stdlib.h>
#include <stdio.h>
int getindex(int dim, int x, int y, int z) {
return z * dim * dim + y * dim + x;
}
void printarray(int* tdarray, int dim) {
printf("[\n");
for (int i = 0; i < dim; i++) {
printf("\t[\n");
for (int j = 0; j < dim; j++) {
printf("\t\t[");
for (int k = 0; k < dim; k++) {
if (k == 0) printf("%d", *(tdarray + getindex(dim, k, j, i)));
else printf(",\t %d", *(tdarray + getindex(dim, k, j, i)));
}
printf("]\n");
}
printf("\n\t]\n");
}
printf("]\n");
}
int main() {
int dim = 10;
size_t arraysize = sizeof (int) * dim * dim * dim;
int lookupindex = getindex(dim, 7, 5, 4); /* Numbers picked randomly */
int* tdarray = (int*) malloc(arraysize);
calloc(*tdarray, arraysize);
/* Below is test code and visualizations, all magic happens above.*/
if (*(tdarray + lookupindex) == 0) *(tdarray + lookupindex) = 7;
printf("tdarray[x:%d, y:%d, z:%d]:\t%d\n\n", 7, 5, 4, *(tdarray + lookupindex));
printarray(tdarray, dim);
printf("\n\n\n\n\n\n\n\n\n\n");
for (int i = 0; i < getindex(dim, 9, 9, 9) + 1; i++) *(tdarray + i) = i;
printarray(tdarray, dim);
free(tdarray);
}
How to normalize a matrix?
Suppose I have a 2x3 matrix:
1 2 3
4 5 6
The normalized matrix would be:
1/sqrt(pow(2,2) + pow(3,2)) 2/sqrt(pow(2,2) + pow(3,2)) 3/sqrt(pow(2,2) + pow(3,2))
4/sqrt(pow(5,2) + pow(6,2)) 5/sqrt(pow(5,2) + pow(6,2)) 6/sqrt(pow(5,2) + pow(6,2))
This is my sample code:
#include <stdio.h>
#include <conio.h>
#include <math.h>
int main(){
int rows, cols, rowCounter, colCounter, r, c;
int initial[100], inputMatrix[100][100], rowSum[100] = {0}, norm[100][100], square[100] = {0};
printf("Enter size of a matrix\n");
scanf("%d %d", &rows, &cols);
printf("Enter matrix of size %dX%d\n", rows, cols);
/* Input matrix */
for(rowCounter = 0; rowCounter < rows; rowCounter++){
for(colCounter = 0; colCounter < cols; colCounter++){
scanf("%d", &inputMatrix[rowCounter][colCounter]);
}
}
for(r = 0; r < rows; r++)
{
for(c = 1; c < cols; c++)
{
float a;
a == inputMatrix[r][c];
square[r] += pow(a, 2);
}
printf("%.2lf ", square[r]);
}
for(rowCounter = 0; rowCounter < rows; rowCounter++)
{
for(colCounter = 0; colCounter < cols; colCounter++)
{
norm[rowCounter][colCounter] == (inputMatrix[rowCounter][colCounter]) / sqrt(square[rowCounter]);
}
}
printf("\nNormalized Matrix:\n");
for(rowCounter = 0; rowCounter < rows; rowCounter++)
{
for(colCounter = 0; colCounter < cols; colCounter++)
{
printf("%.3lf ", norm[rowCounter][colCounter]);
}
printf("\n");
}
getch();
return 0;
}
Why are you using == here:
for(r = 0; r < rows; r++)
{
for(c = 1; c < cols; c++)
{
float a;
a == inputMatrix[r][c]; //look here
square[r] += pow(a, 2);
}
It should be:
for(r = 0; r < rows; r++)
{
for(c = 1; c < cols; c++)
{
float a;
a = inputMatrix[r][c];
square[r] += pow(a, 2);
}
The same here:
norm[rowCounter][colCounter] == (inputMatrix[rowCounter][colCounter]) / sqrt(square[rowCounter]);
It should be:
norm[rowCounter][colCounter] = (inputMatrix[rowCounter][colCounter]) / sqrt(square[rowCounter]);
And you should be careful here:
int initial[100], inputMatrix[100][100], rowSum[100] = {0}, norm[100][100], square[100] = {0};
Are you sure about use int for all of this declarations?
I think you should use double or float instead, at least in some of them.
There are some problems in your code, I'll try to address the most important ones.
Your norm matrix is a 2D array of int as inputMatrix, but you have to use an array of float or double to correctly store the result and to perform the right calculation. In C if both of the terms of a division are integers types an integer division (like: 3/2 = 1, not 1.5) is performed, which is not what you need.
Another mistake is to use == instead of = to perform an assignment. In C == is the 'equal to' relational operation.
EDIT
As #chux pointed out it would be wiser to choose a more accurate type for a and square[]. Using long long int will (may) prevent numeric overflow in case the elements of the matrix are too big for their square or the sum of them to be reprensented by an int.
Be aware that if you decide to use double instead there are other subtle numerical issues concernig the sum of small number (and the order in which it is performed) represented by floating point types. So, as a partial remedy, you can use long double (if it really has more precision then double in your environment) for a and square.
EDIT 2
In the question and in comment you say that the first element of each row of the matrix is supposed to be "constant in the matrix" so it doesn't take part to the sum of squares in your code and in the example you gave, but in both of them they are updated in the next loop. I'm not sure of what is going on, so I corrected my code to mimic the behavior of yours.
Here is a working corrected version of your code:
#include <stdio.h>
#include <math.h>
int main() {
int rows, cols, r, c;
// you may think about dynamical allocation here
int inputMatrix[100][100], rowSum[100] = {0};
// it's better to use a type that can manage bigger numbers to avoid numeric overflow
long long int a, square[100] = {0};
// your starting matrix can be a matrix of int but the normalized one need to
// contain floating point numbers
double norm[100][100], k;
printf("Enter size of a matrix\n");
scanf("%d %d", &rows, &cols);
printf("Enter matrix of size %dX%d\n", rows, cols);
/* Input matrix */
for ( r = 0; r < rows; r++) {
for (c = 0; c < cols; c++) {
scanf("%d", &inputMatrix[r][c]);
// ^^ if you are scanning integer numbers...
}
}
printf("\nrows: %d cols: %d elements:\n",rows,cols);
for( r = 0; r < rows; r++) {
for( c = 0; c < cols; c++) {
printf("%d ", inputMatrix[r][c]);
// ... ^^ you should print integer numbers
}
printf("\n");
}
for (r = 0; r < rows; r++) {
for (c = 1; c < cols; c++) {
// ^^^ I don't know why you skip this here
a = inputMatrix[r][c];
//^ You have to assign, not to compare!
square[r] += a * a;
// ^^^^^ no need to call pow()
}
printf("Sum of squares of row %d: %lld\n",r,square[r]);
// square contains int ^^
// It would be nice and safer if you check here if square == 0 to avoid a
// division by zero and probably detect bad input data
}
for ( r = 0; r < rows; r++ ) {
// It's far more efficient to precalculate this term, even if compilers
// could be smart enough to do it for you. You may want to store those
// values in an array of doubles instead of the (sum of) squares
k = 1.0 / sqrt(square[r]);
for( c = 0; c < cols; c++ ) {
norm[r][c] = k * inputMatrix[r][c] ;
// again, ^ assign not compare
}
}
// you can add the printf to the previous loop...
printf("\nNormalized Matrix:\n");
for( r = 0; r < rows; r++) {
for( c = 0; c < cols; c++) {
printf("%.3lf ", norm[r][c]);
// ^^^^^ norm contains double
}
printf("\n");
}
return 0;
}
I keep the input matrix of integer type, but it would be better to use double for that too. As i added a print loop for the original matrix, the final output is:
rows: 2 cols: 3 elements:
1 2 3
4 5 6
Sum of squares of row 0: 13
Sum of squares of row 1: 61
Normalized Matrix:
0.277 0.555 0.832
0.512 0.640 0.768
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;
}
Good day,
I need a help. We get a homework to write a programme in C which should generate and print bigger and smaller matrix made from "X" and ".". And after that find if the smaller 3x3 matrix is in the bigger one. I tried to make it by one dimensional field, but my programme finds matrix only sometimes. I am not able to find it out where is my mistake and how to fix it. I read some threads on forum, but none of it was helpfull to me. Thanks for any help.
P.S. Forgive me language mistakes, I am not a native english speaker.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* Generates matrix of given dimensions */
void initMatrix(char *Matrix, int rows, int cols)
{
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
Matrix[i*cols+j]= "X.." [rand () % 3]; // 2/3 that X will be generated
}
}
}
/* Prints given matrix */
void printMatrix(char *Matrix, int rows, int cols)
{
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
printf("%c", Matrix[i * cols + j]);
}
printf("\n");
}
}
int main(void)
{
int rowM1, colM1; // Dimensions of primary (bigger) matrix
int rowM2 = 3, colM2 = 3; // Dimensions of secondary (smaller) matrix
int first, second; // Position of the begginng of matrix 2 in matrix 1
int rel_pos;
int i, j, k, l;
char *M1 = NULL; // Pointer to matrix 1
char *M2 = NULL; // Pointer to matrix 2
printf("Enter the matrix dimensions separated by a space ([rows] [columns]) : ");
if (scanf("%d %d", &rowM1, &colM1) != 2) // Bad parameters
{
printf("Wrong parameters.");
return 1; // End program
}
if (rowM1 < rowM2 || colM1 < colM2)
{
printf("Matrix 2 can not be found because is bigger than Matrix 1.");
return 1;
}
srand(time(NULL)); // Randomly generates numbers
M1 = malloc(rowM1 * colM1 * sizeof(char)); // M1 points to matrix 1
M2 = malloc(rowM2 * colM2 * sizeof(char)); // M2 points to matrix 2
initMatrix(M1, rowM1, colM1); // Initializes matrix 1
initMatrix(M2, rowM2, colM2); // Initializes matrix 2
printf("\nMatrix 1:\n");
printMatrix(M1, rowM1, colM1); // Prints matrix 1
printf("\nMatrix 2:\n");
printMatrix(M2, rowM2, colM2); // Prints matrix 2
putchar('\n');
for (i = 0; i < rowM1; i++)
{
for(j = 0; j < colM1; j++){
{
for (k = 0; k < rowM2 * colM2; k++) // checking the smaller matrix
{
if(M1[i*rowM1+j] == M2[k])
{
first = i*rowM1;
rel_pos = i+1;
}
if(j % colM2 == 0) // Matrix 2 has ended on this line, move on next one.
rel_pos += colM1 - colM2;
if(M1[rel_pos] == M2[j]) // If character are same, keep searching
rel_pos++;
else // else this is not the matrix I'm searching for
break;
}
if(k == rowM2*colM2) // if all k cykle went to the end I found the matrix
{
printf("Matrix found at [%d][%d]", first, second);
return 0;
}
}
}
if(i*colM1 > i*colM1-colM2) // matrix cannot be found
printf("Matrix not found");
break;
}
free(M1); // frees memory of matrix 1
free(M2); // frees memory of matrix 2
return 0;
}
Your inner loop for (k = 0; k < rowM2 * colM2; k++) iterates over the contents of the small matrix, and should compare each entry of the small matrix to the corresponding entry in the large matrix (as defined by the start point given by i and j).
The comparison if(M1[i*rowM1+j] == M2[k]), however, compares all entries of the small matrix with the same entry in the large matrix (the array index of M1 is independent of k).
To fix this, you need to make a fourdimensional loop
for(y0 = 0; y0 < colM1 - colM2 + 1; y0++) {
for(x0 = 0; x0 < rowM1 - rowM2 + 1; x0++) {
for(dy = 0; dy < colM2; dy++) {
for(dx = 0; dx < rowM2; dx++) {
if(M1[(y0 + dy)*rowM1 + (x0 + dx)] == M2[dy*rowM2 + dx]) {
...
}
}
}
}
}