Understanding two dimensional arrays - c

Here's the code and wondering if you can help me understand it.
/* Two dimensional array */
#include <stdio.h>
void main() {
int i, j, sum[2], mean[2];
int mark[3][2] = { { 34, 56}, { 48, 65}, { 53, 59} };
for (j = 0; j < 2; j++)
sum[j] = 0;
for (i = 0; i < 3; i++) {
for (j = 0; j < 2; j++) {
sum[j] = sum[j] + mark[i][j];
}
}
for (j = 0; j < 2; j++)
mean[j] = sum[j] / 3;
printf("Average mark in Mathematics is %d\n", mean[0]);
printf("Average mark in Chemistry is %d\n", mean[1]);
}
My understanding of it so far....
Define data types i, j, sum[2], mean[2] as integers.
Initialising the array....mark is data type int, the array should have 3 rows and 2 columns.
First for loop, j initialised at 0, condition: j has to be less than 2, update: add one onto the value of j. Sum of j = 0.
Also for 2nd loop, i initialised at 0, condition: i has to be less than 3, update: add one onto the value of i.
Similar for the next line that uses the for loop and value j.
I'm a bit confused about the syntax:
sum[j] = sum[j] + mark[i] [j]; does this mean, work out the sum of j and add it to the marks contained in the array displayed as [i] and [j].
After this is completed then similar j loop though not sure how this interacts with the previous loops.
Mean calculated and values printed to the screen.
When I've looked at the worked example...
sum[0] = 0 and sum[1] = 0, I don't really understand why sum[1] is also 0.
Firstly, i=0 and j=0,
sum[0] = sum[0] + mark [0,0]
then j=1
sum[1]=sum[1]+mark[0,1]
then
i=1, j=0
sum[0] = sum[0] + mark [1,0]
then
sum[1] = sum[1]+mark[1,1]
then i = 2, j=0
sum [0] = sum[0]+ mark[2,0]
then
sum[1] = sum[1]+ mark[2,1]
What is confusing me a bit is how the loops are interacting with each other and the values of i and j throughout.
I know that the 2d array would be in a table (that I can't seem to format here).
Would appreciate if anyone could shed some light on this.

sum[j] = sum[j] + mark[i][j]; can be simplified as sum[j] += mark[i][j];. It adds the contents of the cell at row i, column j of the 2D matrix mark to the jth element of array sum.
Accessing an element of a 2D array is written mark[i][j] in C, not mark[i, j].
Note that mark[i, j] is not a syntax error: the expression i, j is a comma expression, evaluating i, then discarding it and evaluating j. It is therefore the same as mark[j] which is not a matrix cell but a reference to the jth row of the 2D matrix.

Nope, an array is in fact a pointer (aka an address). When you define int sum[2], sum is the address of the first element of your array of two integer.
So sum is an int* or int[] (same).
Mark is an 2d array. Mark is in fact an array of array. So Mark contain addresses, and thoses addresses are the beggining of some arrays.
(In fact it can be different in the memory, but the compiler do the work).
Mark is a int**, or an address of address of int.
When you do:
for (i = 0; i < 3; i++) {
for (j = 0; j < 2; j++) {
sum[j] = sum[j] + mark[i][j];
}
}
It's like if you were saying
for each line i in the array, I want to do:
for each value j in the line, I want to do:
...;
Like this, you work on every "line" (or column, visualize the way you want), and for every "line", you work on every value.

Related

Arrays in C programming

I was working on the following 2d-array program to output this result shown in picture:
I can't seem to get the min value for the result and get it displayed in array form.
The code is below:
#include<stdio.h>
#define NUMROWS 2
#define NUMCOLS 3
//accessing elements of 2D array using pointers
int main(void){
const int table[NUMROWS][NUMCOLS]={{1,2,3},{5,6,7}};
int minvals[NUMROWS];
int i, j;
int *ptr = &table;
//accessing the elements of 2D array using ptr
printf("table values: min value\n");
for(int i=0;i<NUMROWS;i++){
for(int j=0;j<NUMCOLS;j++)
printf("%d ",*((ptr+i*NUMCOLS)+j));
printf("\n");
}
for(int i=0;i<NUMROWS;i++){
for(int j=0;j<NUMCOLS;j++)
printf("%d ",*((ptr+i*NUMCOLS)+j)<minvals[i]);
}
return 0;
}
The existence of minvals would imply that you are expected to calculate the minimum value of each 'row' of table before then moving on to printing. As it stands, had your program properly calculated the minimum values of each array, your printing would be rather out of order.
There's no need to do any tricky, manual pointer manipulation. Simple array subscription is much clearer.
Let's start simple and return to basics by looking at the way we find the minimum value in a one dimensional array, as it is the core of this problem.
To find the minimum value in an array we need a few things to start:
An array
The length of the array
An initial value to compare against
The array itself is obviously each subarray of table, and the length in this case is known to be NUMCOLS. Our initial value should either be INT_MAX (or another type-appropriate maximum constant found <limits.h>), such that every element in the array is equal to or less than our initial value, or a value from the array itself.
Often times we opt for the second option here, choosing the first element in the array as our initial value, and comparing it to the second and onward elements.
As such, finding the minimum value in a single 'row' would look like this
const int row[NUMCOLS] = { 9, 2, 5 };
int min = row[0];
for (int i = 1; i < NUMCOLS; i++)
if (row[i] < min)
min = row[i];
but since we want to find and record the minimum value of each 'row' in table, we're going to use a nested loop. Instead of the min variable from before, we store each value in the associated index of our minvals array.
for (i = 0; i < NUMROWS; i++) {
minvals[i] = table[i][0];
for (j = 1; j < NUMCOLS; j++)
if (table[i][j] < minvals[i])
minvals[i] = table[i][j];
}
When it comes time to print, we're going to repeat our nested loop. Our inner loop prints each element of each 'row' of table, and we end each iteration of the outer loop by printing the value found in minvals with the same index of our 'row'.
for (i = 0; i < NUMROWS; i++) {
for (j = 0; j < NUMCOLS; j++)
printf("%6d", table[i][j]);
printf(":%6d\n", minvals[i]);
}
Here's a working example.
#include <stdio.h>
#define NUMROWS 2
#define NUMCOLS 3
int main(void) {
const int table[NUMROWS][NUMCOLS] = {
{ 9, 2, 5 },
{ 3, -4, -12 }
};
int minvals[NUMROWS];
int i, j;
for (i = 0; i < NUMROWS; i++) {
minvals[i] = table[i][0];
for (j = 1; j < NUMCOLS; j++)
if (table[i][j] < minvals[i])
minvals[i] = table[i][j];
}
puts("Table value: minimum values");
for (i = 0; i < NUMROWS; i++) {
for (j = 0; j < NUMCOLS; j++)
printf("%6d", table[i][j]);
printf(":%6d\n", minvals[i]);
}
}
A good further exercise for you would be to compose the logic of the inner loop for finding minimum values into a more generic function. Its function signature would look like
int min(int *array, size_t length);
allowing it to work on arrays of varying sizes. Then our outer loop could be as simple as:
for (i = 0; i < NUMROWS; i++)
minvals[i] = min(table[i], NUMCOLS);
The line
int *ptr = &table;
is wrong, because &table is of type int (*)[2][3] (i.e. a pointer to the entire table), whereas ptr is a pointer to a single element. Also, your pointer is non-const, so it cannot point be made to point into a const array.
If you want ptr to point to a single int value, then you should declare it the following way:
const int *ptr = &table[0][0];
Also, you are reading the contents of the array minvals, although that array contains uninitialized data. This does not make sense and causes undefined behavior.
Instead of doing complex pointer arithmetic with the expression
*((ptr+i*NUMCOLS)+j))
you can simply write the following:
table[i][j]
That way, you do not need the pointer ptr and your code is simpler.

