Nested boxes: what am I missing? - arrays

I have to create an efficient program in C(99) where I have n boxes and I can insert one of them into another one (of the same n boxes), like a matryoshka. The goal is to find the maximum number of boxes that can be insereted and list them from the outside one to the most inside one (including the outside one). So, given x (width), y (height) and z (depth), all >= 0, a box can be inserted into another if x[i] < x[j] and y[i] < y[j] and z[i] < z[j] where i and j are the indexes (starting from 0) of two boxes. Boxes can't be rotated!.
The input file has this structure:
x[0] y[0] z[0]
…
x[n-1] y[n-1] z[n-1]
This is what I could achieve in some days of work:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct Array Boxes;
struct Array {
unsigned int count;
struct Box **elements;
};
struct Box {
int id;
double x;
double y;
double z;
struct Array inside;
};
int n;
/**
* Pretty print the boxes, according to the resulting output format
*
* #param boxes
*/
void print_boxes(Boxes boxes) {
printf("%d boxes\n", boxes.count);
for (int i = 0; i < boxes.count; ++i) {
struct Box box = *(boxes.elements[i]);
printf("box %d: %f %f %f - How many inside? %d\n", box.id, box.x, box.y, box.z, box.inside.count);
}
}
/**
* Append a box to an array
*
* #param arr
* #param box
* #param mem_alloc if true, memory will be allocated before appending the new box
*/
void array_append(struct Array *arr, struct Box *box, bool mem_alloc) {
if (mem_alloc) {
if (arr->count == 0) {
arr->elements = malloc(sizeof(struct Box *));
} else {
arr->elements = reallocarray(arr->elements, arr->count + 1, sizeof(struct Box *));
}
}
arr->elements[arr->count] = box;
arr->count += 1;
}
struct Array find_inside_boxes(Boxes boxes, struct Box *box) {
struct Array boxes_inside = {0, malloc(boxes.count * sizeof(struct Box *))};
for (int i = 0; i < boxes.count; ++i) {
struct Box *b = boxes.elements[i];
if (b->x < box->x && b->y < box->y && b->z < box->z) {
array_append(&boxes_inside, b, false);
}
}
return boxes_inside;
}
struct Box *find_best_box(Boxes boxes) {
struct Box *max = boxes.elements[0];
for (int i = 1; i < boxes.count; ++i) {
struct Box *box = boxes.elements[i];
if (box->inside.count > max->inside.count) {
max = box;
}
}
return max;
}
void print_inside_boxes(struct Box *box) {
Boxes boxes = {0, NULL};
array_append(&boxes, box, true);
while (box->inside.count > 0) {
box = find_best_box(box->inside);
array_append(&boxes, box, true);
}
print_boxes(boxes);
}
int main(int argc, char *argv[]) {
FILE *file = fopen(argv[1], "r");
if (!file) {
printf("No input or can't open the input file");
return EXIT_FAILURE;
}
fscanf(file, "%d\n", &n);
double x, y, z;
Boxes boxes = {n, malloc(n * sizeof(struct Box))};
for (int i = 0; fscanf(file, "%lf%lf%lf", &x, &y, &z) != EOF; i++) {
struct Box *box = malloc(sizeof(struct Box));
box->id = i;
box->x = x;
box->y = y;
box->z = z;
boxes.elements[i] = box;
}
fclose(file);
for (int i = 0; i < boxes.count; ++i) {
struct Box *box = boxes.elements[i];
box->inside = find_inside_boxes(boxes, box);
}
struct Box *best = find_best_box(boxes);
print_inside_boxes(best);
return EXIT_SUCCESS;
}
Basically, it gets the maximum box by its volume and it repeats this until there are no more boxes. Boxes are deleted from the boxes array if their dimensions (x, y, z) are incompatible with the latest box found.
This code mostly works. The issue is that it doesn't work with the last test file I have. I have these test files (.in files are input files, where .out are the expected outputs):
Sample 1: Input - Output
Sample 2: Input - Output
Sample 3: Input - Output
The program works with samples 1 and 2 (the first sample output differs for one line which is fine if the number of the boxes is valid and listed boxes follow the inserting condition). What doesn't work is sample 3: the program finds less boxes than the expected ones (my program finds the first board as 730 while the expected output is 714). What am I missing or what is wrong in my code? Can you help me to fix it, since I have little time left to deliver this.
Thanks to anyone who tries to help me!

