0

Hello i am currently writing a program to emulate bouldering in real life, where there is a Wall ADT where you can store certain rocks on the wall which is represented basically as a 2d matrix. Unfortunately, when i tried to implemement the adjacency matrix (struct rock **rocks) in the code below, some of the rocks wouldn't get added to the matrix. I don't know if its because my initailisation of the matrix in WallNew is not done correctly. But i initialised it by the w->capacity which is width times the height of the rockwall. I'm not sure what im doing wrong, if i can't fix it i might go to use a single pointer array instead, but I'm trying to implement this with no luck. My program takes in a list of data and then creates an matrix.

#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#include "Wall.h"

struct wall {
    int height;
    int width;
    int numRocks;
    int capacity; // this is just here to simplify future operations
    struct rock **rocks; // adjacency matrix storing rocks
    // needs to be a double pointer
};
// struct rock is usually in wall.h but i moved it here so you could read it
struct rock {
    int row;
    int col;
    Colour colour;
};

static int compareRocks(const void *ptr1, const void *ptr2);

/**
 * Creates a new blank wall with the given dimensions
 */
Wall WallNew(int height, int width) {
    assert(height > 0);
    assert(width > 0);

    Wall w = malloc(sizeof(*w));
    if (w == NULL) {
        fprintf(stderr, "error: out of memory\n");
        exit(EXIT_FAILURE);
    }

    w->height = height;
    w->width = width;
    w->capacity = height * width;
    // No rocks initially
    w->numRocks = 0;


    w->rocks = malloc(w->capacity * sizeof(struct rock*));
    if (w->rocks == NULL) {
        fprintf(stderr, "error: out of memory\n");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < w->capacity; i++) {
        w->rocks[i] = calloc(w->capacity, sizeof(struct rock));
        if (w->rocks[i] == NULL) {  
            fprintf(stderr, "error: out of memory\n");
            exit(EXIT_FAILURE);
        }
    }

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            w->rocks[i][j].row = -1;
            w->rocks[i][j].col = -1;
            // Default green
        }
    }

    return w;
}

You can see below my programs output of the boulder wall compared to what it should be. The boulder wall stops adding rocks at a width greater than 20. (When inputed with a wall width of 25 and heigh of 20)expected output and current output You can see the difference where the rocks added just suddenly cuts off with not explanation. Even though i know the rocks are being processed because i added a printf statement to the rock add function which showed it worked. Ill put the rockadd fucntion below.

// Checks if rock is already present, true if rock exists
static int checkExistingRock(Wall w, struct rock g) {
    return  w->rocks[g.col][g.row].row != -1 && w->rocks[g.col][g.row].col != -1;
}

/**
 * Adds a rock to the wall
 * If there is already a rock at the given coordinates, replaces it
 */
void WallAddRock(Wall w, struct rock rock) {
    // assert(validRock(w, rock));
    assert(validRockColour(w, rock));
    printf("wassup\n");

    // if no existing rock numRocks++, otherwise replace rock
    if (!checkExistingRock(w, rock)) {
        printf("hello there\n");
        w->numRocks++;
    }

    printf("come on\n");
    printf("stuff: %d %d %d\n", rock.row, rock.col, rock.colour);

    // set rock.col and rock.row to current rock
    // This is redundant as place on w->rocks is the same pos,
    // but for when it is handled singley this is useful
    w->rocks[rock.col][rock.row].row = rock.row;
    w->rocks[rock.col][rock.row].col = rock.col;
    w->rocks[rock.col][rock.row].colour = rock.colour;
}

I tried different ways of implememnting the struct rocks array, like using single pointer array. However, i want to use a double pointer array in my implementation so even though i figured out single pointer im not sure what im doing for double pointers wrong.

Edit: I know that i should of looped by height andwidth the allocate memory for each row. But when i did that, my program showed these big memory errors. Below is the original code i did for it

  // Loop run height times to allocate memory for each row of the rocks array
// for (int i = 0; i < height; i++) {
//     w->rocks[i] = malloc(width * sizeof(struct rock));
//     if (w->rocks[i] == NULL) {
//         fprintf(stderr, "error: out of memory\n");
//         exit(EXIT_FAILURE);
//     }
//     for (int j = 0; j < width; j++) {
//         // initialise values in row
//         w->rocks[i][j].row = -1;
//         w->rocks[i][j].col = -1;
//         // Default green
//         w->rocks[i][j].colour = 0;
//     }
// }
Ken White
  • 123,280
  • 14
  • 225
  • 444
Alex
  • 1
  • 1
  • Sorry i dont know if formatted in correctly as this is one of my first question ive asked, but i have put attached two images, 'expected output' and 'currrent output' which look like that are the same link but its not, there is two images – Alex Apr 14 '23 at 02:53
  • also ignore the printf statements, they were for debugging lol – Alex Apr 14 '23 at 02:55
  • 1
    The code you show should not build. What does `malloc` return? What is the variable `w`? Please try to create a [mre], and [edit] your question to show it. – Some programmer dude Apr 14 '23 at 02:57
  • And the loop `for (int i = 0; i < w->capacity; i++)` is wrong for your "rock" allocation. You should be creating an array of `height` pointers. Then an array of `width` "rocks". The problem with your code is that you allocate *to many* pointers and "rocks". – Some programmer dude Apr 14 '23 at 03:00
  • And you should really learn not to pass *copies* of your structures to functions. Any modification you make to the structure will be made only to that structure object, not the one you use in the call. Pass *pointers*. – Some programmer dude Apr 14 '23 at 03:02
  • @Someprogrammerdude I think i tried your example. I just edited my post to show what i did beforehand but it gave me this big memory error, and that memory error only disappeared when i changed it to capacity so i just ran with it i guess – Alex Apr 14 '23 at 03:04
  • Please create a [mre] of the *failing* program. We can't help you with code that works. :) – Some programmer dude Apr 14 '23 at 03:07
  • And if by "memory error" you mean you get a crash, then use a [*debugger*](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) to catch the crash and see when and where in your code it happens. Also examine all involved variables and their values and the time and place of the crash. Most likely you go out of bounds of your arrays in one way or another. For example, you have a check for `row` and `col` not being `-1`, but what if they're equal to or bigger than `width` or `height`? – Some programmer dude Apr 14 '23 at 03:09
  • If you *don't* get a crash, then use the debugger to step through your code, line by line, while monitoring variables and their values. That should help you figure out what wrong. – Some programmer dude Apr 14 '23 at 03:17
  • 1
    @Someprogrammerdude Hii thanks i fixed it, turns out i mixed up row and columns in w->rocks[i][j]. When u mentioned my assert function for rock, i realised i had commented it out cus it kept failing, and i jus realised is because i mixed up the rows and collumns. Thanks for ur help. – Alex Apr 14 '23 at 03:40

0 Answers0