I was given an assignment to create a program that gets a 2d array, number of rows and number of columns, and then return the transposed matrix and print it, using only pointer arithmetic, no [] allowed.
My code is working perfectly. It does indeed print the transposed matrix, but after that, i get the following message:
Windows has triggered a breakpoint in First Assignment.exe.
This may be due to a corruption of the heap, which indicates a bug in First Assignment.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while First Assignment.exe has focus.
The output window may have more diagnostic information.
Can anyone help me with this? I have no idea what's wrong. This is my code:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
int** allocate_matrix(int rows,int columns);
void print_matrix(int** mat1,int rows, int columns);
void scan_matrix(int** mat1,int rows, int columns);
int** transpose_matrix(int** mat1, int rows, int columns);
void main()
{
int** mat1;
int** trans_mat1;
int rows,columns;
printf("Enter the number of rows and columns you wish to see\n");
printf("Rows:");
scanf("%d",&rows);
printf("Columns:");
scanf("%d",&columns);
mat1 = allocate_matrix(rows,columns);
scan_matrix(mat1,rows,columns);
printf("the matrix you entered is: \n");
print_matrix(mat1,rows,columns);
printf("The transposed matrix is:\n");
trans_mat1 = transpose_matrix(mat1,rows,columns);
print_matrix(trans_mat1,columns,rows);
getch();
free(mat1);
free(trans_mat1);
}
int** allocate_matrix(int rows,int columns)
{
int i;
int** ptrmatrix;
ptrmatrix = (int**)malloc(rows*sizeof(int*));
for(i=0;i<rows;i++)
*(ptrmatrix+i) = (int*)malloc(columns*sizeof(int));
return ptrmatrix;
}
void print_matrix(int** mat1,int rows, int columns)
{
int i,j;
for(i=0;i<rows;i++)
{
for(j=0;j<columns;j++)
printf("%d ",*(mat1+i*columns+j));
printf("\n");
}
}
void scan_matrix(int** mat1,int rows, int columns)
{
int i,j;
for(i=0;i<rows;i++)
{
printf("Enter %d values for row number %d\n",columns,i+1);
for(j=0;j<columns;j++)
scanf("%d",(mat1+i*columns+j));
}
}
int** transpose_matrix(int** mat1,int rows,int columns)
{
int i,j;
int** trans_mat1;
trans_mat1 = allocate_matrix(columns,rows);
for(i=0;i<rows;i++)
for(j=0;j<columns;j++)
*(trans_mat1+(j*rows)+i)=*(mat1+(i*columns)+j);
return trans_mat1;
}
There seems to be an error in your pointer arithmetic that is causing the problem.
printf("%d ",*(mat1+i*columns+j));
Should be:
printf("%d ",*(*(mat1+i)+j));
It seems that you misunderstood how you are allocating your matrix. Normally in these kinds of assignments you would allocate your matrix as a single array of NxM integers and then use the formula that you initially used.
Example:
int rows = 7, cols = 9;
int* matrix = (int*) malloc(rows * cols * sizeof(int));
// Get 3rd row and 5th column value
int value = *(matrix + 3 * rows + 5);
But what you are doing is allocating an array of pointers to arrays of integers. Each integer array is a row in your code. So what you need to do is first access the correct pointer in the array of pointers (mat + i) (which signifies a pointer to the ith row array) , get the pointer value *(mat+i) and then access the correct column value. Here's a play by play for your example:
int rows = 9, cols = 21;
// Allocate the array of pointers to rows
int** matrix = (int**) malloc(rows * sizeof(int*));
// Allocate each row as an array of values
for (int j = 0; j < rows; ++j)
{
*(matrix + j) = (int*) malloc(cols * sizeof(int));
}
// Access the value at row 5, column 7
int* rowPtr = *(matrix + 5);
int value = *(rowPtr + 7);
Edit:
Other suggestions
Dealocation:
#mikyra's answer has also advised to deallocate your array's after use. I also recommend this but won't include it in my answer since he has already done the work in his. Please give him credit for it.
Memory efficiency:
Allocating the extra array of pointers uses more memory than using a single array of NxM size, provided that all rows are allocated. If you have some logic that tries to leave empty rows unallocated you could get better memory performance but it would only be beneficial for large, sparse matrices which I believe is beyond the scope of your assignment.
I personally prefer the single array approach as it is simpler to allocate/deallocate and index.
You really didn't do yourself a favor in deciding on not just allocating a row x column memory block for your matrix operations. Especially if this is intended as a beginners exercise in pointer-arithmetic.
The right expression to access the value of the cell in row i and column j is in fact this one:
*((*(mat1 + i))+j)
Using the following corrected versions everything should work as expected:
void print_matrix(int** mat1,int rows, int columns)
{
int i,j;
for(i=0;i<rows;i++)
{
for(j=0;j<columns;j++)
/* this line has been changed */
printf("%d ", *((*(mat1 + i))+j));
printf("\n");
}
}
void scan_matrix(int** mat1,int rows, int columns)
{
int i,j;
for(i=0;i<rows;i++)
{
printf("Enter %d values for row number %d\n",columns,i+1);
for(j=0;j<columns;j++)
/* this line has been changed */
scanf("%d",(*(mat1+i))+j);
}
}
int** transpose_matrix(int** mat1,int rows,int columns)
{
int i,j;
int** trans_mat1;
trans_mat1 = allocate_matrix(columns,rows);
for(i=0;i<rows;i++)
for(j=0;j<columns;j++)
/* this line has been changed */
*((*(trans_mat1 + j))+i) = *((*(mat1 + i))+j);
return trans_mat1;
}
Nevertheless you still lack a method to free all the memory consumed by your matrices. You'd need something like this:
void deallocate_matrix (void* mat, int rows) {
while (rows--)
free (*(mat + rows));
free (mat);
}
To really free all the allocated memory.
Related
Code:
#include <stdio.h>
char* input(char* arr,int N, int M){
int i, j;
for(i=0;i<N;i++){
for(j=0;j<M;j++){
scanf("%d",&arr[i][j]);
}
}
return arr;
}
int main() {
int i,N,M;
scanf("%d%d",&N,&M);
char arr[N][M];
arr=input(arr,N,M);
return 0;
}
Explanation:
The above given is a simple program where the user inputs the data into a 2-D array.
Here I have Tried to assign the value to arr pointer(That points to the base address); an address that we get from the input function, of the same array filled with elements now. We have passed the pointer to the array in input function as one argument, and the array dimensions as the other.
Majorly the problem faced here is about pointers and their application into arrays. But I am not able to figure out how I'll make the changes
There are two ways you can pass a 2D array as a function argument.
char *input (char [][m]arr, int n, int m)
You would read/write values the way you are doing in your code. Keep in mind that this is a feature introduced in C99 and won't compile with older compilers.
Another option is to pass it as a pointer:
char *input (char *arr, int n, int m)
Here you would read or write the array like so:
int i, j;
for(i=0; i<N; i++){
for(j=0; j<M; j++){
*(arr + i * n + j) = 'a';
/* OR you can also do this */
arr[i *n + j] = 'a';
}
}
Multidimensional arrays in C are stored in memory row by row. So if you allocated a 3 x 2 array, you would have 3 rows, each having 2 columns. But the memory layout would be:
0, 1 => row1
2, 3 => row2
4, 5 => row3
Here, 0,1,2,3,4,5 are the contiguous indices of the array. In order to access the 2nd column of 3rd row , given a pointer arr to the base address of the array, you would have to find the address of the correct cell in the array.
We know that each row has 2 cells so in order to jump to the 3rd row we need to add the row_id * number_of_cols_per_row to the base pointer. So to get to 3rd row, we need to do arr + 2 * 2. Once we are in the correct row we need to add the column offset of the column we want to access. So here we want to access the second column, so we add 1.
arr + 2 * 2 + 1
But this will be the address of the second column of the third row. In order to write here we need to use the * operator:
*(arr + 2 * 2 + 1) = 'a';
This is exactly what we are doing in the loop.
As an aside, in your code you are calling scanf with %d format specifier, which is for integers. But you are storing the value in a char array. This can be a potential bug, correct thing is to use %c specifier.
You can use a two-dimensional array masterpiece as an argument or a parameter, you can specify the size of all dimensions when defining the parameter group in the called function, or you can omit the size description of the first dimension, such as:
void Func(int array[3][10]);
void Func(int array[][10]);
Here is a complete solution that works:
#include <stdio.h>
void input(int N, int M, char arr[N][M]){
int i, j;
for(i=0; i<N; i++){
for(j=0; j<M; j++){
scanf("%c", &arr[i][j]);
}
}
}
int main() {
int N, M;
scanf("%d %d", &N, &M);
char arr[N][M];
input(N, M, arr);
return 0;
}
Is it possible to make a function that works with arrays of undefined length?
For example, I made this code to fill a matrix of 3x3 and I wonder if is there a way to do this but with a matrix of nxn.
void fillMatrix(double mat[][COLS])
{
int i,j;
printf("Enter the %d matrix elements:\n",COLS*ROWS);
for(i=0;i<ROWS;i++)
{
for(j=0;j<COLS;j++)
{
scanf("%lf",&mat[i][j]);
}
}
printf("\n");
}
In this code I defined ROWS=COLS=3.
Yes, if you know the number of columns in the 2D array at the time of passing it to the function. You do not have to define COL beforehand.
void foo(int col, int arr[][col]) {
//Do something
}
You can try this:
void func(void *data, int row, int col)
{
int (*a)[col] = (int(*)[col])data;
//now you can access a[i][j] with i<row and j<col
//data must be an continous array
//replace int with your data type
}
Working code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n = 5;
int (*a)[n];
int b[5][5];
a = (int(*)[n])b;
b[0][0]=0;
b[0][1]=1;
b[2][1]=111;
b[1][2]=666;
b[4][3]=222;
printf("%d\n", a[0][0]);
printf("%d\n", a[0][1]);
printf("%d\n", a[2][1]);
printf("%d\n", a[1][2]);
printf("%d\n", a[4][3]);
return 0;
}
may be you can add a new parameter row to your function fillMatrix(double mat[][COLS]), that is, fillMatrix(double mat[][col], int row)
another way:
double** matrix = (double**) malloc(sizeof(double*)*n);
for(int i = 0; i<n; i++){
matrix[i] = (double*) malloc(sizeof(double)*n);
}
then change the function to: fillMatrix(double** matrix, int n)
Is it possible to make a function that works with arrays of undefined length?
You'll better know the dimension of the array. If it is a function argument, you should in general pass the dimension in some other argument.
Remember that when passed as argument, an array is decayed into a pointer. Look also into some C reference site and later refer to the C11 standard n1570.
In your case, you want to define then have an abstract data type (probably some opaque pointer) for your matrixes. Using flexible array members could be useful. See this answer for details.
yes, you can do it using dinamic memory.
you will something like:
void fillMatrix(double** mat, int rows, int cols) {
int i,j;
printf("Enter the %d matrix elements:\n",rows*cols);
for(i=0;i<rows;i++)
{
for(j=0;j<cols;j++)
{
scanf("%lf",&mat[i][j]);
}
}
printf("\n");
}
where double** mat is a vector of vectors that you will have to ask for memory using malloc for the rows and the malloc for the columns.
This question already has answers here:
How to return matrix (2D array) from function? (C)
(3 answers)
Closed 6 years ago.
Maybe my question is easy but I am newby in C.
I create a function which read some data from a file and then pass them to a another function which parse them given number of rows and columns and create a 2D array.
I want to return this array in order to perform some operantions in its rows. How can I return a 2D array in C
Can someone give me an example or what may I did wrong?
Regards
Beware, returning arrays in C is a beginner's trap, because it is highly dependant on the storage duration:
static or global: no problem, but content will be overwritten by next call
automatic : never do that! What is actually returned is a dangling pointer, because the array's life ends at the end of the return statement
dynamic (malloc-ed): fine, but caller must free it later.
An more idiomatic way is that the caller passes an array that it owns, along with its size(s).
You can not return an array as a result of a function no matter whether it has one dimension or two. You can return a pointer to the first element of the array. Also, strictly speaking, there are no two dimensional arrays in C. What is closest to this, is an array containing another array as elements. I.e. a definition like:
int twoDimArray[2][3];
If dimensions of such array are determined dynamically you can not define it on file scope. You can define it locally withing some function only. Such an array will be a local variable, will be stored in system stack and will disappear when control leaves the function. Personally, I'd use such a pattern. I.e. a code like:
int main() {
int rows, cols;
...
getDimensions(&rows, &cols);
// definition with dynamic dimensions in function scope is O.K.
int a[rows][cols];
init(rows, cols, a);
proceed(rows, cols, a);
...
}
where init function can be defined like:
void init(int rows, int cols, int a[rows][cols]) {
int i,j;
for(i=0; i<rows; i++) {
for(j=0; j<cols; j++) {
a[i][j] = i*100+j;
}
}
}
If such a pattern can not be used (the array is too big and your system stack too small for example), I'd use:
int main() {
int rows, cols;
getDimensions(&rows, &cols);
int (*a)[cols] = malloc(sizeof(int [rows][cols]));
init(rows, cols, a);
proceed(rows, cols, a);
free(a);
}
If you insist on functions returning such an array I'd use void pointers:
void *allocate2DintArray(int rows, int cols) {
return(malloc(sizeof(int [rows][cols])));
}
void *allocateAndInit(int rows, int cols) {
int i,j;
int (*a)[cols] = allocate2DintArray(rows, cols);
for(i=0; i<rows; i++) {
for(j=0; j<cols; j++) {
a[i][j] = i*100+j;
}
}
return(&a[0][0]);
}
int main() {
int rows, cols;
...
getDimensions(&rows, &cols);
int (*a)[cols] = allocateAndInit(rows, cols);
proceed(rows, cols, a);
...
free(a);
}
I am trying to write a function that returns the pointer of 2d array read from a binary file. Although I compile without error there is always a segmentation fault, when I try to print one of the elements of the array. Here my code:
double ** readArray(int rows, int cols)
{
int i;
double **myArray=malloc(rows*sizeof(double*));
if (myArray){
for (i=0; i < rows; i++)
{
myArray[i]=malloc(cols*sizeof(double));
}
}
FILE *data;
data=fopen("matrix.bin", "rb");
fread(myArray,sizeof(double),rows*cols,data);
return myArray;
}
int main ()
{
int cols = 7;
int rows = 15;
double **myArray=readArray(rows, cols);
printf("%f\n", myArray[1][0]);
return 0;
}
The problem is that there is no 2D array in your code. The pointer-to-pointer look-up table thing is not a 2D array. It is [rows] number of segments scattered all over the heap, at random places. It is therefore also needlessly slow.
Also, you should keep memory allocation and algorithms separated.
Do something like this instead:
#include <stdio.h>
#include <stdlib.h>
void* allocArray (int rows, int cols)
{
return malloc( sizeof(double[rows][cols]) ); // allocate 1 2D-array
}
void readArray (int rows, int cols, double array[rows][cols])
{
FILE *data;
data=fopen("matrix.bin", "rb");
fread(array, sizeof(double[rows][cols]), 1, data); // read 1 2D-array
}
int main ()
{
int cols = 7;
int rows = 15;
double (*myArray)[cols] = allocArray(rows, cols);
readArray(rows, cols, myArray);
printf("%f\n", myArray[1][0]);
free(myArray); // free 1 2D-array
return 0;
}
The reason for the peculiar declaration double (*myArray)[cols] instead of the more logical double (*myArray)[rows][cols], is that we want to avoid the inconvenient array pointer de-referencing syntax. (*myArray)[1][0] is not easy to read. So instead of declaring an array pointer to a 2D array, declare an array pointer to a 1D array, then use pointer indexing on that array pointer. For any pointer, any_pointer[n] gives pointed-at item number n. Array pointers are no difference, so you get 1D array number n.
Your fread() call is overwriting all those pointers you painfully set up.
You need to read a single row at a time, and use the set-up pointer to store to:
for(size_t i = 0; i < rows; ++i)
fread(myArray[i], cols * sizeof *myArray[i], data);
Also, when doing I/O and memory allocation you should check the return values too, of course.
I have a 2D jagged array declared in my main() block. This is to be passed to a function to have memory allocated to it. The following is the most reduced case which compiles but crashes when it runs. Where am I going wrong?
#include <stdio.h>
#include <stdlib.h>
void alloc2d(double ***p);
int main () {
double **data;
alloc2d(&data);
printf("Before assign to data\n");
data[0][0] = 0.1;
printf("After assign to data\n");
free(data);
}
void alloc2d(double ***p) {
int i, n, m;
// Get some dynamically assigned sizes
printf("Enter size: ");
scanf("%d %d", &n, &m);
// Now allocate
*p = malloc(n * sizeof(double*));
for (i = 0; i < n; i++) {
*p[i] = malloc(m * sizeof(double));
}
printf("End of alloc2d\n");
}
This reads the values but crashes when I enter low numbers (i.e. '1 1') but crashes when I enter high numbers (i.e. '10 10').
You made a very simple syntax error
*p[i] = (double*)malloc(m * sizeof(double));
should really be
(*p)[i] = (double*)malloc(m * sizeof(double));
This is because in C, [] operator has higher precedence than *.
So when you type *p[i],
it is translated into **(p + i).
This means: you are asking the compiler to calculate the address by offsetting the address of p by i * sizeof(double**), which is clearly not what you actually want.
So, in order to force the compiler to dereference p first, simply surroud *p with brackets.
Operator precedence is the answer. *p[i] is equivalent to *(p[i]). This makes you access memory that lies right after the data pointer, which will either corrupt some other variables on the stack, or crash completely.
You were looking for (*p)[i], which will be the i-th entry in the newly allocated array.
What your alloc2d() allocates is not really a 2D array, but:
1 1D n-long array of pointers to double
n 1D m-long arrays of doubles
Multi-dimensional arrays in C are only possible, if all but the last of the dimensions are known at compile-time:
double a[5][11];
Maybe, this program can help you understand... Note, how COLUMNS is a compile-time constant, even if rows is a run-time variable:
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <err.h>
typedef double myrow_t[11]; /* 11 columns */
#define COLUMNS (sizeof(myrow_t)/sizeof(double))
static unsigned
alloc2d(myrow_t **pd)
{
unsigned int rows;
printf("Enter the number of rows: ");
while (scanf("%u", &rows) != 1)
printf("\ninvalid input, please, try again: ");
*pd = malloc(rows * sizeof(**pd));
if (*pd == NULL)
err(EX_TEMPFAIL, "Out of memory");
return rows;
}
int
main()
{
myrow_t *d;
unsigned int row, column, rows;
rows = alloc2d(&d);
for (row = 0; row < rows; row++)
for (column = 0; column < COLUMNS; column++)
d[row][column] = row * column;
for (row = 0; row < rows; row++) {
printf("Row %3d:\t", row);
for (column = 0; column < COLUMNS; column++)
printf("%.0f\t", d[row][column]);
puts("");
}
free(d);
return 0;
}