Related

How to work out if a member of a struct was set or not?

Say I have the following struct:
struct cube {
int height;
int length;
int width;
};
I need to create a library that allows the user to enter values into the struct and then pass it into a function, which will determine whether the user wants either the area or the volume from the values provided.
For example:
int main() {
struct cube shape;
shape.height = 2;
shape.width = 3;
printf("Area: %d", calculate(shape)); // Prints 6
shape.length = 4;
printf("Volume: %d", calculate(shape)); // Prints 24
return 0;
}
int calculate(struct cube nums) {
if (is_present(nums.height, nums) && is_present(nums.width, nums)) {
return nums.height * nums.width;
}
else if (is_present(nums.height, nums) && is_present(nums.width, nums) && is_present(nums.length, nums)) {
return nums.height * nums.width * nums.length;
}
else {
return -1; // Error
}
}
This should work, if I can use a function (like is_present(), which I just made up) to work out if a value was given to a member of a struct.
Is there such a function and if not, how could this be implemented?
You should initialize your fields to something that is out of the domain of the possible values. For example, for such dimensions, which are positive numbers, a negative value could act as a "not assigned" value.
Also, I reordered your if statements: the one checking for all the fields should be the first.
Here's an example:
#include <stdio.h>
#define NOT_PRESENT -1
#define is_present(x) ((x) != NOT_PRESENT)
struct cube {
int height;
int length;
int width;
};
int calculate(struct cube);
int main() {
struct cube shape = {
.height = NOT_PRESENT,
.length = NOT_PRESENT,
.width = NOT_PRESENT,
};
shape.height = 2;
shape.width = 3;
printf("Area: %d\n", calculate(shape)); // Prints 6
shape.length = 4;
printf("Volume: %d\n", calculate(shape)); // Prints 24
return 0;
}
int calculate(struct cube nums) {
if (is_present(nums.height) && is_present(nums.width) && is_present(nums.length)) {
return nums.height * nums.width * nums.length;
} else if (is_present(nums.height) && is_present(nums.width)) {
return nums.height * nums.width;
} else {
return -1; // Error
}
}
First you have to clearly define what "a value was given" means to your domain. A member initialized to 0 means no value was given?
A simple solution is to initialize your struct with 0 (for example), and just compare each member against it. Example:
struct cube shape = {0};
shape.width = 3;
if (shape.width != 0)
printf("width was set");
Or simpler:
struct cube shape = {2,0,3};
if (shape.width != 0)
printf("width was set");

Unable to read a maze of chars and put it into a bidimensional array

