Filling array using array from function - c

I am trying to fill a 2d array in function drawInitialNim(), using values passed from main.
int drawInitialBoard(int x, int y, int z);
int main(int argc, const char * argv[]) {
int board[3][50] = {{0}};
int row1, row2, row3;
int i, j;
row1 = 0;
row2 = 0;
row3 = 0;
printf("Enter the number of rocks in each row: ");
scanf("%d %d %d", &row1, &row2, &row3); //values for amount of "O" in the array
printf("this is row 1: %d\n", row1); //debug
board[2][49] = drawInitialBoard(row1, row2, row3); //fill array from function
printf("this is 0,0 in main: %d\n",board[0][0]); // debug
for (i=0; i<3; i++) { //print indexes that contain "O" or 79
printf("Row %d: ", i+1);
for (j=0; j<50; j++) {
if (board[i][j] != 0) {
printf("%c", board[i][j]);
}
}
printf("\n");
}
}
int drawInitialBoard(int x, int y, int z)
{
int i,j,k;
static int arr[3][50] = {{0}};
for (i=0; i<x; i++) { //fill board with "O", or its that equal 79
arr[0][i] = 'O';
}
for (j=0; j<y; j++) {
arr[1][j] = 'O';
}
for (k=0; k<z; k++) {
arr[2][k] = 'O';
}
printf("This is 0,0 in the function: %d\n", arr[0][0]); //debug
return **arr;
}
I am getting this output, using 1, 2, 3 as input for x, y, z in main:
Row 1:
Row 2:
Row 3: O
I feel like the values from drawInitialNim() are not getting passed to main properly. I know that arrays can't be returned, so I returned the pointer. Additionally, I don't think that this is a dereferencing problem. I am not sure how to solve this.
Any help would be appreciated!

See the first thing I see incorrect in your program is:
You define the function like int drawInitialBoard(int x, int y, int z); which means that it will give back an int but you are returning **arr. Now according to what I know, * means "value at address of" so *arr would mean value at address of the pointer arr. And as arr is an array it is a pointer to its first element. So I think there is something wrong in there when you use return **arr. And as the first element in the array is not a pointer then I think that **arr would probably just give you not what you desire.

Your function is declaring an array, filling the rows according to the arguments passed, and then returning the value of arr[0][0], which in the case of the input values you state is 79 or 'O'. This value is then written to the main array board[2][49] and you then report correctly on its contents - all other elements are still 0. I don't see why you are using two arrays, not just one. And I don't see why you have declared an int array when you are treating it as a char array.

An easier way to make you program work would be, make your array board[3][50] global.
And, change the return type of your function drawInitialBoard(int x, int y, int z); to void, i.e., void drawInitialBoard(int x, int y, int z);.
And instead of working on a new array arr in the function, you can use the array defined previously board[3][50].
This won't clear the concept of passing the 2-D array, but will surely make it work.

Related

C: how to give 2D Array to a function

