2D Array elements changing after they are set - c

The program below is meant to print a square grid of integers based on the dimension which is inputted by the user (as part of the harvard cs50 course on edx).
The array is being initialized correctly, but when it comes to printing it out, the last column always prints incorrectly. I tried debugging by putting 2 printf statements in the innermost for loop of the init() function.
It seems that after the outermost loop runs once, the entry in the last column gets decremented by one, although it was correct just before this.
Why is this happening? Shouldn't it print correctly?
#include <stdio.h>
main()
{
void init(int dim, int arr[dim-1][dim-1]);
int dim;
printf("Enter board dimension(max 10): ");
scanf("%d", &dim);
int arr[dim-1][dim-1];
init(dim, arr);
int i,j;
for(i=0;i<dim;i++)
{
for(j=0;j<dim;j++)
{
printf("%2d ",arr[i][j]);
}
printf("\n");
}
}
void init(int dim, int arr[dim-1][dim-1])
{
int i,j,p;
for(i=0;i<dim;i++)
{
for(j=0;j<dim;j++)
{
arr[i][j] = (dim*dim-1)-i*dim-j;
}
for(p=0;p<dim;p++)
{
printf("%d ", arr[i][p]);
if(i>=1)
printf("%d ", arr[i-1][p]);
}
}
printf("\n");
if(dim%2==0)
{
arr[dim-1][dim-3] = 1;
arr[dim-1][dim-2] = 2;
}
}
EDIT: it should compile now

You define your array with a[dim - 1][dim - 1], which is one short of the desired dimension. If the user enters "4", you create a 3×3 array.
Your array is two-dimensional and of variable length. Therefore, you must pass the dimension alongside the array in functions, at least for the last dimension. You do this correctly, but the code in ´initbehaves as if the array werea[dim][dim], when it's actuallya[dim - 1][dim - 1]`.
Define the array with the actual dimension, dim and access the elements with indices 0 through dim - 1. This is usually done in a loop like this:
for (int i = 0; i < dim; i++) ...
Seeing >= or dim - 1 something similar should make you wary.
Your program now looks like this:
#include <stdio.h>
void init(int dim, int arr[dim-1][dim-1]);
void print(int dim, int arr[dim-1][dim-1]);
int main(void)
{
int dim;
printf("Enter board dimension: ");
scanf("%d", &dim);
int arr[dim][dim];
init(dim, arr);
print(dim, arr);
return 0;
}
void print(int dim, int arr[dim][dim])
{
int i,j;
for(i = 0; i < dim; i++) {
for(j = 0; j < dim; j++) {
printf("%2d ", arr[i][j]);
}
printf("\n");
}
}
void init(int dim, int arr[dim][dim])
{
int i, j;
for(i = 0; i < dim; i++) {
for(j = 0; j < dim; j++) {
int ii = dim - 1 - i;
int jj = dim - 1 - j;
arr[i][j] = ii*dim + jj;
}
}
}

Related

Function for printing 2D arrays of uknown size in C