I am making a maze solving game. There is a function in the middle of the game that saves the progress and prints everything into the file. But now i want to read the maze, the character, etc from the file and put it into a bidimensional array but i am not being able to do so.
The array is declared globally (because of its use in several functions) and it is maze[30][30]. N is also declared globally as a variable size but at this point it should be 10. filePath too and it gives the name of the file.
This is how they are declared globally.
int N = 10;
char* filePath = "./save.txt";
char maze[30][30];
This is the read function:
void ler()
{
int i, j;
ex=1; ey=0;
sx=N-2; sy=N-1;
int aux;
FILE *fp = fopen(filePath, "r");
if (fp == NULL)
{
printf("Unable to perform.");
return;
}
system("cls");
for(i=0 ; i<N ; i++)
{
for(j=0 ; j<N ; j++)
{
fscanf(fp, "%c", maze[j][i]);
}
}
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
printf("%c", maze[j][i]); //Double print just for visuals
printf("%c", maze[j][i]);
}
printf("\n");
}
fclose(fp);
}
This is the save function:
void save(char maze[30][30]){
int i,j;
FILE *fp = fopen(filePath, "w");
if(fp==NULL){
printf("Unable to perform.");
return;
}
for(i=0 ; i<N ; i++){
for(j=0 ; j<N ; j++){
fprintf(fp, "%c", maze[j][i]);
fprintf(fp, "%c", maze[j][i]);
}
fprintf(fp, "\n", maze[j][i]);
}
fclose(fp);}
At this point it should only be possible to print the maze but it is not doing even that.
What save.txt file looks like after saving
The weird II is the caharcter and the other is like a highscore thing.
Using multidimensional arrays in C is actually more pain than they're worth. A much better option is to use a structure with a dynamically allocated array describing the maze, and accessor functions to examine and change the maze cells. Instead of putting markers in the maze data, you can put start/end/current location coordinates in the structure.
(I do realize that this does not answer the OP's stated question, but this is an answer to the underlying problem OP is trying to solve.)
Consider the following example. It limits the maze size to 255×255, but because each coordinate and maze cell is always just one byte, the save files are portable between architectures, as there is no byte order (endianness) to worry about. (You, as the programmer, do need to choose to use only codes 0..255 in the maze, though, to keep the data portable; the functions below won't enforce that.)
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct {
unsigned char row;
unsigned char col;
} mazepoint;
typedef struct {
unsigned char rows;
unsigned char cols;
unsigned char *cell;
mazepoint player;
} maze;
#define OUTSIDE 0
static inline unsigned char maze_get(maze *const m,
const int row,
const int col)
{
if (m &&
row >= 0 && row < (int)(m->rows) &&
col >= 0 && col < (int)(m->cols))
return m->cell[ (size_t)col + (size_t)(m->cols) * (size_t)row ];
else
return OUTSIDE;
}
static inline unsigned char maze_set(maze *const m,
const int row,
const int col,
const unsigned char val)
{
if (m &&
row >= 0 && row < (int)(m->rows) &&
col >= 0 && col < (int)(m->cols))
return m->cell[ (size_t)col + (size_t)(m->cols) * (size_t)row ] = val;
else
return OUTSIDE;
}
static inline void maze_free(maze *const m)
{
if (m) {
free(m->cell);
m->rows = 0;
m->cols = 0;
m->cell = NULL;
}
}
int maze_create(maze *const m,
const int rows,
const int cols)
{
size_t cells = (size_t)rows * (size_t)cols;
unsigned char *cell;
if (!m)
return -1; /* NULL reference to a maze variable! */
if (rows < 1 || rows > 255 ||
cols < 1 || cols > 255)
return -1; /* Invalid number of rows or columns! */
cell = malloc(cells); /* sizeof (unsigned char) == 1. */
if (!cell)
return -1;
/* Initialize all maze cells to OUTSIDE. */
memset(cell, OUTSIDE, cells);
m->rows = rows;
m->cols = cols;
m->cell = cell;
/* Let's initialize player location to upper left corner. */
m->player.row = 0;
m->player.col = 0;
return 0; /* Success. */
}
int maze_save(maze *const m, const char *filename)
{
size_t cells;
FILE *out;
if (!m || m->rows < 1 || m->cols < 1)
return -1; /* No maze to save! */
if (!filename || !filename[0])
return -1; /* NULL or empty filename! */
cells = (size_t)(m->rows) * (size_t)(m->cols);
out = fopen(filename, "wb");
if (!out)
return -1; /* Cannot open file for writing! */
do {
/* First byte is the number of rows. */
if (fputc(m->rows, out) == EOF)
break;
/* Second byte is the number of columns. */
if (fputc(m->cols, out) == EOF)
break;
/* rows*cols bytes of maze data follows. */
if (fwrite(m->cell, 1, cells, out) != cells)
break;
/* Player location follows. */
if (fputc(m->player.row, out) == EOF)
break;
if (fputc(m->player.col, out) == EOF)
break;
/* You can save additional data at this point. */
/* That completes the save file. Ensure it is correctly saved. */
if (fflush(out))
break;
if (fclose(out))
break;
/* Maze successfully saved. */
return 0;
} while (0);
/* Save failed. */
fclose(out);
remove(filename);
return -1;
}
int maze_load(maze *const m, const char *filename)
{
size_t cells;
unsigned char *cell;
int rows, cols, r, c;
FILE *in;
if (!m)
return -1; /* No reference to a maze variable to load into! */
/* Just in case, we clear the maze first. Might help finding bugs! */
m->rows = 0;
m->cols = 0;
m->cell = NULL;
if (!filename || !filename[0])
return -1; /* NULL or empty filename! */
in = fopen(filename, "rb");
if (!in)
return -1; /* Cannot open file for reading. */
rows = fgetc(in);
cols = fgetc(in);
if (rows == EOF || rows < 1 || rows > 255 ||
cols == EOF || cols < 1 || cols > 255) {
fclose(in);
return -1; /* Not a saved maze! */
}
cells = (size_t)(rows) * (size_t)(cols);
cell = malloc(cells);
if (!cell) {
fclose(in);
return -1; /* Not enough memory available! */
}
do {
/* Read maze cell data. */
if (fread(cell, 1, cells, in) != cells)
break;
/* Player location. */
r = fgetc(in);
c = fgetc(in);
if (r == EOF || r < 0 || r > 255 ||
c == EOF || c < 0 || c > 255)
break;
m->player.row = r;
m->player.col = c;
/* Load other saved data here. */
/* All data read successfully. */
fclose(in);
m->rows = rows;
m->cols = cols;
m->cell = cell;
return 0;
} while (0);
/* Read error. */
fclose(in);
free(cell);
return -1;
}
In your own program, you'd create a maze thus:
maze m;
/* Create a 20-row, 30-column maze. */
if (maze_create(&m, 20, 30)) {
/* Failed to create maze! Show an error message. */
exit(EXIT_FAILURE);
}
To save the maze to say maze.dat, you use
m.player.row = /* row where the player is */
m.player.col = /* column where the player is */
if (maze_save(&m, "maze.dat")) {
/* Failed! Show an error message. */
exit(EXIT_FAILURE);
}
If you look at the example code, you can add additional data, especially points like the player place, to be saved and loaded along with the maze cells themselves.
To destroy a maze when it is no longer needed, use
maze_free(&m);
To load a saved maze, say from maze.dat, use
if (maze_load(&m, "maze.dat")) {
/* Failed! Show an error message. */
exit(EXIT_FAILURE);
}
/* Restore player place from m.player.row and m.player.col */
The accessor function maze_get() is not limited to the valid coordinates (0 through rows-1 or cols-1, inclusive). If you examine outside the maze itself, it will just return the value of the OUTSIDE macro. For example,
if (maze_get(&m, row, col) == 5) {
/* That cell has value 5 */
} else {
/* Either the cell has a different value,
or row,col is outside the maze. */
}
Similarly, you can try to set any cell value safely. It will only "stick" if it is within the valid maze coordinate range, however; elsewhere it will return OUTSIDE:
if (maze_set(&m, row, col, 5) == 5) {
/* Changed cell value to 5 */
} else {
/* row,col is outside the maze. */
}
The reason I wrote the accessor macros that way, is that it makes rendering only a part of the maze very simple. If the view is viewrows by viewcols in size, centered at row and col, then you can render the view using a simple loop:
const int top = row - viewrows / 2;
const int left = col - viewcols / 2;
int vr, vc;
for (vr = 0; vr < viewrows; vr++) {
for (vc = 0; vc < viewcols; vc++) {
const unsigned char v = maze_get(&m, top+vr, left+vc);
/* Draw v at row vr, col vc */
}
}
and the cells are even drawn in the same order as you read this text; from top to bottom, left to right.
Note that instead of using the maze cell values for character codes, you should use a lookup table instead. For example,
int cell_char[256];
Instead of printing cell values directly, you'd print the corresponding cell_char, for example
fputc(cell_char[maze_get(&m, row, col)], stdout);
That way you can group e.g. different wall characters into a consecutive range, or even use the individual bits in the 8-bit cell value as identifiers. The maze cells then describe the logical contents in that maze cell, rather than its visual representation, with the logical-to-visual mapping in a separate array.
If you used Gtk+, you could have an array of GtkImage pointers,
GtkImage *cell_image[256] = {0}; /* All NULL by default */
or using SDL, you could have the maze cells as textures you can render,
SDL_Texture *cell_texture[256] = {0}; /* All NULL by default */
and in both cases, read them from either one large image (say, divided into 16×16 exact same size rectangles), or from individual image files.
For example, you could decide that the four least significant bits in the cell value specify whether movement from that cell up (previous row), down (next row), left (previous column), or right (next column) is possible:
#define CAN_GO_UP(value) ((value) & (1 << 0)) /* == 1 */
#define CAN_GO_DOWN(value) ((value) & (1 << 1)) /* == 2 */
#define CAN_GO_LEFT(value) ((value) & (1 << 2)) /* == 4 */
#define CAN_GO_RIGHT(value) ((value) & (1 << 3)) /* == 8 */
Note that this allows you to do "trap walls": passages that only work one way. Maze cell values that are multiples of 16 (0, 16, 32, 48, 64, 80, 96, ..., 208, 224, and 240) represent completely blocked cells: no way out. +1 allows passage up; +2 allows passage down; +3 allows passage up and down; +4 allows passage left; +5 allows passage left and up; +6 allows passage left and down; +7 allows passage up, left, and down; +8 allows passage right; +9 allows passage up and right; +10 allows passage down and right; +11 allows passage up, down, and right; +12 allows passage left and right; +13 allows passage up, left, and right; +14 allows passage down, left, and right; and +15 allows passage up, down, left, and right.
I would personally also recommend using the wide version of the ncurses library (ncursesw). (I do not use Windows, so I am not exactly sure how you install and use it in windows, but the ncurses home page does have downloads when using mingw.)
Then, you would have a much wider variety of glyphs you could use. (When using UTF-8 locales, potentially the entire Unicode glyph set -- the Box Drawing block especially would be useful for maze drawing, and most of those glyphs are also available in the old CP437 codepage, which means they should work both in Windows and non-Windows terminals nicely.)
In that case, you'd probably use
cchar_t cell_char[256];
As I mentioned above, you could even do a graphical version (perhaps later on, extending your terminal version?) in C using SDL or GTK+. (Note that the above separation between logical maze cell content value and the visual describing the cell also means you can, at runtime, choose between "themes", by having more than one set of cell images. That allows you to start with crude informational versions, for debugging, and then add visual goodness.)
The approach shown in this answers allows you to start with a simple terminal-based game, and if you decide you want to, add support for graphical UI, with image-based maze cells, without having to rewrite any of your core maze code.

C: Best way to make a buffer copy of an Image Map

I have a struct that basically has these contents:
typedef struct {
unsigned int width, height;
float *r, *g, *b;
} image;
Using the FreeImage.h library I am able to open a certain image and associate the pixels with its RGB colours. So the code is as follows:
imagem open_image(char *name_of_file) {
FIBITMAP *bitmapIn;
int x, y;
RGBQUAD color;
image I;
bitmapIn = FreeImage_Load(FIF_JPEG, name_of_file, 0);
if (bitmapIn == 0) {
printf("Error! File not found - %s\n", name_of_file);
} else {
printf("File found!\n");
}
x = FreeImage_GetWidth(bitmapIn);
y = FreeImage_GetHeight(bitmapIn);
I.width = x;
I.height = y;
I.r = malloc(sizeof(float) * x * y);
I.g = malloc(sizeof(float) * x * y);
I.b = malloc(sizeof(float) * x * y);
for (int i=0; i<x; i++) {
for (int j=0; j <y; j++) {
int idx;
FreeImage_GetPixelColor(bitmapIn, i, j, &color);
idx = i + (j*x);
I.r[idx] = color.rgbRed;
I.g[idx] = color.rgbGreen;
I.b[idx] = color.rgbBlue;
}
}
return I;
}
So now when I call the function in my main file like:
image img = open_image("file_name");
I have my image "map" in my reference named img.
Basically what I want to know is what is the best way to make a copy of this img so that I can apply a filter in this buffer img, for exemple a blur filter. That way when I get the surrounding pixels values to write to the central one, it is always the original pixels so get the pixels from "img" and write them with the filter to the "img_buffer".
I guess I could just make another reference named img_buff and call the open_image function again but that takes to much real and user time.
So how would you suggest I made the copy? From my research I found that memcpy() maybe won't do the trick since it gives me a shallow copy but not to sure about it.
Any suggestion that won't take to much more real/user time is welcome!
If you want to improve performances,you should try to avoid copies which are time-consuming specially for large arrays.
But I assume you can't, so there is a solution :
Image imgCopy;
imgCopy.width = img.width
imgCopy.height = img.height
In a first time you allocate memory :
imgCopy.r = (float*)malloc(sizeof(float) * imgCopy.width * imgCopy.height );
imgCopy.g = (float*)malloc(sizeof(float) * imgCopy.width * imgCopy.height );
imgCopy.b = (float*)malloc(sizeof(float) * imgCopy.width * imgCopy.height );
Then you can copy the pointer's content :
*(imgCopy.r) = *(img.r);
*(imgCopy.g) = *(img.r);
*(imgCopy.b) = *(img.r);

Iterator and Pointer on Matrix in C

For a JPEG image compression, I manipulate image in grey levels and 8bits by pixels
I have this type of matrix I dynamically allocated :
typedef char pixel_t;
pixel_t ** pix_matrix;
after allocating and filling it, I have a bidimensional array with the values (from -128 to +127) of the luminance of the picture.
For the JPEG compression, I need to iterate this array in zigzag like this:
So I want to create an Iterator structure for this type. This iterator must have 'current' and 'begin' members and I want those members to be pointers to the current element and first one of the matrix. In other words, I want to store the addresses and not the indexes. But after hours of tests, prints and researches, I couldn't find the way to make that possible. What type of pointer do I have to use? how make it point to the first address of my matrix? Is my request simply possible?
And if all of this is possible, how can I get the next element, and the value of the current one?
You can write an interator structure:
struct zigzag_t {
int width; // width, must be initialised
int height; // height, must be initialised
int x; // current x index
int y; // current y index
int underway; // dummy value to start at (0, 0)
};
which you must initialise with the width and height of your image. Write an interator function, so that you can use this iterator like this:
struct zigzag_t zz = {8, 8};
while (zigzag_next(&zz)) {
printf("(%d, %d)\n", zz.y, zz.x);
}
The iterator itself is not too complicated: If the sum of the x and y indices is odd, you walk southwest until you hit either the west or south edge. If the sum is even, you walk northeast until you hit either the north or east wall. If you hit the ne or sw edges, the east and south edges get priority. The iteration ends after you have visited the se edge.
Because the struct starts off with x and y both zero, the first point is (0, 1). In order to fix this, the dummy field underway, which also is zero, is used.
The iterator must be reset if you want to use it a second time. better yet, define and initialise a fresh iterator.
The iterator function:
int zigzag_next(struct zigzag_t *zz)
{
int odd = (zz->x + zz->y) % 2;
if (zz->underway == 0) {
zz->x = zz->y = 0;
zz->underway = 1;
return 1;
}
if (odd) {
/* walk southwest */
int w_edge = zz->x == 0;
int s_edge = zz->y == zz->height - 1;
if (s_edge) {
zz->x++;
return zz->x < zz->width;
} else if (w_edge) {
zz->y++;
} else {
zz->x--;
zz->y++;
}
} else {
/* walk northeast */
int e_edge = zz->x == zz->width - 1;
int n_edge = zz->y == 0;
if (e_edge) {
zz->y++;
return zz->y < zz->height;
} else if (n_edge) {
zz->x++;
} else {
zz->x++;
zz->y--;
}
}
return 1;
}
This solution returns the x and y positions, which you can use as indices to your double pointer to pixel data. It would not be hard to extend the struct to hold the base pointer to your pixel data and have the iterator function return a pointer to a pixel or NULL if the iteration has run out.
An example solution with pointers is below.
#include <stdlib.h>
#include <stdio.h>
typedef char pixel_t;
struct zigzag_t {
pixel_t **p; // base data
int width; // width, must be initialised
int height; // height, must be initialised
int x; // current x index
int y; // current y index
int underway; // dummy value to start at (0, 0)
};
pixel_t *zigzag_next(struct zigzag_t *zz)
{
int odd = (zz->x + zz->y) % 2;
if (zz->underway == 0) {
zz->x = zz->y = 0;
zz->underway = 1;
return *zz->p;
}
if (odd) {
/* walk southwest */
int w_edge = zz->x == 0;
int s_edge = zz->y == zz->height - 1;
if (s_edge) {
zz->x++;
if (zz->x == zz->width) return NULL;
} else if (w_edge) {
zz->y++;
} else {
zz->x--;
zz->y++;
}
} else {
/* walk northeast */
int e_edge = zz->x == zz->width - 1;
int n_edge = zz->y == 0;
if (e_edge) {
zz->y++;
if (zz->y == zz->height) return NULL;
} else if (n_edge) {
zz->x++;
} else {
zz->x++;
zz->y--;
}
}
return zz->p[zz->y] + zz->x;
}
int main()
{
pixel_t *data[] = {
"abcde", "fghij", "klmno", "pqrst", "uvwxy"
};
struct zigzag_t zz = {data, 5, 5};
for (;;) {
pixel_t *p = zigzag_next(&zz);
if (p == NULL) break;
putchar(*p);
}
putchar('\n');
return 0;
}
This solution is a C solution. There is no begin member function; initialisation is done via simple struct initialisation. There is no increment operator and no end member function; moving the iterator forward and checking for the end is done in a plain old function.
You have tagged the question C, but iterators are more frequent in C++, where they can be implemented as classes. The above C example may serve as a base for such an implementation.
Something nice and simple.
Function next is the iterator; it returns true until all cells have been visited.
A variable of type POSITION holds the iterator state.
Function current returns a pointer to the current cell in the matrix.
Demo function sample_application puts it all together.
#define MAX_XY 7
typedef struct { int x, y; } POSITION;
static int sign_of(int i)
{
return i < 0 ? -1 : i > 0 ? 1 : 0;
}
static int get_direction(int a, int b, int odd_is_forward)
{
return sign_of(((a + b) % 2 == odd_is_forward || b >= MAX_XY ? MAX_XY : 0) - a);
}
int next(POSITION *pos)
{
int x = pos->x;
int y = pos->y;
pos->x += get_direction(x, y, 0);
pos->y += get_direction(y, x, 1);
return x < MAX_XY || y < MAX_XY;
}
pixel_t *current(POSITION *pos)
{
return &pix_matrix[pos->y][pos->x];
}
void sample_application() // just demonstrating the use of POSITION
{
POSITION pos = {-1, -1}; // always start from these dummy coordinates
while (next(&pos)) // this iterates through the matrix
{
int coord_x = pos.x; // this is how you get the current coordinates
int coord_y = pos.y;
*current(&pos) = 12; // this is how you access the current cell
}
}

Changing fixed bi-dimensional array to take size given at runtime

I've been trying to wrap my head around this the whole day...
The code that I have so far works as planed, the idea is that I'll have to change tCell * cells[3][5]; to take a size that's given at runtime. What changes do I need to make to retain the functionality?
typedef struct {
int active;
} tCell;
typedef struct {
tCell * cells[3][5];
} tGrid;
// creates a grid and initialize all the cells to NULL
tGrid *init_grid()
{
tGrid *grid= malloc(sizeof(tGrid));
if(grid == NULL)
exit(127); // failed to malloc
int i, j;
for(i=0; i < 3; i++)
for(j=0; j < 5; j++)
grid->cells[i][j]= NULL;
return grid;
}
// adds a cell to the grid
void add_cell(tGrid *grid)
{
tCell cell;
int y = rand() % 4;
if(grid->cells[0][y] != NULL)
exit(127); // cell is taken
cell.active = 1;
grid->cells[0][y] = &cell;
}
void remove_cell(tGrid *grid, int x, int y)
{
if(x < 0 || x > 3 || y < 0 || y > 5)
exit(127); // out of bounds
grid->cells[x][y]= NULL;
}
Basically, init_grid will have to take x and y as parameters:
tGrid *init_grid(int x, int y);
But then, how do I change tGrid struct definition? Whatever I've tried so far yielded a compiler error (e.g. tCell * cells[][];)
On a slightly related note, how do you read "tCell * cells[3][5];" outloud?
Note:
this is a C question
I'm using gcc 4.1 to compile the code
Easy.
typedef struct {
int rows;
int columns;
tCell **cells;
} tGrid;
And allocating:
tGrid *pGrid = (pGrid*)malloc(sizeof(tGrid));
/* check results etc */
pGrid->rows = rows;
pGrid->columns = columns;
pGrid->cells = (tCell**)malloc(sizeof(tCell*)*rows);
/* check results */
do{
pGrid->cells[rows-1] = (tCell*)malloc(sizeof(tCell)*columns);
/* check results */
} while (--rows);
Done.
Or, you can also do:
typedef struct {
int rows;
int columns;
tCell *cells;
} tGrid;
/*****whatever in the middle ***********/
pGrid->cells = (tCell*)malloc(sizeof(tCell)*rows*columns);
instead of the do-while loop. The difference is that in the first case, each row will be a separate array in the memory, which may be useful when handling the thing.
Of course, in the end, for each malloc there has to be a free.

Resources