Cannot print out the values of a dynamic 2D array of structs - c

This program is supposed to ask the user for two values, then generate and print a table using the two values as the number of rows and columns respectively. Each cell of the table has two values, denoted as cellX and cellY. The x-value and y-value of each cell of the table is 1 and 2 respectively.
So in short, it's a dynamic 2D array of structs. The problem is, the program seems to be skipping the last for loop, so it's not printing the contents of the array of structs. No errors were generated.
#include <stdio.h>
#include <stdlib.h>
typedef struct // one cell of a table holding two int values
{
int *cellX;
int *cellY;
} Table;
int main()
{
char dump;
int row, col, y, x;
printf("Enter number of rows and columns (r,c): ");
scanf("%d%c%d", &row, &dump, &col);
Table **grid;
grid = (Table **)malloc(row * col * sizeof(Table));
for (y = 0; y < row; y++) // assigns values to the table
{
for (x = 0; x < col; x++)
{
*grid[x][y].cellX = 1; // all x-values will be 1
*grid[x][y].cellY = 2; // all y-values will be 2
}
}
for (y = 0; y < row; y++) // displays the table
{
for (x = 0; x < col; x++)
{
printf("%d, %d\t", *grid[x][y].cellX, *grid[x][y].cellY);
}
}
free(grid);
return 0;
}

grid = (Table **)malloc(row * col * sizeof(Table));
This is not how you allocate a 2D array, Table** is an array of pointers (Table*) to an array of Table, so you have to allocate all those separate sub-arrays.
Table **grid = malloc(sizeof(*grid) * row);
for (int y = 0; y < row; ++y)
grid[y] = malloc(sizeof(*grid[0]) * col);
And then remember to free all those arrays as well.
In many cases this is not really wanted, so you can make a 1D array and then index it as-if 2D. For example with array[y * width + x].
Table *grid = malloc(sizeof(*grid) * row * col);
for (y = 0; y < row; y++) // assigns values to the table
{
for (x = 0; x < col; x++)
{
grid[y * col + x].cellX = 1; // all x-values will be 1
grid[y * col + x].cellY = 2; // all y-values will be 2
}
}
Also your struct contains pointers, but I don't really see why, and you never allocated them. Just store values.
typedef struct
{
int cellX;
int cellY;
} Table;

Related

adding an array table (bidimensional) to a List (Java)

I am doing a Bingo program and now, the section of the bingoCard, to do this I am using an a bidimensional array but I need to shuffle the numbers of each row. For the shuffle part I saw that the setList is much better, but I don't know how to relate the List with the array here is a part of the code:
public static Integer[][] bingoCard(){
Integer [][] bingoCard= new Integer[3][9];
for(int x =0; x<bingoCard.length; x++){
for(int y =0; y<bingoCard[x].length; y++){
if(y <5){
int random = (int)(Math.random()*90+1);
System.out.print((bingoCard[0][y] = random) + " ");
}
if(y >4 && y <9){
System.out.print((bingoCard[0][y] = 0) + " ");
}
}
System.out.println();
}
List<Integer[]> list =Arrays.asList(bingoCard);
Collections.shuffle(list);
list.toArray(bingoCard);
return bingoCard;
}
Any question please ask me!!
Thanks.
In your code, when you do List<Integer[]> list = Arrays.asList(bingoCard), you are converting the outer array into a List and then shuffling its contents. The effect of this will be that the order of the 3 rows are shuffled rather than the contents of the 3 rows which is what you want. You could achieve this by shuffling the contents of each row within your for-loop. Or, after constructing the 2D array, you can loop over each row again and shuffle them.
Also, you have another small bug. When you assign the value, you are doing bingoCard[0][y] = ... but it should be bingoCard[x][y]. Otherwise, you are only assigning the first row new values on each iteration.
I would recommend not converting the array to a List just to shuffle it and then converting it back. Instead, you can use Random.nextInt to pick indexes of the array to assign. That would look something like this:
public static Integer[][] bingoCard(){
int numRows = 3;
int numCols = 9;
int randomNumbersPerRow = 5;
int randomNumberBound = 90;
Random random = new Random();
Integer[][] bingoCard = new Integer[numRows][numCols];
for (int row = 0; row < numRows; row++) {
for (int col = 0; col < numCols; col++) {
// Initialize all spots to 0
bingoCard[row][col] = 0;
}
for (int i = 0; i < randomNumbersPerRow; i++) {
// Choose a spot to assign a random number
int indexToAssign = random.nextInt(numCols);
// Make sure we haven't already chosen it
while (bingoCard[row][indexToAssign] != 0) {
indexToAssign = random.nextInt(numCols);
}
int numToAssign = random.nextInt(randomNumberBound) + 1;
bingoCard[row][indexToAssign] = numToAssign;
}
}
// Print the bingo card
for (int row = 0; row < numRows; row++) {
for (int col = 0; col < numCols; col++) {
System.out.printf("%2d ", bingoCard[row][col]);
}
System.out.println();
}
return bingoCard;
}