I'm new to C programming and I've run into a problem when creating 2D array printing function. When I try to execute the code below I get:
points.c:13: error: unknown array element size
As I've checked there are very similar codes online, which are supposed to work. I've tried to initialize function as
int print2DArray( int arrayLen, int elementLen, int array[arrayLen][elementLen])
but it raises:
points.c:3: error: 'arrayLen' undeclared
Could somebody tell me what's wrong with this code and how to fix it? I also don't understand why very similar function for 1D arrays works just fine. It has to be in pure C.
#include <stdio.h>
//supposed to print 2D array:
int print2DArray(int array[][], int arrayLen, int elementLen)
{
int i;
int j;
for (i = 0; i < arrayLen; i++)
{
for (j=0; j < elementLen; j++)
{
printf("%5d", array[i][j]);
}
printf("\n");
}
}
//prints 1D array:
int printArray( int array[], int arrayLen)
{
int i;
for (i = 0; i < arrayLen; i++)
{
printf("%d", array[i]);
}
}
--- edit ---
I undestand most of you pointed out that the function has to be called like that:
#include <stdio.h>
int print2DArray( int arrayLen, int elementLen, int array[arrayLen][elementLen])
{
int i;
int j;
for (i = 0; i < arrayLen; i++)
{
for (j=0; j < elementLen; j++)
{
printf("%5d", array[i][j]);
}
printf("\n");
}
}
This raises an error:
points.c:3: error: 'arrayLen' undeclared
I'm using tcc for windows and according to documentation it is supposed to support C99 VLA.
It appears OP's compiler (or the mode it is used) does not support variable length array (VLA) as a function parameter.
Below is a non-VLA approach.
void print2DArrayX(int arrayLen, int elementLen, const int *array) {
int i;
int j;
for (i = 0; i < arrayLen; i++) {
for (j = 0; j < elementLen; j++) {
printf("%5d", array[i*elementLen + j]);
}
printf("\n");
}
}
Call with address of first int, not the 2D array
#define ARRAY_LEN 3
#define ELEMENT_LEN 4
int array[ARRAY_LEN][ELEMENT_LEN] = { 0 };
...
print2DArrayX(ARRAY_LEN, ELEMENT_LEN, array[0]);
Ok, so thanks for all the answers - they were very helpful. I've just tried to use gcc in linux and as you've pointed out this approach works fine:
int print2DArray( int arrayLen, int elementLen, int array[arrayLen][elementLen])
I guess tcc (tiny c compiler, windows version 0.9.27) doesn't support VLA after all. A bit strange since documentation says it does.
How about you try this solution.
#include <stdio.h>
int print2DArray(int* array, int arrayLen, int elementLen)
{
int i;
int j;
for (i = 0; i < arrayLen; i++)
{
for (j=0; j < elementLen; j++)
{
printf("%5d ", *(array+j+elementLen*i));
}
printf("\n");
}
}
int main(){
int arr[2][6] = { {9,258,9,96,-8,5},
{1,1212,-3,45,27,-6}
};
print2DArray(*arr,2,6);
return 0;
}
Unless you are using a C99 compiler,
int print2DArray( int arrayLen, int elementLen, int array[arrayLen][elementLen])
is not possible.
Even if you are using C99 compiler, your code has a problem. You need to pass one of the dimension first.
int print2DArray(int arrayLen, int elementLen, int arr[][elementLen]);
So,
int print2DArray(int arrayLen, int elementLen, int arr[][elementLen])
{
// Your code
int i;
int j;
for (i = 0; i < arrayLen; i++)
{
for (j=0; j < elementLen; j++)
{
printf("%5d", array[i][j]);
}
printf("\n");
}
return 0;
}
This can be used as
int main(void)
{
int i32Array[3][3] = {{-15, 4, 36}, {45, 55, 12}, {-89, 568, -44568}};
int m = 3, n = 3;
// I am not sure why 'print2DArray' would return an int
// (or anything at all for that matter).
// If you can establish a case for it,
// modify the function and the value it is supposed to return,
// And catch it below.
print2DArray(m, n, i32Array);
return 0;
}
I am not sure how you are calling print2DArray function. Unless you post that piece of code, it is difficult to resolve your problem. Confirm that you are calling the function correctly as shown above.

how to scan a 2d array using a function without deleting it's content

as a homework assignment, i need to scan N matrices and a user input integer, and scan if any of the matrices values contains that number
without using pointers.
as soon as i finish scanning the array and exits the function, the content of the array resets to zero, or trash if i dont init the array.
#pragma warning(disable:4996)
#include<stdio.h>
#define N 2
int exist(int matrix[][N], int elem);
void input_matrix(int matrix[][N], int size);
void main()
{
int matrix_1[][N] = { 0 }, matrix_2[][N] = { 0 }, matrix_3[][N] = { 0 };
int elem;
printf("please enter values of squared matrix:\n");
input_matrix(matrix_1[][N], N);
//(input_matrix(&matrix_2[N][N]));
// (input_matrix(&matrix_3[N][N]));
printf("please enter number to search for in the matrix:\n");
scanf("%d", &elem);
if (exist(matrix_1,elem))
//printf("exist.");//the next part of h.w to be written when input func works
}
void input_matrix(int matrix[][N], int size)//something here fishy
{
int i, j;
for (i = 0; i < size; i++)
{
for (j = 0; j < size; j++)
{
scanf("%d", &matrix[i][j]);
}
}
}
int exist(int matrix[][N], int elem)
{
int i, j;
int flag = 0;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
if ((matrix[i][j]) == elem)
{
flag = 1;
break;
}
}
}
return flag;
}
Inside the main function, in the call input_matrix(matrix_1[][N], N) you pass the invalid parameter. Instead should pass the whole matrix, like input_matrix(matrix_1, N).
As noted in a comment, it will be better to declare matrix like matrix_1[N][N].

