Assignment: Print 2D array

E

Eric Lilja

Assignment: Create a 3x4 2-dimensional array of integers. Populate each
element using some non-random scheme so that no two elemens contain the
same value. Then create two functions for printing the 2D array. One
should only work for set column size, accepting only the number of rows
as an additional argument, one should accept both the number of rows
and columns as arguments.

So, I came up with:
#include <stdio.h>

static void print_2d_array(int[][4], int);
static void print_2d_array_2(const int *, int, int);

int
main(void)
{
int array[3][4] =
{
{0, 1, 2, 3},
{4, 5, 6, 7},
{8, 9, 10, 11},
};
int num_rows = sizeof(array) / sizeof(array[0]);
int num_cols = sizeof(array[0]) / sizeof(array[0][0]);

print_2d_array(array, num_rows);
print_2d_array_2(&array[0][0], num_rows, num_cols);

return 0;
}

/* Even if specify int array[2][4], the compiler would
happily accept our 3x4 array. Therefore we leave
that dimension empty, passing the number of rows
as an argument. However, if we try to pass a 2D-array
where the number of columns is not 4, the compiler
will complain. */
static void
print_2d_array(int array[][4], int num_rows)
{
int row = 0;
int column = 0;

for(row = 0; row < num_rows; ++row)
for(column = 0; column < 4; ++column)
printf("[%i][%i] = %i\n", row, column, array[row][column]);
}

static void
print_2d_array_2(const int *ptr, int num_rows, int num_columns)
{
int currow = 0;
int curcol = 0;
int offset = 0;

for(; currow < num_rows; ++currow)
{
for(curcol = 0; curcol < num_columns; ++curcol) /* curcol = 0
needed! */
{
/* The layout of the 2D-array is linear as seen by our
program,
on a row-by-row basis. All rows have the same number of
columns.
Rows and columns are indexed starting from 0.
So if we have five colums per row and we want the element
in
the second column of the second row, we want element with
offset
six (offset 0 gives us the element at [0][0]).
offset = index_of_wanted_row * num_cols_per_row +
index_of_wanted_column
or
offset = 1 * 5 + 1 = 6 */
offset = currow * num_columns + curcol;
printf("[%i][%i] = %i\n", currow, curcol, *(ptr + offset));
}
}
}


Output when run:
$ ./foo.exe
Calling print_2d_array().
[0][0] = 0
[0][1] = 1
[0][2] = 2
[0][3] = 3
[1][0] = 4
[1][1] = 5
[1][2] = 6
[1][3] = 7
[2][0] = 8
[2][1] = 9
[2][2] = 10
[2][3] = 11
Calling print_2d_array_2().
[0][0] = 0
[0][1] = 1
[0][2] = 2
[0][3] = 3
[1][0] = 4
[1][1] = 5
[1][2] = 6
[1][3] = 7
[2][0] = 8
[2][1] = 9
[2][2] = 10
[2][3] = 11

Is this what my instructor is after?

/ E
 
F

Flash Gordon

Eric said:
Assignment: Create a 3x4 2-dimensional array of integers. Populate each
element using some non-random scheme so that no two elemens contain the
same value. Then create two functions for printing the 2D array. One
should only work for set column size, accepting only the number of rows
as an additional argument, one should accept both the number of rows
and columns as arguments.

Good, you've given us the problem statement for the program and you are
not trying to hide that it is homework. A pleasant change.
So, I came up with:
#include <stdio.h>

static void print_2d_array(int[][4], int);

I would avoid using a magic number. Use a #define instead:
#define NO_COLS 4
static void print_2d_array(int[][NO_COLS], int);
static void print_2d_array_2(const int *, int, int);