Minefieldin C matrix [duplicate]

This question already has an answer here:
Minesweeper revealing cells in C
(1 answer)
Closed 1 year ago.
I want to make a minefield. First I made a matrix, asked the user to enter with the rows and columns.
I need to:
put the bombs
indicate the amount of bombs nearby.
#include <stdio.h>
#include <stdlib.h>
int main(){
int rows, columns, i, j, bombs, **matrix;
printf("\Enter the rows: ");
scanf("%d", &rows);
printf("Enter the columns:");
scanf("%d", &columns);
printf("Enter the bombs:");
scanf("%d", &bombs);
if (bombs>= (rows*colums)){
printf("Error");
}
if (bombs<= 0){
printf("Error);
}
for (i = 0; i < rows; i++){
for (j = 0; j < columns; j++){
matrix[i][j] = rand() % 10;
}
}
// show the map //
for (i = 0; i < rows; i++){
for (j = 0; j < columns; j++) {
printf("%d", matrix[i][j]);
}
printf("\n\n");
}
return 0;
}
``
Data Structures
Instead of using an int then remembering magical numbers like -1 indicates a mine, it's more natural to say what these mean explicitly. Then you can change your mind or add to it without worrying about rewriting your whole programme. In the whole minefield, it's useless to have int **m without cols and rows. This interdependence is a sign that you should also package them in a structure to pass as one variable.
struct tile { unsigned nearby : 4, is_mine : 1, is_revealed : 1; };
struct map { size_t x, y; struct tile **tile; };
These definitions are very similar to what you had before, but they express the intent of the code much better.
Arrays
I would forget your complicated alocMatrix and just use one allocation, but then you have to use tiles[y * map->x + x]. Personal preference; I think it's easier to have a constructor that returns one allocated block.
struct map { size_t x, y; struct tile *tile; };
...
if(!(map = malloc(sizeof *map + sizeof *tile * x * y)))
{ if(!errno) errno = ERANGE; return 0; }
...
map->tile = (struct tile *)(map + 1);
memset(map->tile, 0, sizeof *tile * x * y);
Mines
A method of laying mines uniformly at random is to repeatedly choose a random tile, throwing out the tiles you've seen. Another method is to visit all the tiles and calculate the probability of each, P(mines left / tiles left). It depends on the number of mines which will be faster.
const size_t x1 = map->x, y1 = map->y;
size_t x, y, squares = x1 * y1;
assert(map && mines < squares);
for(x = 0; x < x1; x++) {
for(y = 0; y < y1; y++) {
struct tile *tile = &map->tile[y * x1 + x];
tile->is_revealed = 0;
tile->is_mine = rand() < RAND_MAX / squares * mines;
mines -= tile->is_mine;
squares--;
}
}
for(x = 0; x < x1; x++) for(y = 0; y < y1; y++)
map->tile[y * x1 + x].nearby =
(x && y && map->tile[(y-1) * x1 + (x-1)].is_mine) +
...
(x && y < y1 - 1 && map->tile[(y+1) * x1 + (x-1)].is_mine);
How about using this function to place the bombs? Call it by passing the address of m. Keep in mind that marking the rest of the squares with the appropriate number has to happen after the bombs have been placed (and it shouldn't depend on a call to rand). Also, the map has to be initialized to avoid surprises.
void placeBombs(int*** map, int numOfRows, int numOfColumns, int numOfBombs)
{
while (numOfBombs > 0) {
int column = rand() % numOfColumns;
int row = rand() % numOfRows;
if ((*map)[row][column] != -1) {
(*map)[row][column] = -1;
--numOfBombs;
}
/* Else, if a bomb already exists in the cell,
* we iterate without placing a bomb
*/
}
}

C - Printing elements of a 2d array inside a struct array

Im trying to make a function that sets the values of a 2D array, and then another function that prints those values.
For some reason, with my current implementation, if I create a 3x3 matrix and I set every value to the number 5, it prints the values, but it prints them counting up from 5, so it prints 567, 678, 789, when instead I want it to print the exact value that I set.
Here are the function definitions - what am I doing wrong?:
Struct Definition:
struct matrix{
char matrixName[50];
int rows;
int columns;
float* data;
};
typedef struct matrix matrix_t;
Matrix Creation:
int create_matrix(matrix_t* matrixP, int matrixLocation){
char tempName[50];
int rows, cols;
printf("Enter a name for your matrix>\n");
scanf("%s", tempName);
printf("Enter the number of rows>\n");
scanf("%d", &rows);
printf("Enter the number of cols>\n");
scanf("%d", &cols);
float * our_matrix = (float *) malloc(rows * cols * sizeof(float));
strcpy(matrixP[matrixLocation].matrixName, tempName);
matrixP[matrixLocation].rows = rows;
matrixP[matrixLocation].columns = cols;
matrixP[matrixLocation].data = our_matrix;
return 0;
}
Set Values:
int setValues(matrix_t* our_matrix, int matrix_index) {
int counter = 0;
int row = 0, col = 0;
for (col = 1; col <= our_matrix[matrix_index].columns; col++) {
for (row = 1; row <= our_matrix[matrix_index].rows; row++) {
counter++;
printf("Enter the value for column number %d of row number %d>\n", col, row);
scanf("%f", our_matrix[matrix_index].data+(col-1)+(row-1));
}
/* separate rows by newlines */
}
return 0;
}
Print:
int printMatrix(matrix_t* our_matrix, int index) {
int row = 0, col = 0;
for (col = 1; col <= our_matrix[index].columns; col++) {
for (row = 1; row <= our_matrix[index].rows; row++) {
printf(" %2.f ", *our_matrix[index].data+(col-1)+(row-1));
}
printf("\n");
}
return 0;
}
If I call the printMatrix() function without first using setValues, it seems to print the relative position of the cell that it's printing like so:
But when I call setValues() and set all values to the number 5, its prints counting up from the number 5 like this:
Your position calculation is incorrect. There's one problem and one 'aconventional notation' issue.
The problem is the calculation of the array subscripts:
scanf("%f", our_matrix[matrix_index].data+(col-1)+(row-1));
printf(" %2.f ", *our_matrix[index].data+(col-1)+(row-1));
You need to multiply the (row - 1) value by our_matrix[matrix_index].cols. You will probably do better with some shorter names for the values:
int max_col = our_matrix[matrix_index].columns;
int max_row = our_matrix[matrix_index].rows;
float *data = our_matrix[matrix_index].data;
for (col = 1; col <= max_col; col++)
{
for (row = 1; row <= max_row; row++)
{
printf("Enter the value for column number %d of row number %d>\n", col, row);
if (scanf("%f", data + (col-1) + (row-1) * max_col) != 1)
{
…report error and do not continue…
}
}
}
for (col = 1; col <= max_col; col++)
{
for (row = 1; row <= max_row; row++)
printf(" %.2f", data[(col-1) + (row-1) * max_col]);
putchar('\n');
}
That deals with the substantive bug. Note the error checking on scanf(). That is important in 'real world' programs (even if you get away without it in classes or in online contests). You could sensibly use the notation &data[(col-1) + (row-1) * max_cols] in place of data + (col-1) + (row-1) * max_cols in the call to scanf() too — that would improve the consistency of the code.
The 'aconventional notation' issue is that in C, array indexing starts at 0, not 1, and you could avoid the multitude of -1 terms by following the C conventions. This snippet also declares the loop variables when they're needed, minimizing their scope. This is a feature of C since C99 — it may not be available to you on some retrograde (but popular and widespread) platforms.
for (int col = 0; col < max_col; col++)
{
for (int row = 0; row < max_row; row++)
printf(" %.2f", data[col + row * max_col]);
putchar('\n');
}

C - create 3D array of ints and initialize it to zeros

I'm trying to create a 3D array of ints initialized to zeros each of fixed size denoted as "dim".
For example, for dim=3, it will have 27 cells for ints.
I tried this:
int ***board;
int **rows;
int *tried;
board = calloc(dim,sizeof(int**));
rows = calloc(dim*dim, sizeof(int*));
tried = calloc(dim*dim*dim, sizeof(int));
int i;
int j;
int k;
for (i=0 ; i<dim ; i++) {
board[i] = rows + i*dim*dim;
for (j=0 ; j<dim ; j++) {
board[i][j] = tried + j*dim + i*dim*dim;
}
}
for (i=0 ; i<dim ; i++) {
for (j=0 ; j<dim ; j++) {
for (k=0 ; k<dim ; k++) {
board[i][j][k] = 0;
}
}
}
Trying to debug it, I found that it works until:
board[1][1][0] = 0
And then the program gets stuck and i just can't find the reason.
Can someone explain this please?
Thanks!
First about the error in your code. Compare this:
rows = calloc(dim*dim, sizeof(int*));
to this:
for (i=0 ; i<dim ; i++) {
board[i] = rows + i*dim*dim;
The entire size of the array allocated to rows is dim*dim elements. So, already in the second iteration of this loop, you access it out of bounds. You probably meant:
for (i=0 ; i<dim ; i++) {
board[i] = rows + i*dim;
As I already mentioned in the comment, this is not a 3D array. It mimics the usage in code by using pointers and you're using a kind-of clever trick here, so you only need 3 allocations in total. This might be a good idea under the following conditions:
your dim is variable at runtime, so you can't know it in advance, and
you have to write code for compilers that don't support VLAs1) (variable-length-arrays).
If one of this conditions is not true, it's much better to use a real 3D array. If the array doesn't have to live after leaving your function and the size isn't huge, just use a simple variable with automatic storage duration like
int board[3][3][3] = { 0 }; // possibly #define the dimension
or, for a variable dim, requiring a compiler supporting VLAs
int board[dim][dim][dim] = { 0 };
If on the other hand, the array will be huge and/or you need to return it from your function, you indeed have to allocate it dynamically. Then just use the following:
int (*board)[3][3] = calloc(3, sizeof *board); // static size
int (*board)[dim][dim] = calloc(dim, sizeof *board); // dynamic case, with VLA suppport
Also note that calloc() already sets your allocated memory to 0, so no need for looping all over it.
Side notes:
with sizeof, prefer the expression form, so instead of writing
int *a = calloc(5, sizeof(int));
better write
int *a = calloc(5, sizeof *a);
this avoids errors when you later change the type of a.
always check the return value of malloc() and friends -- they might return a null pointer (e.g. when you're running out of memory).
1) VLAs don't exist in the oldest standards C89/C90 -- they were introduced in C99 as a mandatory feature, but later made optional in C11. This allows C11 compilers to omit them, which might make sense when e.g. targeting embedded systems. In practice, you can safely assume a C11 compliant compiler supports them if it isn't special purpose.
I rewrote your code to show how allocation of a 3D array could look like. And as pointed out in the comments, there's no need to initialize the array to 0 since calloc does that for you. Had you used malloc the array would not have been initialized.
#include <stdlib.h>
#include <stdio.h>
#define dim (3u)
int main() {
int x;
int y;
int z;
int ***cube;
cube = calloc(dim, sizeof(int**));
for (z = 0; z < dim; z++) {
cube[z] = calloc(dim, sizeof(int*));
for (y = 0; y < dim; y++) {
cube[z][y] = calloc(dim, sizeof(int));
}
}
for (z = 0; z < dim; z++) {
for (y = 0; y < dim; y++) {
for (x = 0; x < dim; x++) {
cube[z][y][x] = z + y + x;
}
}
}
for (z = 0; z < dim; z++) {
for (y = 0; y < dim; y++) {
for (x = 0; x < dim; x++) {
printf("%d ", cube[z][y][x]);
}
printf("\n");
}
printf("\n");
}
return 0;
}
What you want to store in it is up to you, in my example I wrote the sum of the counter to each index.
Code below is Unlicense.
I will suggest something different. Just create a 1D array and set some boundaries to interpret it as 3D. I added some test cases for you to better visualize how it works. Do not forget to look at how easy 'calloc' call is. Here is the code:
#include <stdlib.h>
#include <stdio.h>
int getindex(int dim, int x, int y, int z) {
return z * dim * dim + y * dim + x;
}
void printarray(int* tdarray, int dim) {
printf("[\n");
for (int i = 0; i < dim; i++) {
printf("\t[\n");
for (int j = 0; j < dim; j++) {
printf("\t\t[");
for (int k = 0; k < dim; k++) {
if (k == 0) printf("%d", *(tdarray + getindex(dim, k, j, i)));
else printf(",\t %d", *(tdarray + getindex(dim, k, j, i)));
}
printf("]\n");
}
printf("\n\t]\n");
}
printf("]\n");
}
int main() {
int dim = 10;
size_t arraysize = sizeof (int) * dim * dim * dim;
int lookupindex = getindex(dim, 7, 5, 4); /* Numbers picked randomly */
int* tdarray = (int*) malloc(arraysize);
calloc(*tdarray, arraysize);
/* Below is test code and visualizations, all magic happens above.*/
if (*(tdarray + lookupindex) == 0) *(tdarray + lookupindex) = 7;
printf("tdarray[x:%d, y:%d, z:%d]:\t%d\n\n", 7, 5, 4, *(tdarray + lookupindex));
printarray(tdarray, dim);
printf("\n\n\n\n\n\n\n\n\n\n");
for (int i = 0; i < getindex(dim, 9, 9, 9) + 1; i++) *(tdarray + i) = i;
printarray(tdarray, dim);
free(tdarray);
}

Filling C array with pointers

The following function is supposed to fill a two dimensional array with floats increasing by 0.5
void MatrixFill(float *pf, float x, int rows, int columns, FILE *fp) {
int i, j;
printf ("\n***\tBegin MatrixFill\t***\n\n");
fprintf (fp, "\n***\tBegin MatrixFill\t***\n\n");
for (i = 0; i < rows; i++) {
for (j = 0; j < columns; j++) {
*(pf + i + columns ) = x;
x += 0.5;
}
}
printf ("\n***\tEnd MatrixFill\t***\n\n");
fprintf (fp, "\n***\tEnd MatrixFill\t***\n\n");
}
However, I'm not sure what goes in my "filling statement." (*(pf+stuff)=x;)
Any help with pointers/ array filling would be great.
Thanks!
this is were you got the mess: (pf + i + columns ) = x it should be: *(pf + i + j * rows)
Why is that?
First, you must see that each row passes through all the columns:
col1|col2|col3
----+----+----
row1 | |
----+----+----
Now, you see if you want to get to row number x, you must pass through all the columns x times!
Generally Speaking
in each 2D array arr[COLS][ROWS] where COLS and ROWS are the total numbers of columns and rows consequently, arr[i][j] = arr[i + j * COLS] = arr[j + i * ROWS]

Resources