C passing 2D array to function, printing results

I am trying to print a 2D array by passing it to a function, but I got weird results. Here is my code.
#include <stdio.h>
int main()
{
int b[2][3] = {{1,2,3},{4,5,6}};
printArray(b);
return 0;
}
void printArray(int (*ptr)[3])
{
int i, j;
for(i = 0; i < 2; i++)
{
for(j = 0; j < 3; j++)
{
printf("%d\t", *((*ptr+i)+j));
}
printf("\n");
}
}
However, the output is
1 2 3
2 3 4
I think it is something to do with my 'j' variable but I can't seem to pinpoint it. Please help.
You need to apply the addition operator before using the dereference operator. You need to use parenthesis as the dereference operator(*) has higher precedence than the addition operator(+).
So, this
printf("%d\t", *((*ptr+i)+j));
should be
printf("%d\t", *((*(ptr+i))+j));
or better
printf("%d\t", ptr[i][j]);
Also, you need to move the function printArray before main or provide a function prototype before main like:
void printArray(int (*ptr)[3]);
You need to multiply i by 3 before adding j ...
printf("%d\t", *((*ptr+(i*3))+j));
Abandoning indexes in favor of pointers, assuming matrix is stored by rows (whic is normally the case):
#include <stdio.h>
void printArray(int *);
int main()
{
int b[2][3] = {{1,2,3},{4,5,6}};
printArray((int*)b);
return 0;
}
void printArray(int *ptr)
{
int i, j;
for(i = 0; i < 2; i++)
{
for(j = 0; j < 3; j++)
{
printf("%d\t", *ptr++);
}
printf("\n");
}
}
Outputs:
1 2 3
4 5 6
printArray can take nb_column nb_line param and deal with all sort of 2D array
#include <stdio.h>
static void printArray(int *ptr, int nb_columns, int nb_lines)
{
int i, j;
for(i = 0; i < nb_lines; i++)
{
for(j = 0; j < nb_columns; j++)
{
printf("%d\t", *(ptr++));
}
printf("\n");
}
}
int main()
{
int b[2][3] = {{1,2,3},{4,5,6}};
printArray((int *)b, 3, 2);
return 0;
}

How to create a 2d array, the dimensions of which are specified by the user? (in C)

Here is my try. I am not totally sure about my manipulations with the pointer. Maybe this is why I am wrong, maybe there is some other case. I want to take the dimensions from the user and create a square matrix, make some manipulations with its elements, and display the original and results to the user. Last time I accomplished this by creating a 100x100 array, and specifying the end of each line, and end of lines by constants. Then I would print all the elements up to this constant. But it does not seem to be right to create a 100x100 array for 4x4 matrices. I could create a smaller array, but this does not seem to be the right solution to the problem. Is there a way in C to create a 2d array exactly the size specified by the users (it will be a square array). Thanks
#include <stdio.h>
#include <stdlib.h>
double * createMatrix(int dimentions);
void drawMatrix(double * matrix);
int main(void)
{
int n, i, j;
system("cls");
system("color 70");
system("pause");
puts("Enter the matrix's dimension");
scanf("%i", &n);
double * pmatrix = createMatrix(n);
for (i = 0; i < n; ++j)
for (j = 0; j < n; ++j)
{
printf("A%i%i: ", i + 1, j + 1);
scanf("%lf", pmatrix[i][j]);
getchar();
}
for (i = 0; i < n; ++i)
{
putchar('\n');
for (j = 0; j < n; ++j)
printf(" %lf ", &pmatrix[i][j]);
}
system("color 08");
return 0;
}
double * createMatrix(int n)
{
const int N = n;
const int N1 = N;
double matrix[N][N];
double * pmatrix = matrix;
return pmatrix;
}
You can create a matrix directly; you don't need a function for that. Replace the code
double * pmatrix = createMatrix(n);
by the regular way of declaring a 2-D array:
double matrix[n][n];
One more way of doing it using pointers.
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
double **pmatrix;
int rowsize, colsize, i, j;
printf("Enter the number of rows: ");
scanf("%d",&rowsize);
printf("Enter the number of columns: ");
scanf("%d",&colsize);
//Allocate memory for 2D array
pmatrix = malloc(rowsize*sizeof(double*));
for(i=0;i<rowsize;i++)
{
pmatrix[i] = malloc(colsize*sizeof(int));
}
//Accepting the values
for(i=0;i<rowsize;i++)
{
for(j=0;j<colsize;j++)
{
printf("A %i %i: ", i + 1, j + 1);
scanf("%lf",&pmatrix[i][j]);
}
}
//Printing the values
for(i=0;i<rowsize;i++)
{
for(j=0;j<colsize;j++)
{
printf("%lf\t",pmatrix[i][j]);
}
printf("\n");
}
//Free the memory
for(i=0;i<rowsize;i++)
free(pmatrix[i]);
free(pmatrix);
return 0;
}