As a matter of style I would prefer having the parameters names in the
prototype. Also, why only specify const in one of the two functions?
int
main(void)
{
int array[3][4] =

You did not need to specify the number of rows. You could have used:
int array[][4] =
Or, with the change above:
int array[][NO_COLS] =
{
{0, 1, 2, 3},
{4, 5, 6, 7},
{8, 9, 10, 11},
};
int num_rows = sizeof(array) / sizeof(array[0]);
int num_cols = sizeof(array[0]) / sizeof(array[0][0]);

print_2d_array(array, num_rows);
print_2d_array_2(&array[0][0], num_rows, num_cols);

return 0;
}

/* Even if specify int array[2][4], the compiler would
happily accept our 3x4 array. Therefore we leave
that dimension empty, passing the number of rows
as an argument. However, if we try to pass a 2D-array
where the number of columns is not 4, the compiler
will complain. */
static void
print_2d_array(int array[][4], int num_rows)

Again with the magic number.
{
int row = 0;
int column = 0;

for(row = 0; row < num_rows; ++row)
for(column = 0; column < 4; ++column)

And again. Lots of changes if you want to change the number of columns!
printf("[%i][%i] = %i\n", row, column, array[row][column]);
}

static void
print_2d_array_2(const int *ptr, int num_rows, int num_columns)
{
int currow = 0;
int curcol = 0;
int offset = 0;

I would not bother initialising these here.
for(; currow < num_rows; ++currow)

As a matter of style I would initialise currow in the for loop rather
than on declaration. Then it does not matter if things change.
for(currow = 0; currow < num_rows; ++currow)
{
for(curcol = 0; curcol < num_columns; ++curcol) /* curcol = 0
needed! */
{
/* The layout of the 2D-array is linear as seen by our
program,
on a row-by-row basis. All rows have the same number of
columns.
Rows and columns are indexed starting from 0.
So if we have five colums per row and we want the element
in
the second column of the second row, we want element with
offset
six (offset 0 gives us the element at [0][0]).
offset = index_of_wanted_row * num_cols_per_row +
index_of_wanted_column
or
offset = 1 * 5 + 1 = 6 */
offset = currow * num_columns + curcol;
printf("[%i][%i] = %i\n", currow, curcol, *(ptr + offset));

Array notation would be easier to read IMHO:
printf("[%i][%i] = %i\n", currow, curcol, ptr[offset]);
Alternatively, assuming there is no risk of wanting to use some other
order, you could get rid of offset all together and use
printf("[%i][%i] = %i\n", currow, curcol, *ptr++);
}
}
}

Output when run:
$ ./foo.exe
Calling print_2d_array().
[0][0] = 0

Is this what my instructor is after?

It looks good to me. I've suggested a few style changes/improvements,
but functionally what you've done seems correct.

Also, you are to be congratulated for your posting style. You've
provided your complete program, the output you get, the original problem
statement, and your question. Feel free to ask further questions here
and good luck with your course.
 
E

Eric Lilja

Flash said:
Eric said:
Assignment: Create a 3x4 2-dimensional array of integers. Populate each
element using some non-random scheme so that no two elemens contain the
same value. Then create two functions for printing the 2D array. One
should only work for set column size, accepting only the number of rows
as an additional argument, one should accept both the number of rows
and columns as arguments.

Good, you've given us the problem statement for the program and you are
not trying to hide that it is homework. A pleasant change.
So, I came up with:
#include <stdio.h>

static void print_2d_array(int[][4], int);

I would avoid using a magic number. Use a #define instead:
#define NO_COLS 4

Good point. I prefer symbolic names.
static void print_2d_array(int[][NO_COLS], int);
static void print_2d_array_2(const int *, int, int);

As a matter of style I would prefer having the parameters names in the
prototype. Also, why only specify const in one of the two functions?

Some gnu style iirc my instructor uses. So I use it too. :)
int
main(void)
{
int array[3][4] =

You did not need to specify the number of rows. You could have used:
int array[][4] =
Or, with the change above:
int array[][NO_COLS] =
{
{0, 1, 2, 3},
{4, 5, 6, 7},
{8, 9, 10, 11},
};
int num_rows = sizeof(array) / sizeof(array[0]);
int num_cols = sizeof(array[0]) / sizeof(array[0][0]);

print_2d_array(array, num_rows);
print_2d_array_2(&array[0][0], num_rows, num_cols);

return 0;
}