A for loop in C using an array

I've created an array named a that can hold 100 double values,
double a[100];
I set the first element of the array a to NUM, which is a symbolic constant defined early in my code.
a[0] = NUM
I'm curious as to how I would write a for loop that sets each remaining value of a to the value of the preceding element plus 0.1. For example, the second element in the array is the first plus 0.1. I've tried doing
for(i=1; i<=99; i=+0.1)
But I think something is wrong with my initialization of i
Use i to index the array, not to store the value you should put on the array. Remember you can use expressions to access the array, like a[i - 1]
for (i = 1; i < 100; i++)
a[i] = a[i - 1] + 0.1;
int i;
for(i = 0; i < 100; i++)
a[i] = NUM + 0.1 * i;
dont forget to tell the type int !
int i = 0;
for(i = 0; i < 100; i++){
if (i == 0)
a[i] = NUM;
else
a[i] = a[i - 1] + .1;
}
Your array definition includes the step. So your array would run about 1000 times, at 1, 1.1, 1.2, but a[1.1] isn't a valid index of your array. Use i to index the array, and then retrieve the previous value to set the next.
From your question I can understand that this is one of your first program in C/C++, so I think that you need to start from basic things and learn how to do it properly, before doing it elegantly.
http://ideone.com/RGZgXL
for(i = 0; i < ARRAY_SIZE; i++) {
if(i == 0) { // if we are on the first element, set it to NUM
array[i] = NUM;
} else { // otherwise make the sum
array[i] = array[i-1] + STEP;
}
}
In the link you'll find the code and some comments that I hope will help you in understanding it.
Cheers

