How should you add elements to a multi dimensional array? (In C) - c

I'm working on a table football cup program (in C), where I have 16 people facing off to get to the final. I'm having trouble putting elements into the different elements of the array (which has sort of stopped my progress until I figure it out). I've searched on the internet (not extensively) about pointers, but I can't find anything on multi dimensional arrays.
I have 8 games, each with 2 participants, who each play 5 matches against each other. Hopefully that means I define the array as int lastSixteen[8][2][5]. All participants have a unique ID
Assuming I have declared my arrays correctly... On to the main question.
This is what I'm currently doing:
int i;
for(i=0; i<MAX_PLAYERS/2;i++){
roundOne[i] = i;
}
I want to set the first dimension of my array to be the numbers 1 through 8 incl. but I run into 'error: incompatible types in assignment'.
I tried setting the line with the assignment to be roundOne[i][][] = i; but as I expected, that didn't work either.
Later on in the program I need to set the second set of numbers to be the games participants to be the 16 participants (to keep it simple I'm doing it in ascending numerical order) so Game 1 is Player 1 and Player 2, Game 2 is Player 3 and 4 etc.
for(i=0; i<16; i++){
if(i % 2 != 0){
roundOne[(MAX_PLAYERS/2)-1][0] = i; /* puts 1,3,5,7,9,11,13,15 */
}
else{
roundOne[(MAX_PLAYERS/2)-1][1] = i; /* puts 2,4,6,8,10,12,14,16 */
}
}
I'm assuming the second part will be fixed by the answer to the first part since they return the same error, but I included it because I don't know.
A sample of code that has a minimal, Complete, and Verifiable example.
#include <stdio.h>
#define MAX_PLAYERS 16
int main(void){
int i;
int roundOne[8][2][5];
/* seeded in numerical order.*/
for(i=0; i<MAX_PLAYERS/2;i++){
roundOne[i] = i;
}
for(i=0; i<MAX_PLAYERS; i++){
if(i % 2 != 0){
roundOne[(MAX_PLAYERS/2)-1][0] = i;
}
else{
roundOne[(MAX_PLAYERS/2)-1][1] = i;
}
}
return 0;
}
Thanks in Advance,
Rinslep

You can't just use a multi dimensional array - it doesn't do what you want. And here is why: Lets say you have 8 games and 2 players (forget that there are 5 matches for a second) That means your multi dimensional array would have 16 spots:
Player
0 1
+---+---+
0 | | |
+---+---+
1 | | |
+---+---+
2 | | |
G +---+---+
a 3 | | |
m +---+---+
e 4 | | |
+---+---+
5 | | |
+---+---+
6 | | |
+---+---+
7 | | |
+---+---+
Now you want to put the game number in there AND you want to put the unique player IDs in there AND you might want to put other stuff in there (like who won and the score)? How are you going to do that? There are a couple choices:
The game number is the index into the array - not a value you store in the array. Now you can store the palyer IDs for each game in the array. But this still doesn't address storing other stuff (like who won and the score)
If the game number needs to be stored in the array (or other things like who won and the score) you will need to store more than one thing in the array so the array cannot hold ints - you need an array of structures.
It is hard to guess what the right data structure is because it depends on what your program is going to do, but I think I would do this:
typedef struct match
{
int score[2]; /* index 0 is player 1, index 1 is player 2 */
int winner; /* index into the player and score arrays (either 0 or 1) */
};
typedef struct game
{
int players[2]; /* index 0 is player 1, index 1 is player 2 */
match matches[5];
};
game games[8];
Now, the the game number (1-8) is just the index to games plus 1, the match number (1-5) is just the index to matches plus 1 and if you want to make unique player numbers that go from 1-16 you can do this:
i=1;
for(int g=0;g<8;g++)
for(int p=0;p<1;p++)
games[g].player[p]=i++;

You need to initialize the array with dynamic allocation.
How do I work with dynamic multi-dimensional arrays in C?
Think of it this way
A = [
[B],
[C],
[D],
...
]
So lets say we need an array round with 10 rows and each row has 20 columns. They will all be filled with integer values.
Option One - Dynamically Allocating
Define the number of buckets the array will have. We are taking the size of the pointer because each bucket will container a pointer/array that represents the inner array.
int** round;
round = malloc(10 * sizeof(int*))
Now that we have allocated the space for the buckets, go through and give space for the points. This one is just a normal integer so we take the sizeof(int).
for (int i = 0; i < 10; i++) {
round[i] = malloc(20* sizeof(int))
}
Option Two
We can define the size of the multidimensional array in a bit of an easier way. We know the number of rows and the number of columns. So alternatively we can allocate the space like this:
int* round;
round = malloc (10 * 20 * sizeof(int));
Both of these will produce the array round[10][20] with memory allocated for it. With C you can't add elements to an array on the fly if the size of the array is unknown, in my experience linked lists are better for this.
Edit: I see that you updated the question, this code can be used with a 3D array also. You can easily use option two as 3D like round = malloc(x * y * z * sizeof(int)), where x, y, and z are equal to the dimensional values. You can also modify option one to work with this also.

Related

How do I access the memory using pointers for a multidimensional array?

I have been learning memory allocation and pointers lately, and I made this program which will ask the user to input the dimensions of a matrix and enter it's elements, after which it displays the elements in a matrix format. Here's the code that I've typed.
#include"stdio.h"
#include"stdlib.h"
int *minput();
int *minput(int x,int y)
{
int *M;
M=(int*)malloc(x*y*sizeof(int));
for(int i=0;i<=(x-1);i++)
{
for(int j=0;j<=(y-1);j++)
{
printf("A(%d,%d)=",i+1,j+1);
scanf("%d",(M+i+j));
}
}
return M;
}
int main()
{
int *A,a,b;
printf("Matrix is (m*n)\n\n");
printf("m=");
scanf("%d",&a);
printf("n=");
scanf("%d",&b);
A=minput(a,b);
printf("\n");
for(int k=0;k<=(a-1);k++)
{
for(int l=0;l<=(b-1);l++)
{
printf("%d ",*(A+k+l));
}
printf("\n");
}
free(A);
return 0;
}
However when I gave my inputs, I got this:
Matrix is (m*n)
m=3
n=3
A(1,1)=1
A(1,2)=2
A(1,3)=3
A(2,1)=4
A(2,2)=5
A(2,3)=6
A(3,1)=7
A(3,2)=8
A(3,3)=9
1 4 7
4 7 8
7 8 9
What's wrong? Amn't I supposed to get
1 2 3
4 5 6
7 8 9
Is there anything I had made wrong in my code?
You get incorrect output because *(A+k+l) is not the right way of accessing matrix element at matrix[k][l].
For addressing a matrix stored as a "flat" array you need to multiply the value of one of the indexes by the size of the opposite dimension. Depending on which index you multiply you get either a row-major order or a column-major order.
You need to apply the same fix to (M+i+j) inside minput function.
// Input
scanf("%d",(M+y*i+j));
...
// Output
printf("%d ",*(A+b*k+l));
The idea behind multiplying k by b is to make k "count faster". For each increment of k by 1 you need to skip an entire row of b elements. In your three-column matrix example, if you would like to access elements at A[k][0] (the initial column) of your matrix for each row, your index would count by three: 0, 3, 6. This is accomplished by multiplying k by b. The rest is the same as the usual pointer arithmetic: *(A+b*k+l) is equivalent to A[b*k+l].
Demo.
Lets take a close look at one of your loops (I use the input loop, but the error is in the output loop as well):
for(int i=0;i<=(x-1);i++)
{
for(int j=0;j<=(y-1);j++)
{
printf("A(%d,%d)=",i+1,j+1);
scanf("%d",(M+i+j));
}
}
The first iteration of the outer loop, i is zero. Then the inner loop runs, and we read into (in turn) M+0+0, M+0+1 and M+0+2.
Then we run the second iteration of the outer loop, where the inner loop will read into M+1+0, M+1+1 and M+1+2.
In these two iterations of the outer loop you will read into M+1 and M+2 twice. That's because M+0+1 and M+1+0 are the same element.
To fix this, lets take a look at your "matrix" as it is in memory
+---+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
+---+---+---+---+---+---+---+---+---+
The numbers inside are the indexes. Now, 0, 1 and 2 is the first row. 3, 4 and 5 is the second. And 6, 7 and 8 is the last.
From this we can see that to get to the next line, we have to add the number of columns.
From this we get the formula line * number_of_columns + column to get the index.
Putting it in place, your input loop could look like
for(int i=0;i<x;i++)
{
for(int j=0;j<y;j++)
{
printf("A(%d,%d)=",i+1,j+1);
scanf("%d",M+i*y+j);
}
}
To choose the address in which to write a value, you use:
M+i+j
Let's try that for a few values of (i,j):
0,0 -> M + 0
0,1 -> M + 1
0,2 -> M + 2 // So far so good.
1,0 -> M + 1 // not right
1,1 -> M + 2 // not right
... etc.
You want M + (i * x) + j. For x == 3:
0,0 -> M + 0
0,1 -> M + 1
0,2 -> M + 2
1,0 -> M + 3
1,1 -> M + 4
... etc.
The same goes for the pointer arithmetic when reading from the same memory.
Furthermore, since the pointer just goes up by one each time, you could get the same behaviour with:
int *m = M;
for(int i=0;i<x;i++)
{
for(int j=0;j<=(y-1);j++)
{
printf("A(%d,%d)=",i+1,j+1);
scanf("%d",m);
m++;
}
}
Or even:
for(int i=0; i<x*y; i++) {
printf("A(%d,%d)=", i/3, i%3);
scanf("%d", M + i);
}
Other points:
In one method you use variables x,y,i,j, and in another you use a,b,k,l. I assume you've done this because you don't want to overwrite one with the other. But because of scope, that's not a factor. x is local to the function minput() -- you can have another x in main() and they will be completely independent of one another. Use x,y,i,j in both places, because they are the "sensible" names for dimensions and loop counters.
for(i=0; i<x; i++) is the conventional way of looping x times. Your i<=(x-1) is equivalent but messy and confusing.
Casting the result of malloc() is discouraged nowadays. Do I cast the result of malloc?
int *M = malloc(x*y*sizeof(int));

function to zero array elements

I wrote this code that check suduko answers and for some reason my the array which I sum the squares of the suduko into is all zeros in the functions I zero it in, but when I use it in my check function it isn't all zeros
if i move the exact same code of my array zeroing function to my other function and run it it works.
(i am using c99, dont know if it matters)
Any ideas?
int squareSum[5][5];
//set array elements to zero
setArrayToZero(squareSize, squareSize, squareSum);
/*for(int i = 0; i<squareSize; i++){
for(int j = 0; j<squareSize; j++)
squareSum[i][j] = 0;
}*/
printf("%d, %d\n%d, %d\n\n", squareSum[0][0], squareSum[0][1], squareSum[1][0], squareSum[1][1]);
this is the array is case squareSize is two
if i add the for in the comments in, the array isall zeros, and as you can see below its the exact same as the function i call.
void setArrayToZero(int rows, int columns, int array[][columns]){
for(int i = 0; i<rows; i++)
for(int j = 0; j<columns; j++)
array[i][j] = 0;\\if i print the array in function its all zeros.
p.s
i know i am using only part of the array, its an assignment from the university and we are not allowed to use malloc so i am creating the array at thier max size - 25.
thank you in advance.
full c file:
https://drive.google.com/open?id=1L00L3lvMYNcaz2SswEBnmi9KO-79oaHg
all the print functions, are part of the demand for the course (for auto checking)
A reference to an object of type array-of-T which appears in an
expression decays (with three exceptions) into a pointer to its first
element; the type of the resultant pointer is pointer-to-T.
So that means in this case also (this is not one of those 3 exceptions) your passed array will decay into pointers and now you change to the array by accessing the address, that's why it will be retained in the callee function.
You are doing it the right way. The problem is not with passing or anything. Maybe you are accessing it wrong or maybe you didn't initialize it properly. But there is nothing wrong with the zeroing out.
And for further information everything is pass by value in C. There is nothing called pass by reference in C. The pointer workings makes us think that there is something called pass by reference in C but that's not the case, here also pointer variables are copied into some local variable in the called function. but as we have those addresses in the called function and we access them and make changes - they retain in callee function.
After OP posted the sample code
Apaprt from the overly complicated sudoku checking logic there is much more going wrong.
I will just mention the printing part.
In C elements of 2d-arrays are stored sequentially. When we pass the 2d array to the function we need to specify the column size so that we can determine the correct element.
Suppose you want to access a[4][7] in 10x13 array. The element would be at the address &a[0][0]+4*13+7. That's why the column part is passed as an argument.
Now what you did :
int squareSum[5][5], rowColSum[25][2];
//set arrays elements to zero
setArrayToZero(size, 2, rowColSum);
setArrayToZero(squareSize, squareSize, squareSum);
The first one is alright. As there are 2 columns. But what about the second one?
here you are telling the function that you are passing an array with column size = 2 but that is not the case. It is still the 2d array with 5 columns.
That's where you had the problem. Suppose you initialize the array with 10,21,34,14
Suppose grid is 5x5 array (in your case it's 25x25)
grid[5][5] array
And you do this
for(int i = 0; i<squareSize; i++)
for(int j = 0; j<squareSize; j++)
scanf("%d",&grid[i][j]);
/*
Input is 13 17 19 23
*/
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
/ \ \ / \ \
13 17 19 23
Now you access it like this
You pass it to the function with this call print2dArray(int row, int col, int g[][col])
You call like this `print2dArray(2,2,grid);``
...
for(int i = 0; i<row; i++)
for(int j = 0; j<col; j++)
printf("%d",&grid[i][j]);
Now you will print these elements (i) : denotes the order
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
/ \ \ ^ ^ / \ \
13 17 | | 19 23
(1) (2) (3) (4)
Similarly, those were uninitialized in your case. That's why you got those weird results. You were initializing some elements of the 2d array to 0 but when you are reading the array then you were accessing some different elements. That's why the wrong result.
Solution for this:
Call int correctSum = inputGrid(squareSize, 25, grid); Note that it should be squareSize. Accordingly change the storage of digitsCounter in inputGrid.
The function signature for inputGrid would be inputGrid(size, col, grid[][col]);
Same when calling the
setArrayToZero(size, 2, rowColSum); and
setArrayToZero(squareSize, 5, squareSum);
I simply didn't check the logic. The answer deals with explaining the printing behavior of the 2d array.

"C" i couldnt understand how i can add two matrises

I'm a begginer about c and i need help about it please help
{
int matris[2][2];
for(int i=0;i<2;i++)
{
for(int j=0;j<4;j++)
{
printf("Sayi giriniz: "); scanf("%d",&matris[i][j]);
}
}
for(int i=0;i<3;i++)
{
for(int j=0;j<2;j++)
{
printf("%d ",matris[i][j]);
}
printf("\n");
}
}
As a beginner, you need to realize that programming is nothing more than problem-solving, well there is the bit about expressing the answer in a programming language.
Doing matrix addition -- how do you do it, how would a mathematician define it? Arnaldo has given you the answer to this, $A + B = C$ where $c_{ij} = a_{ij} + b_{ij}$. So already, this starts to set some restrictions on the two matrices that your are working with, notably they have to have the same number of rows and columns.
Representation of matrices -- ok, now that you know how to add to matrices, you need to figure out how you are going to represent a matrix in your program. Computer memory is a one-dimensional array of storage units, so we need to map our two dimensional structure onto this one-dimensional array. There are two ways of doing this. The first is row major which means that we write the first row to memory, then the second row and so on. The second is column major which means that we write the first column to memory and then the second row.
Consider the following 2x3 matrix:
| a b c |
| d e f |
in row-major form, it would be laid out in memory as:
+---+---+---+---+---+---+
| a | b | c | d | e | f |
+---+---+---+---+---+---+
and in column-major form, in would be laid out in memory as:
+---+---+---+---+---+---+
| a | d | b | e | c | f |
+---+---+---+---+---+---+
Remember that computer science is zero based, so where a mathematician would designate the first element in the first row as a_{11}, we will be using zero based indicies so we will designate it as a_{00}.
Most modern program languages use row-major form to store two dimensional arrays (or in this discussion matrices). So what you might ask? Well, because we are mapping a two dimensional array to a one dimensional array, and all we really know about the one dimensional array is its starting point in memory, we need to be able to change the pair (row, col) into a single index. You should convince yourself that the following equation is correct, assuming that nRow and nCol are the number of rows and columns in the matrix.
index = nCol * row + col
So, now write some code to add to matrices together. In pseudo-code form this would be:
A <-- read in first n-by-m matrix
B <-- read in second n-by-m matrix
C <-- initialize a n-by-m matrix to all zero elements.
for(r = 0; r < nRow; r++)
for(c = 0; c < nCol; c++)
C[r][c] = A[r][c] + B[r][c]
print C
It is an implementation detail to decide if you want to use fix sized matrices, i.e. 'A[2][2]', or potentially use a dynamically allocated matrix, i.e. 'A = malloc(nRow * nCol * sizeof(int));' (assuming we are storing integers). This will determine exactly how the addition line in the above pseudo-code would be written.
Hope this helps, and kinda show you how to approach problems like this.
Don't be afraid to ask additional questions if you get stuck on attempting the implementation.
Best of Luck,
T
I don't fully understand what your question is, but I can definately show you how to add two matricies of the same length elementwise, if that's what you're looking for.
#include <stdio>;
int main()
{
//this part is declaring the two arrays you want to add,
//and the array you want to store the result in.
int arrayA[3];
int arrayB[3];
int result[3];
//this part is just initializing the data in the array
arrayA[0] = 1;
arrayA[1] = 2;
arrayA[2] = 3;
arrayB[0] = 5;
arrayB[1] = 6;
arrayB[2] = 7;
//loops from 0 to 2, and adds the nth element of arrayA and
// arrayB to store in result
for(int n =0; n < 3; n++)
{
result[n] = arrayA[n] + arrayB[n];
}
//at this point, result is the addition of your arrays.
//You can print it, or whatever it is you wanted to do with it.
return 0;
}
There are many different things that could be 'adding matricies', but this is one of them.
However, the code you submitted looks like you're trying to store numbers from the keyboard into a 2D array. You're on the right track there, but on your first nested for loop your inner loop goes too far, so it's going outside of the array bounds. Try more liek this:
int matris[2][2];
for(int i=0;i<2;i++)
{
//you had j<4 here. That will put you in invalid memory!
for(int j=0;j<2;j++)
{
printf("Sayi giriniz: "); scanf("%d",&matris[i][j]);
}
}
//you had i<3 here. That will also put you in invalid memory.
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
printf("%d ",matris[i][j]);
}
printf("\n");
}
I hope I've addressed whatever question you were going for.
İyi şanslar!

2d dynamic array (in C) with specific row number and different column size in each row

How do I make a 2d dynamic array (in C) with specific row number and different column size in each row?
For example:
This is an array (3=rows)
|1 | 4 | 5 |
|3 |
|6 | 2 |
1st row - 3 columns
2nd row - 1 column
3rd row - 2 columns
I want my program while running to ask the user for every row to give the number of cols.
How do I make an array like this?
If you want something dynamic and don't care about constant access time, you can create an array of linked list, otherwise you have no choice but to allocate some space with sufficient memory and keep it updated with realloc.
What you will probably want to is to use a pointer pointer and allocate sufficient memory for each row then. Example:
int ** array = calloc(sizeof(*array), NUMROWS);
array[0] = calloc(sizeof(**array), 3); // 3 fields
array[1] = calloc(sizeof(**array), 1); // 1 field
array[2] = calloc(sizeof(**array), 2); // 2 fields
You need an array of pointers:
int *ptr_array[3];
Then for each row, you need to allocation memory:
int map_array[3] = {3,1,2}
int i;
for(i = 0; i < 3; i++){
ptr_array[i] = malloc(sizeof(int)*map_array[i]);
}
If you need the number of row to be dynamic, you should do the first part as:
int **ptr_ptr_array;
(*ptr_ptr_array) = malloc(sizeof(int *)*3);
Good luck with recycling the memory.

Traverse through layers of array using pointer to layer of array

|--------|
// / |4 4 4 |
// |--------| 4 |
// / |3 3 3 | 4 |
// |---------|3 | |
// / | 2 2 2 |3 | /
// |---------|2 |__|
// | 1 1 1 |2 | /
// | 1 1 1 |__|
// | 1 1 1 | /
// |_________|
double arr[4][3][3] = {{1,1,1,1,1,1,1,1,1},{2,2,2,2,2,2,2,2,2},{3,3,3,3,3,3,3,3,3},{4,4,4,4,4,4,4,4,4}};
I consider that this array consists of 4 layers.
I want to create pointer to layer of array and traverse through layers of that array using pointer.
I try :
double (*pp1)[sizeof(arr[0]) / sizeof(ar[0][0][0])];
pp1 = arr[0];
and get error from intelIsense:
value of type (double (*)(3) can`t be assigned to double(*)(9)
So if you do:
int i;
double arr[4][3][3] = {{1,1,1,1,1,1,1,1,1},{2,2,2,2,2,2,2,2,2},
{3,3,3,3,3,3,3,3,3},{4,4,4,4,4,4,4,4,4}};
double (*pp3)[3][3];
pp3 = arr;
for (i = 0; i <= 3; i++)
{ printf("pp3 + %d is %f \n", i, ***(pp3 + i));
}
Then you get the desired behavior. The problem with your code is that, just as the compiler is telling you, you are trying to assign a pointer to an array of 9 double (double (*pp1)[sizeof(arr[0] / sizeof(arr[0][0][0])] evaluates to double (*pp1)[9] ), but you need a pointer to an array of 3 of array of 3, which is what you declared with double arr[4][3][3]. From my tests, gcc will accept the double (*pp1)[9] with a compiler warning, which is what I tried to get at in my comment below. Hope that clears things up.
If you want to keep this general, then what you really want is double (*pp3)[sizeof(arr[0]) / sizeof(arr[0][0])][sizeof(arr[0][0]) / sizeof(arr[0][0][0])], which is a bloody nightmare.
EDIT: Forgot a dereference... Should've copy/pasted haha. Also added explanation about the question's code behavior. Fixed as per comments.
Why not simply get the direction of the first element of a given layer?
double *pp1 = &ar[0][0][0];
double *pp2 = &ar[1][0][0];
/* and so on */
While trying to figure out this issue i got some results.
I find out that the following statements raises no errors from compiler
double arr[4][4][9];
double (*pp3)[9];
pp3 = arr[0];
So, is it right to deduce from code above that pointer can be assigned to array only in case if number of elements to which it points is equall to the smallest dimension of array?
update:
I think that pointer can be created on the smallest layer of array only.
Can somebody explain this?

Resources