Transpose matrix function in C, with function receiving and returning a 2D array

I need to create a function that takes a matrix and returns it transpose. The only requirement is that it directly returns a matrix, not just modifies it by reference. Here's what I've done so far:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define ROW 100000000
#define COL 100000000
int (*(f_MatTrans)(int mat[][COL], int r, int c))[COL];
int main(void)
{
int x[2][2]={1,2,3,4};
int (*a)[2];
a=f_MatTrans(x,2,2);
for(int i=0; i<2; i++)
{
for(int j=0; j<2; j++)
{
printf("X[%d][%d]=%d\n",i,j,x[i][j]);
printf("A[%d][%d]=%d\n",i,j,a[i][j]);
}
}
return 0;
}
int (*(f_MatTrans)(int mat[][COL], int r, int c))[COL]
{
int a[c][r];
for(int i=0; i<r; i++)
{
for(int j=0; j<c; j++)
{
a[j][i]=mat[i][j];
}
}
return a;
}
The purpose of this is to include the function on a library created by myself, just in case it is useful information.
The code in the question (when I read it) doesn't compile because the array x is not compatible with the function signature.
I'm not clear what the real constraints on your problem are. The easy way to do it in C99 or C11 is with VLA notation:
#include <stdio.h>
static void MatrixTranspose(int r, int c, int src[r][c], int dst[c][r])
{
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
dst[j][i] = src[i][j];
}
int main(void)
{
int x[3][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 } };
int y[2][3];
MatrixTranspose(3, 2, x, y);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
printf("X[%d][%d]=%d ", i, j, x[i][j]);
printf("Y[%d][%d]=%d\n", j, i, y[j][i]);
}
}
return 0;
}
Sample output:
X[0][0]=0 Y[0][0]=0
X[0][1]=1 Y[1][0]=1
X[1][0]=2 Y[0][1]=2
X[1][1]=3 Y[1][1]=3
X[2][0]=4 Y[0][2]=4
X[2][1]=5 Y[1][2]=5
My suspicion is that you are supposed to be doing something different (notationally more complex), but it is not yet clear what.
You cannot return a pointer to the local array, because that ceases to exist when the function returns. If you want your function to create the result array (not write to some other array that is passed into the function), you must use malloc() in these cases:
//The return type is actually `int (*)[r]`, but C doesn't like that.
int* f_MatTrans(int r, int c, int mat[][c]) {
int (*a)[r] = malloc(c*sizeof(*a));
for(int i=0; i<r; i++) {
for(int j=0; j<c; j++) {
a[j][i]=mat[i][j];
}
}
return *a;
}
Note that I changed the array types: If you declare mat as int mat[][COL], the number COL will be used to calculate the offset mat[1][0], which will be 100000000 integers after the first element in your case, while the array that you pass in only contains four integers. This is undefined behavior, and your program is allowed to format your harddrive if you do this.
Unfortunately, it is not possible for the type of the returned pointer to depend on the value of an argument to the function. That is why I changed the return type to a plain integer pointer, you must document that this is meant to be a pointer of type int (*)[r].
You would use the function above like this:
int main(void) {
int x[2][3]={1,2,3,4,5,6};
int (*a)[2] = (int (*)[2])f_MatTrans(2, 3, x);
for(int i=0; i<2; i++) {
for(int j=0; j<2; j++) {
printf("X[%d][%d]=%d\n",i,j,x[i][j]);
printf("A[%d][%d]=%d\n",i,j,a[i][j]);
}
}
free(a); //Cleanup!
return 0;
}

Resources