cyclic permutation in O(1) space and O(n) time

I saw an interview question which asked to
Interchange arr[i] and i for i=[0,n-1]
EXAMPLE :
input : 1 2 4 5 3 0
answer :5 0 1 4 2 3
explaination : a[1]=2 in input , so a[2]=1 in answer so on
I attempted this but not getting correct answer.
what i am able to do is : for a pair of numbers p and q , a[p]=q and a[q]=p .
any thoughts how to improve it are welcome.
FOR(j,0,n-1)
{
i=j;
do{
temp=a[i];
next=a[temp];
a[temp]=i;
i=next;
}while(i>j);
}
print_array(a,i,n);
It would be easier for me to to understand your answer if it contains a pseudocode with some explaination.
EDIT : I came to knpw it is cyclic permutation so changed the question title.
Below is what I came up with (Java code).
For each value x in a, it sets a[x] to x, and sets x to the overridden value (to be used for a[a[x]]), and repeats until it gets back to the original x.
I use negative values as a flag to indicate that the value's already been processed.
Running time:
Since it only processes each value once, the running time is O(n).
Code:
int[] a = {1,2,4,5,3,0};
for (int i = 0; i < a.length; i++)
{
if (a[i] < 0)
continue;
int j = a[i];
int last = i;
do
{
int temp = a[j];
a[j] = -last-1;
last = j;
j = temp;
}
while (i != j);
a[j] = -last-1;
}
for (int i = 0; i < a.length; i++)
a[i] = -a[i]-1;
System.out.println(Arrays.toString(a));
Here's my suggestion, O(n) time, O(1) space:
void OrderArray(int[] A)
{
int X = A.Max() + 1;
for (int i = 0; i < A.Length; i++)
A[i] *= X;
for (int i = 0; i < A.Length; i++)
A[A[i] / X] += i;
for (int i = 0; i < A.Length; i++)
A[i] = A[i] % X;
}
A short explanation:
We use X as a basic unit for values in the original array (we multiply each value in the original array by X, which is larger than any number in A- basically the length of A + 1). so at any point we can retrieve the number that was in a certain cell of the original array by array by doing A[i] / X, as long as we didn't add more than X to that cell.
This lets us have two layers of values, where A[i] % X represents the value of the cell after the ordering. these two layers don't intersect through the process.
When we finished, we clean A from the original values multiplied by X by performing A[i] = A[i] % X.
Hopes that's clean enough.
Perhaps it is possible by using the images of the input permutation as indices:
void inverse( unsigned int* input, unsigned int* output, unsigned int n )
{
for ( unsigned int i = 0; i < n; i++ )
output[ input[ i ] ] = i;
}

Iterate ALL the elements of a circular 2D array exactly once given a random starting element