/* Even if specify int array[2][4], the compiler would
happily accept our 3x4 array. Therefore we leave
that dimension empty, passing the number of rows
as an argument. However, if we try to pass a 2D-array
where the number of columns is not 4, the compiler
will complain. */
static void
print_2d_array(int array[][4], int num_rows)

Again with the magic number.
{
int row = 0;
int column = 0;

for(row = 0; row < num_rows; ++row)
for(column = 0; column < 4; ++column)

And again. Lots of changes if you want to change the number of columns!
printf("[%i][%i] = %i\n", row, column, array[row][column]);
}

static void
print_2d_array_2(const int *ptr, int num_rows, int num_columns)
{
int currow = 0;
int curcol = 0;
int offset = 0;

I would not bother initialising these here.

Well, I always like to initialize my variables.
for(; currow < num_rows; ++currow)

As a matter of style I would initialise currow in the for loop rather
than on declaration. Then it does not matter if things change.
for(currow = 0; currow < num_rows; ++currow)
{
for(curcol = 0; curcol < num_columns; ++curcol) /* curcol = 0
needed! */
{
/* The layout of the 2D-array is linear as seen by our
program,
on a row-by-row basis. All rows have the same number of
columns.
Rows and columns are indexed starting from 0.
So if we have five colums per row and we want the element
in
the second column of the second row, we want element with
offset
six (offset 0 gives us the element at [0][0]).
offset = index_of_wanted_row * num_cols_per_row +
index_of_wanted_column
or
offset = 1 * 5 + 1 = 6 */
offset = currow * num_columns + curcol;
printf("[%i][%i] = %i\n", currow, curcol, *(ptr + offset));

Array notation would be easier to read IMHO:
printf("[%i][%i] = %i\n", currow, curcol, ptr[offset]);

Right, I didn't realise I could do that. Any maybe rename offset to
index?
Alternatively, assuming there is no risk of wanting to use some other
order, you could get rid of offset all together and use
printf("[%i][%i] = %i\n", currow, curcol, *ptr++);
}
}
}

Output when run:
$ ./foo.exe
Calling print_2d_array().
[0][0] = 0

Is this what my instructor is after?

It looks good to me. I've suggested a few style changes/improvements,
but functionally what you've done seems correct.

Feels good the core program was correct! The changes you pointed out
concerns style mostly. Important to me, but a user couldn't have telled
the difference.
Also, you are to be congratulated for your posting style. You've
provided your complete program, the output you get, the original problem
statement, and your question. Feel free to ask further questions here
and good luck with your course.

Thanks alot!
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc

/ E
 
F

Flash Gordon

Eric said:
Well, I always like to initialize my variables.

Others agree, I don't if from the usage it is obvious that is will be
set before use.

offset = currow * num_columns + curcol;
printf("[%i][%i] = %i\n", currow, curcol, *(ptr + offset));
Array notation would be easier to read IMHO:
printf("[%i][%i] = %i\n", currow, curcol, ptr[offset]);

Right, I didn't realise I could do that. Any maybe rename offset to
index?

Indeed.

Feels good the core program was correct! The changes you pointed out
concerns style mostly. Important to me, but a user couldn't have telled
the difference.

Style is important too. After all, in real projects you might have to go
back to the code 10 years later and understand it. I'm not kidding here,
at work I've had to modify (Pascal) code I wrote 10 years or more
earlier due to new requirements, and based on the contracts when I left
the company others could still have to maintain it another 20 years down
the line!


One small point. Please don't quote signatures (e.g. the bit after the
"-- " in my post or the "/ E" in yours unless you are commenting on them.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top