I want to pass a 2D array already filled with chars to a different method to do something with it.
Background: I am trying to implement GameOfLife. And I have already successfully implement the gameboard with a random amount of living cells. But now I want to pass the board(Array) to a different method to continue working with it. How to do so?
//wow das wird hurenshon
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
void spielStarten(int x, int amountOfLiving){
char feld[x][x];
for(int i = 0; i < x; i++){
for(int j = 0; j < x; j++){
feld[i][j] = 'o';
}
}
for(int i = 0; i < amountOfLiving; i++){
int a = (rand()%x);
int b = (rand()%x);
feld[a][b] = 'x';
}
printf("Gameboard: \n");
for(int i = 0; i < x; i++){
for(int j = 0; j < x; j++){
printf("%c ", feld[i][j]);
}
printf("\n");
}
spielRun(feld);
}
void spielRun(char feld[][]){
int neighbCount;
char feldNew[][] = feld[][];
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++) {
checkForNeighbours(feld[x][y]);
// in progress
}
}
}
int main(int argc, char* argv[]){
srand(time(NULL));
int x = 16;
if(argc < 2 || argc > 3){
printf("2. Argument eine Zahl fuer Feldgroesse eingeben\n");
printf("1. Argument eine Zahl 0-10 fuer ungefähre prozentuale Belegung mit lebenden
Zellen eingeben \n");
return 0;
}
if(argv[2] != NULL){
x = atoi(argv[2]);
}
int i;
i = atoi(argv[1]);
i = (x^2)*(0,1*i);
spielStarten (x,i);
return 0;
}
In the last line of the Method "Spiel starten" i want to give the array to the next Method "spielRun".
Edit: thanks to an other user I found this struture:
void printarray( char (*array)[50], int SIZE )
But it doesn't work for me since I can´t hardcode the number, because the arraysize depends on a user input.
thanks!
The difficulty here is that the size of your array is not known statically (once upon a time, your code would even not compile for the same reason).
That, combined with the fact that 2D-arrays are not arrays of 1D arrays (contrarily to what happen when you malloc a int ** and then every int * in it), and so it doesn't make sense not to specify the size when passing it to a function.
When using arrays of arrays (technically, pointers to a bunch of pointers to ints), like this
void f(int **a){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int **t=malloc(10*sizeof(int *));
for(int i=0; i<10; i++) t[i]=malloc(20*sizeof(int));
f(t);
}
That code is useless, it prints only unitialized values. But point is, f understands what values it is supposed to print. Pointers arithmetics tells it what a[1] is, and then what a[1][0] is.
But if this 2D-array is not pointers to pointers, but real arrays, like this
void f(int a[][20]){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int t[10][20];
f(t);
}
Then, it is essential that the called function knows the size (or at least all sizes, but for the first dimension) of the array. Because it is not pointers to pointers. It is an area of 200 ints. The compiler needs to know the shape to deduce that t[5][3] is the 5×20+3=103th int at address t.
So, that is roughly what is (better) explained in the link that was given in comments: you need to specify the size.
Like I did here.
Now, in your case, it is more complicated, because you don't know (statically) the size.
So three methods. You could switch to pointers to pointers. You could cast your array into a char * and then do the index computation yourself (x*i+j). Or with modern enough C, you can just pass the size, and then use it, even in parameters, declaration
void f(int x, int a[][x]){
printf("%d %d %d\n", a[0][0], a[1][0], a[0][1]);
}
int main(){
int t[10][20];
f(t);
}
Anyway, from an applicative point of view (or just to avoid segfault) you need to know the size. So you would have had to pass it. So why not pass it as first parameter (Note that the function in which you have this size problem, spielRun, does refers to a x, which it doesn't know. So, passing the size x would have been your next problem anyway)
So, spielRun could look like this (not commenting in other errors it contains)
void spielRun(int x, char feld[][x]){
int neighbCount;
char feldNew[][] = feld[][]; // Other error
for(int i = 0; i < x; i++) {
for(int j = 0; j < x; j++) {
checkForNeighbours(feld[i][j]); // Corrected one here
// in progress
}
}
}
And then calls to this spielRun could be
spielRun(x, feld);
Note that I address only the passing of array of size x here. There are plenty of other errors, and, anyway, it is obviously not a finished code. For example, you can't neither declare a double array char newFeld[][] = oldFeld[][]; nor affect it that way. You need to explicitly copy that yourself, and to specify size (which you can do, if you pass it).
I am also pretty sure that i = (x^2)*(0,1*i); does not remotely what you expect it to do.

How to pass a 2 Dimensional array as an argument of function in C?

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

Passing three dimensional arrays to a function in C

I use to program with FORTRAN, but I decided to learn C and C++. I started with C language, and the one thing that I never used are pointers, because FORTRAN pass values by reference. I built the sample code below to understand how pointers work with multidimensional arrays:
#include <stdio.h>
#include <stdlib.h>
#define DIM1 3
#define DIM2 2
#define DIM3 4
void display3DArray1(int, int , int n, int (*arr)[][n]);
void display3DArray2(int rows, int cols1, int cols2,int arr[][cols1][cols2]);
int main(void)
{
int matrix3D[DIM1][DIM2][DIM3] = {
{{1, 2, 3, 4}, {5, 6, 7, 8}},
{{9, 10, 11, 12}, {13, 14, 15, 16}},
{{17, 18, 19, 20}, {21, 22, 23, 24}}
};
int (*pmatrix3D)[DIM2][DIM3] = matrix3D;
display3DArray1(DIM1, DIM2, DIM3,pmatrix3D);
display3DArray2(DIM1, DIM2, DIM3,pmatrix3D);
return 0;
}
void display3DArray1(int rows, int cols1, int cols2,int (*arr)[][cols2]) {
printf("\n");
for(int i=0; i<rows; i++) {
for(int j=0; j<cols1; j++) {
for(int k=0; k<cols2; k++) {
printf("*arr : %d adress: %p\n",*(*((*arr+i*cols1))+j*cols2+k),*((*arr+i*cols1))+j*cols2+k);
}
}
}
}
void display3DArray2(int rows, int cols1, int cols2,int arr[][cols1][cols2]) {
printf("\n");
for(int i=0; i<rows; i++) {
for(int j=0; j<cols1; j++) {
for(int k=0; k<cols2; k++) {
printf("*arr : %d adress: %p\n", *(*(*(arr+i)+j) + k), *(*(arr+i)+j) + k) ;
}
}
}
}
The code works, but there is something that I wasn't able to understand. When I try to use the second printf of the second function in the first one I get a compilation error:
"invalid use of array with unspecified bounds" -- under gcc.
Why *(arr + i) doesn't work in the first function?
You can use the following two ways to pass/print the matrix:
void display3DArray1(int rows, int cols1, int cols2, int *A) {
int *a, i, j, k;
printf("\n");
for(i=0; i<rows; i++) {
for(j=0; j<cols1; j++) {
for(k=0; k<cols2; k++) {
a= A+(i*cols1*cols2)+(j*cols2)+k;
printf("%d, %p\n", *a, a);
}
}
}
}
void display3DArray2(int A[DIM1][DIM2][DIM3]) {
int i, j, k;
printf("\n");
for(i=0; i<DIM1; i++) {
for(j=0; j<DIM2; j++) {
for(k=0; k<DIM3; k++) {
printf("%d, %p\n", A[i][j][k], &A[i][j][k]);
}
}
}
}
The first method does not rely on the dimensions of the matrix; the second one does. As a result, the first one needs explicit address calculations (row i, col j, cell k).
Use calls respectively:
display3DArray1(DIM1, DIM2, DIM3, (int *)matrix3D);
display3DArray2(matrix3D);
Note the cast of the matrix to an int pointer.
In your code, you used parameter names to specify the dimensions of the matrix. In my C version, that is not legal; they must be constants.
Just a complement to Paul Ogilvie's answer.
The correct usage of Variable Length Arrays would be:
void display3DArray3(int rows, int cols1, int cols2,int arr[][cols1][cols2]) {
printf("\n");
for(int i=0; i<rows; i++) {
for(int j=0; j<cols1; j++) {
for(int k=0; k<cols2; k++) {
printf("*arr : %d adress: %p\n", arr[i][j][k], &arr[i][j][k]);
}
}
}
}
I was a bit puzzled, to be honest. The core issue is that the declaration of a function parameter like in f(T arr[]) declares an incomplete type whose size is not known (neither at compile time nor at run time). Originally I thought empty square brackets in function parameter declarations simply declare a pointer — notation notwithstanding —, but that is not the case. The parameter still has array type, albeit incomplete.1
When you write
void display3DArray1(int rows, int cols1, int cols2,int (*arr)[][cols2])
you declare a pointer to such an incomplete type of unknown size. This pointer cannot be manipulated in all the usual ways; in particular, adding to it in order to jump to the next element is impossible because we don't know where the current element ends (and hence the next element starts). But you try that in
printf("*arr : %d adress: %p\n", *(*(*(arr+i)+j) + k), *(*(arr+i)+j) + k) ;
with the innermost arr+1. Just dereferencing it works, because the variable holds the address of the first element all right. This is what the print in the first function does:
printf("*arr : %d adress: %p\n",*(*((*arr+i*cols1))+j*cols2+k),*((*arr+i*cols1))+j*cols2+k);
with *arr. The element size of the incomplete array to which arr points is known (these elements are arrays of cols2 ints), so that we can add to *arr, even if we can't add to arr proper.
For completeness: Why can you access arr that way in the second function? Well:
void display3DArray2(int rows, int cols1, int cols2,int arr[][cols1][cols2])
declares arr as an incomplete array type, true; but the size of its elements is well known: Those are cols1 x cols2 int matrices. The declaration just doesn't specify how many are there, but we can surely iterate them if we somehow know when to stop.
1 Of course this array, like any other, "decays" to a pointer in most contexts, so that the missing type information doesn't matter. But it matters if we have pointers to them.
I had trouble finding the correct syntax for dereferencing matrices of rank2 and rank3. The intent is to remove a level of indexing for faster execution. Here's some pseudo code that will get you started. This is more about getting the syntax right (MSVC 2019) than an example of working code.
int recurse(int n, unsigned char rank2[13][4], unsigned char rank3[13][4][13])
{
if (n < 13)
{
unsigned char (*deRefRank1)[4] = &rank2[n]; // deref matrix rank 2 to rank 1
unsigned char(*deRefRank2)[4][13] = &rank3[n]; // deref matrix rank 3 to 2
// insert pre-recurse code here ... use (*deRefRank1)[] and (*deRefRank2)[][]
if (recurse(n + 1, rank2[n], rank3[n])
return -1;
// insert post-recurse code here ...
}
return 0;
}
Your array indexing in the 'print' routines is invalid. The declaration of 'matrix3D' implies that the type of that name is 'pointer to int'. NOTE: Only one level of indirection there. The indexing expressions have a bunch of ''-s in front of terms; in C that means 'the item to the right of the '' is a pointer which must be dereferenced to get to the value'. That means you are in effect treating 'matrix3D' as 'pointer to (pointer to (pointer to int))' which is too many indirections.

Passing an array created from fscanf into a new function

I have successfully fscanf a text file and saved in to an array E2N1. I am trying to pass this into a function as a pointer but it is not working. Whenever I try to call E2N1[0][0], it says that E2N is neither an array or a pointer. I've been looking all over for a solution on this.
(Sorry E2N was meant to be E2N1)
I use fscanf as:
int E2N1[noz.rowE2N][Q.N];
FILE* f = fopen("E2N.txt", "r");
for(i=0; i<noz.rowE2N; i++){
for (j=0; j<Q.N; j++){
fscanf(f,"%d",&E2N1[i][j]);
}
fscanf(f,"\n");
}
fclose(f);
and again I can't pass E2N1 into function.
Your help will be greatly appreciated.
The function is:
double *dudtF = stiffness(&U, &massM, &noz, &newV, &E2N1, &I2E, &B2E, &PP, &QQ);
and I write the function header as:
double *stiffness(double *U, double *massM, MESH *meshN, double *V1, int *E2N1, int *I2E, int *B2E, ordApprox *pp, ordApprox *qq)
V1, I2E, B2E are three arrays and I'm trying to do the same with them as I am trying to do with E2N1.
The funny thing about arrays is that they actually act as pointers.
if you have array char a[3] the variable is equivalent to char* p the same way if you have array char b[3][4] the variable b is equivalent to char** q. In other words, you should consider changing the handling in the method to take reference to reference (and possibly once more to reference) to integer.
Try google... here are some results I've got.
http://www.dailyfreecode.com/code/illustrate-2d-array-int-pointers-929.aspx
http://www.cs.cmu.edu/~ab/15-123S09/lectures/Lecture%2006%20-%20%20Pointer%20to%20a%20pointer.pdf
You don't need to pass as &E2N1, just pass as E2N1 no & as array name itself translates to pointer.
double *dudtF = stiffness(&U, &massM, &noz, &newV, E2N1, &I2E, &B2E, &PP, &QQ);
Also, you need to take it as int ** as its 2-dimensional array.
double *stiffness(double *U, double *massM, MESH *meshN, double *V1, int **E2N1, int *I2E, int *B2E, ordApprox *pp, ordApprox *qq)
Here is the example how to transfer matrix from one function to another ...
void foo (int **a_matrix)
{
int value = a_matrix[9][8];
a_matrix[9][8] = 15;
}
void main ()
{
#define ROWS 10
#define COLUMNS 10
int **matrix = 0;
matrix = new int *[ROWS] ;
for( int i = 0 ; i < ROWS ; i++ )
matrix[i] = new int[COLUMNS];
matrix[9][8] = 5;
int z = matrix[9][8] ;
foo (matrix);
z = matrix[9][8] ;
}
You cannot reference a multi-dimensional array passed to a function by point referencing as in the following:
int iVals[10][10];
foo(iVals);
void foo(int** pvals)
{
// accessing the array as follows will cause an access violation
cout << pvals[0][1]; // access violation or unpredictable results
}
You will need to specify the second dimension to the array in the function prototype
for example:
foo(int ivals[][10])
{
cout << ivals[0][1]; // works fine
}
If do not know the dimensions, then I would suggest you follow the principles outlined here:
void foo(int *p, int r, int c)
{
for(int i=0; i<r; i++)
{
for(int j=0; j<c; j++)
{
printf("%d\n", p[i*c+j]);
}
}
}
int c[6][6];
// pointer to the first element
foo(&c[0][0], 6, 6);
// cast
foo((int*)c, 6, 6);
// dereferencing
foo(c[0], 6, 6);
// dereferencing
foo(*c, 6, 6);
I hope this helps.
Alternatively you could use SAFEARRAY - see:
http://limbioliong.wordpress.com/2011/06/22/passing-multi-dimensional-managed-array-to-c-part-2/

How do I write a function to search for an element in two dimensional array?

How do I write a function to search for an element in two dimensional array: if exists returns 1, otherwise returns no?
#include <stdio.h>
int search(int a[3][3],int x);
int main ()
{
int Array[3][3]; // array of size 3*3
int i,j; //counters i,j
int result,number;
for(i=0;i<3;i++)
{
printf("\n");
for(j=0;j<3;j++)
{
printf(" Array[%d][%d]= ",i,j);
scanf("%d", &Array[i][j]); //Fill The 3*3 array
}
}
printf("Enter The number you want:>");
scanf("%d",&number);
result=search(Array,number);
if(search(Array,number))
printf("Number exists\n");
else
printf("Number does not exists\n");
return 0;
}
int search(int a[3][3],int x){
int i,j;
for(i=0;i<3;i++){
for(j=0;j<3;j++){
if (x==a[i][j])
return 1;
return 0;
}
}
}
is this right ??
No, it's not. You need to move the return 0; out of the two for loops, and have it be the last statement in search.
No. The return 0; statement should be placed on the line before the very last closing brace.
Your program is not running because the search algorithm returns 1 if and only if the search element is in array[0][0], otherwise it returns zero and you think that the element doesn't exists. All you need to do is return 0 after traversing the full multi-dimensional array.
You can look into above answers. They have given good solutions.
No because your return 0; is inside the for loops.
I think what you want is that :
#include <stdio.h>
int search(int a[3][3],int x);
int main ()
{
int Array[3][3]; // array of size 3*3
int i,j; //counters i,j
int result,number;
for(i=0;i<3;i++)
{ printf("\n");
for(j=0;j<3;j++)
{
printf(" Array[%d][%d]= ",i,j);
scanf("%d", &Array[i][j]); //Fill The 3*3 array
}
}
printf("Enter The number you want:>");
scanf("%d",&number);
result=search(Array,number);
if(result)
printf("Number exists\n");
else
printf("Number does not exists\n");
return 0;
}
int search(int a[3][3],int x)
{
int i,j;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
if (x==a[i][j])
return 1;
}
}
return 0;
}
Jon gave you the answer you need, but there are some details to be aware of.
C's treatment of arrays is such that the search function doesn't receive a 3x3 array of int; rather, it receives a pointer to a 3-element array of int. From the C language standard, draft n1256:
6.3.2.1 Lvalues, arrays, and function designators
...
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
Thus, when you call result = search(Array, number);, the type of the expression Array is implicitly converted from a 3-element array of 3-element arrays of int (int [3][3]) to a pointer to a 3-element array of int (int (*)[3]). In the context of a function parameter declaration, T a[] and T a[n] are synonymous with T *a. You could change the function prototype to
int search(int (*a)[3], int x)
and it would behave exactly the same.
One consequence of this is that search can operate not just on 3x3 arrays, but on any Nx3 array. You've written your function to assume that a is always 3x3; if you want to be able to handle arrays of different numbers of rows, you would need to pass in a separate parameter to specify the number of rows in the array:
int search(int (*a)[3], size_t rows, int x)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < 3; j++)
if (a[i][j] == x)
return 1;
return 0;
}
int main(void)
{
int fiveRowArray[5][3] = {{ 1, 2, 3}, { 4, 5, 6}, { 7, 8, 9},
{10,11,12}, {13,14,15}};
int twoRowArray[2][3] = {{ 1, 2, 3}, { 4, 5, 6}};
int number;
printf("Gimme a number: ");
fflush(stdout);
scanf("%d", &number);
if (search(array, sizeof fiveRowArray / sizeof *fiveRowArray, number))
printf("Number exists in fiveRowArray\n");
else
printf("Number does not exist in fiveRowArray\n");
if (search(array, sizeof twoRowArray / sizeof *twoRowArray , number))
printf("Number exists in twoRowArray \n");
else
printf("Number does not exist in twoRowArray \n");
return 0;
}
The sizeof arr / sizeof *arr expression calculates the number of elements in the array by getting the total array size in bytes (sizeof arr) and dividing that by the number of bytes in an individual array element (sizeof *arr or sizeof arr[0]). Note that this only works for expressions of array type; it will not work for pointers that are being treated as arrays (such as the expression a in the search function).
If you want to handle different numbers of rows and columns, you'll have to take a different approach:
int search(int *a, size_t rows, size_t cols, int x)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
if (a[i * cols + j] == x)
return 1;
return 0;
}
int main(void)
{
int fiveByThree[5][3] = {...};
int twoByFour[2][4] = {...};
...
if (search(&fiveByThree[0][0],
sizeof fiveByThree / sizeof *fiveByThree,
sizeof fiveByThree[0] / sizeof *fiveByThree[0],
number))
...
if (search(&twoByFour[0][0],
sizeof twoByFour / sizeof *twoByFour,
sizeof twoByFour[0] / sizeof *twoByFour[0],
number))
...
}
In this case, we explicitly pass a pointer to the first element in each array, so instead of receiving a pointer to an array of int, search receives a simple pointer to int, which we treat as a 1D array, and compute the offset manually as i * cols + j. This code assumes that all elements in the 2D array are contiguous.
Edit
Note that in C99, you can have what are called Variable Length Arrays (VLAs), where the array dimension can be specified by a runtime variable rather than a constant expression; this allows us to write the prototype as
int search(size_t rows, size_t cols, int arr[rows][cols], int x)
and not mess with pointers.

Resources