We are given a 2-dimensional array A[n,m] with n rows and m columns and an element of that array chosen at random R.
Think of the array as being circular in that when we visit A[n-1, m-1] the next element we visit would be A[0, 0].
Starting with element R, we want to visit each element exactly once and call function foo() before moving to the next element.
The following is my first implementation but there is a bug. The bug being that if we start at row x somewhere between 0 and n-1, we will not visit element from 0 to x-1 in that column.
// Init - pretend rand() always returns valid index in range
curr_row = rand();
curr_col = rand();
// Look at each column once
for (int i = 0; i < m; ++i)
{
for (; curr_row < n; ++curr_row)
{
foo(A[curr_row][curr_col]);
}
curr_row = 0;
curr_col = (curr_col + 1) % m;
}
What is a clean way to do this traversal such that we meet the above requirements?
Just move to the next index, and check whether you are back at the start, in which case, stop:
// should be something that guarantees in-range indices
curr_row = rand();
curr_col = rand();
int i = curr_row, j = curr_col;
do {
foo(A[i][j]);
++j;
if (j == n) {
j = 0;
++i;
if (i == m) {
i = 0;
}
}
}while(i != curr_row || j != curr_col);
This doesn't do what your implementation does, but what the question title asks for.
quite rusty with c , but it should be the same:
// Init - pretend rand() always returns valid index in range
curr_row = rand();
curr_col = rand();
//first row
for(int j=curr_col;j<m;++j)
foo(A[curr_row][j]);
//rest of the rows
for(int i=(curr_row+1)%n;i!=curr_row;i=(i+1)%n)
for(int j=0;j<m;++j)
foo(A[i][j]);
//first row , going over missed cells
for(int j=0;j<curr_col;++j)
foo(A[curr_row][j]);
if you care a lot about performance , you can also divide the second loop so that there won't be a "%" at all .
another alternative , since C has 2d arrays in a simple array:
// Init - pretend rand() always returns valid index in range
curr_row = rand();
curr_col = rand();
int start=curr_row*m+curr_col;
int maxCell=n*m;
int end=(start-1)%maxCell;
for(int i=start;i!=end;i=(i+1)%maxCell)
foo(A[i]);
foo(A[end]);
could have a tiny math bug here and there ,but the idea is ok.
A[curr_row, curr_col] is not the syntax used to access a member of a multidimensional array; instead, you want A[curr_row][curr_col], assuming the array was declared correctly. A[curr_row, curr_col] will invoke the comma operator, which effectively computes the first value, then throws it away and calculates the second value, then indexes the array with that value.

C: Problem with initializing array values to zero

I'm trying to construct the following 14*14 array i C: [I 0; 0 -I], that is a 7*7 identity matrix upper left, minus the identity lower right and zeros otherwise.
This is the method:
#define DIM 7
double S[2*DIM][2*DIM];
for(i = 0; i < DIM; i++){
for(j = 0; j < DIM; j++){
if(i == j){
S[i][j] = 1.0;
S[i+7][j+7] = -1.0;
}
else{
S[i][j] = 0.0;
}
}
}
This works fine for all the diagonal elements; however, some elements of the array get initialized to crazy values; for example, 13,6 gets initialized to
68111186113812079535019899599437200576833320031036694798491976301968333351950125611739840800974137748034248687763243996679617222196278187875968953700681881752083957666277350377710107236511681624408064.000000
This seems to be happening consistently (at least thrice) to entries 11,13, 12,9, 12,10, 13,12 and 13,6.
Can anybody tell me what's at play here or provide an alternative solution?
Cheers!
EDIT: The weird entries aren't consistent.
EDIT2: Typo: 13,12, not 13,15
Your loop only covers the upper left quadrant, so the off-diagonal elements in the other quadrants are not initialized and contain garbage. Your loop should go up to 2*DIM for each dimension, so that the off-diagonal elements are zeroed, and then your conditional for the diagonal elements should just be a little more complex to decide which value to set the diagonal element to.
Note that [13, 15] is entirely outside of this array!
You can initialize the whole array with zeros, then set only the diagonal
double S[2*DIM][2*DIM] = {0};
for (i = 0; i < DIM; i++) {
s[i][i] = 1;
s[i + DIM][i + DIM] = -1;
}
You are never writing to s[i][j] for i != j and i >= DIM or j >= DIM. If your array has automatic storage (is "local") it contains arbitrary init values.
I would say most of the elements that are outside 7x7 will not be initialized at all unless i == j (diagonal elements).
What do you want to initialize them to?
That's because your not initializing those elements. Here is some better code:
#define DIM 14
double S[DIM][DIM];
for (i = 0; i < DIM; i++) {
for (j = 0; j < DIM; j++) {
if (i == j) {
if (i < 7) {
S[i][j] = 1.0;
} else {
S[i][j] = -1.0;
}
} else {
S[i][j] = 0.0;
}
}
}
You never initialize values with an i or j between DIM + 1 and 2*DIM. So when you look at a value stored in one of those positions, you see whatever was there before that space was accessed by your matrix.

Resources