Related
EDIT: Full code has now been posted so u can compile.
So we're a few first semester software students kind of stuck on a problem regarding structs in c. Stack overflow has helped me so many times already, so figured I'd actually try asking this time, as i couldn't seem to find what im looking for.
Our logic (see code below):
Main calls empty_trash
empty_trash (in its parameter) calls compare_trash
Compare trash parses through 4 areas (structs)
Compare trash checks if the average of our data is over a margin, if so
checks if that average is higher than firstly our empty struct,
which presumably has 0 average, and then if a higher is found that
one. This leaves us with the index of the struct with the highest
average
Compare trash returns this struct to empty trash, and an int
pointer of the index to main.
empty trash then goes through the subareas and checks their average of data and resets the ones over margin2
we return the reset area to main
in main we have an array of our structs 1-4. We assign the area returned from empty trash to arrayofstructs[index pointed back]
In our minds the logic makes sense, but it seems it's not working as our program crashes at the line in main. We think it's because we don't assign the struct correctly in main, but not 100% sure.
We're kinda baffled as both of these functions work fine on their own when we tested them seperately, but together they do not.
Any help would be much appreciated <3
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define MARGIN 70
#define MARGIN2 30
#define SIZE 5
struct subarea
{
int co2_cost, time;
double average, sensorData[SIZE];
};
struct area
{
struct subarea sub_area1, sub_area2, sub_area3, sub_area4;
double average;
};
struct area simmulated_days(struct area area, int lower_random, int upper_random);
struct area average_trash(struct area area);
struct area sensor_data_start(struct area area1);
struct area compare_trash_to_empty(struct area area1, struct area area2, struct area area3, struct area area4, int *);
struct area empty_trash(struct area chosen_area, int *co2_counter_p, int *time_counter_p);
int main(void)
{
int co2_counter, time_counter;
int day_counter = 0;
int *co2_counter_p = &co2_counter;
int *time_counter_p = &time_counter;
int area_number;
srand(time(NULL));
struct subarea subarea1_1 = {50, 50, 0, {}};
struct subarea subarea1_2 = {50, 50, 0, {}};
struct subarea subarea1_3 = {50, 50, 0, {}};
struct subarea subarea1_4 = {50, 50, 0, {}};
struct area area1 = {subarea1_1, subarea1_2, subarea1_3, subarea1_4, 0};
struct subarea subarea2_1 = {50, 50, 0, {}};
struct subarea subarea2_2 = {50, 50, 0, {}};
struct subarea subarea2_3 = {50, 50, 0, {}};
struct subarea subarea2_4 = {50, 50, 0, {}};
struct area area2 = {subarea2_1, subarea2_2, subarea2_3, subarea2_4, 0};
struct subarea subarea3_1 = {50, 50, 0, {}};
struct subarea subarea3_2 = {50, 50, 0, {}};
struct subarea subarea3_3 = {50, 50, 0, {}};
struct subarea subarea3_4 = {50, 50, 0, {}};
struct area area3 = {subarea3_1, subarea3_2, subarea3_3, subarea3_4, 0};
struct subarea subarea4_1 = {50, 50, 0, {}};
struct subarea subarea4_2 = {50, 50, 0, {}};
struct subarea subarea4_3 = {50, 50, 0, {}};
struct subarea subarea4_4 = {50, 50, 0, {}};
struct area area4 = {subarea4_1, subarea4_2, subarea4_3, subarea4_4, 0};
struct area useless_area = {};
struct area all_areas[5] = {useless_area, area1, area2, area3, area4};
struct area local_area = {};
area1 = sensor_data_start(area1);
area2 = sensor_data_start(area2);
area3 = sensor_data_start(area3);
area4 = sensor_data_start(area4);
int running = 1;
while (running)
{
area1 = simmulated_days(area1, 7, 10);
area2 = simmulated_days(area2, 4, 7);
area3 = simmulated_days(area3, 9, 12);
area4 = simmulated_days(area4, 6, 9);
for (int i = 0; i < SIZE; i++)
{
printf("%lf | %lf | %lf | %lf |\n", area1.sub_area1.sensorData[i], area2.sub_area1.sensorData[i], area3.sub_area1.sensorData[i], area4.sub_area1.sensorData[i]);
}
day_counter++;
printf("Day %d\n", day_counter);
area1 = average_trash(area1);
area2 = average_trash(area2);
area3 = average_trash(area3);
area4 = average_trash(area4);
printf("hihi\n");
all_areas[area_number] = empty_trash(compare_trash_to_empty(area1, area2, area3, area4, &area_number), co2_counter_p, time_counter_p);
printf("titi\n");
for (int i = 0; i < SIZE; i++)
{
printf("Local area %lf\t", local_area.sub_area1.sensorData[i]);
}
printf("\n");
if (day_counter == 2)
{
running = 0;
}
}
}
struct area simmulated_days(struct area area, int lower_random, int upper_random)
{
for (int i = 0; i < SIZE; i++)
{
area.sub_area1.sensorData[i] += ((rand() % (upper_random - lower_random + 1)) + lower_random);
area.sub_area2.sensorData[i] += ((rand() % (upper_random - lower_random + 1)) + lower_random);
area.sub_area3.sensorData[i] += ((rand() % (upper_random - lower_random + 1)) + lower_random);
area.sub_area4.sensorData[i] += ((rand() % (upper_random - lower_random + 1)) + lower_random);
}
return area;
}
//Average Trash Function
struct area average_trash(struct area area)
{
double sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;
for (int i = 0; i < SIZE; i++)
{
sum1 += area.sub_area1.sensorData[i];
sum2 += area.sub_area2.sensorData[i];
sum3 += area.sub_area3.sensorData[i];
sum4 += area.sub_area4.sensorData[i];
}
area.sub_area1.average = sum1 / SIZE;
area.sub_area2.average = sum2 / SIZE;
area.sub_area3.average = sum3 / SIZE;
area.sub_area4.average = sum4 / SIZE;
area.average = (area.sub_area1.average + area.sub_area2.average + area.sub_area3.average + area.sub_area4.average) / 4;
return area;
}
struct area sensor_data_start(struct area area1)
{
double x = 75;
for (int i = 0; i < SIZE; i++)
{
area1.sub_area1.sensorData[i] = x;
area1.sub_area2.sensorData[i] = x;
area1.sub_area3.sensorData[i] = x;
area1.sub_area4.sensorData[i] = x;
}
return area1;
}
struct area compare_trash_to_empty(struct area area1, struct area area2, struct area area3, struct area area4, int *area_number_p)
{
struct area local_area = {};
int i, highBlock = 0;
struct area block[5] = {local_area, area1, area2, area3, area4};
for (i = 1; i <= 4; i++)
{
if (block[i].average >= MARGIN)
{
if (block[i].average > block[highBlock].average)
{
highBlock = i;
}
}
}
*area_number_p = highBlock;
return block[highBlock];
}
struct area empty_trash(struct area chosen_area, int *co2_counter_p, int *time_counter_p)
{
int co2_counter = 0;
int time_counter = 0;
if (chosen_area.sub_area1.average > MARGIN2)
{
co2_counter += chosen_area.sub_area1.co2_cost;
time_counter += chosen_area.sub_area1.time;
chosen_area.sub_area1.average = 0;
for (int i = 0; i < SIZE; i++)
{
chosen_area.sub_area1.sensorData[i] = 0;
printf("ET %lf\t", chosen_area.sub_area1.sensorData[i]);
}
printf("\n");
}
if (chosen_area.sub_area2.average > MARGIN2)
{
co2_counter += chosen_area.sub_area2.co2_cost;
time_counter += chosen_area.sub_area2.time;
chosen_area.sub_area2.average = 0;
for (int i = 0; i < SIZE; i++)
{
chosen_area.sub_area2.sensorData[i] = 0;
}
}
if (chosen_area.sub_area3.average > MARGIN2)
{
co2_counter += chosen_area.sub_area3.co2_cost;
time_counter += chosen_area.sub_area3.time;
chosen_area.sub_area3.average = 0;
for (int i = 0; i < SIZE; i++)
{
chosen_area.sub_area3.sensorData[i] = 0;
}
}
if (chosen_area.sub_area4.average > MARGIN2)
{
co2_counter += chosen_area.sub_area4.co2_cost;
time_counter += chosen_area.sub_area4.time;
chosen_area.sub_area4.average = 0;
for (int i = 0; i < SIZE; i++)
{
chosen_area.sub_area4.sensorData[i] = 0;
}
}
*co2_counter_p = co2_counter;
*time_counter_p = time_counter;
return chosen_area;
}
My original comment:
Side note: Whenever I see (e.g.) v1 v2 v3 v4 v5 I want to replace it with an array v[5]. So, in struct area, you want: struct subarea sub_area[5]; This will greatly simplify your code. You already do this in main –
Craig Estey
Your response:
#Craig Estey Ye don't have a huge experience with debuggers yet, usually just use printfs, but sounds very helpful so ill youtube a guide side note: very helpful we didn't foresee this at first but would simplify so much, ty4input –
Thybo
I've done better(?) I've done the preliminary restructuring of your code. I believe this will be helpful to others in addition to yourselves.
I'm sorry, but (and I'm saying this with kindness), the code needs a lot of restructuring. The sheer [needless] complexity could be masking numerous bugs.
Things to note:
Passing a struct by value is hazardous. It is legal, but it makes the code complicated. Passing by pointer is 99.44% of the time better. You can just modify the given struct "in-place" rather than having to return it [again, by value].
Learn about iterating through an array by using a pointer to the "current" element instead of an index. You'll see this in the FORALL loop below.
Don't "replicate" code. Notice what happens when using arrays. Instead of (e.g) four copies of the code, we have one
Instead of 4 areas (e.g. area1, area2, area3, area4), if we had 10,000 areas. Would you replicate the code 10,000 times as was done in (e.g.) empty_trash?
I added typedef for your two struct to simplify things a bit.
I've added a few advanced techniques, such as the use of the FORALL macro to traverse arrays.
I've used preprocessor conditionals to denote old code vs new:
#if 0
// old code
#else
// new code
#endif
I've done some/most of the editing. I've compiled it. I could have made a zillion mistakes. But, it should give you the idea:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define MARGIN 70
#define MARGIN2 30
#define SIZE 5
#define NAREA 4
typedef struct subarea {
int co2_cost, time;
double average, sensorData[SIZE];
} subarea_t;
typedef struct area {
#if 0
struct subarea sub_area1, sub_area2, sub_area3, sub_area4;
#else
subarea_t sub_area[NAREA];
#endif
double average;
} area_t;
#define COUNTOF(_arr) \
(sizeof(_arr) / sizeof(_arr[0]))
#define FORALL(_ptr,_arr) \
__typeof__(_arr[0]) *_ptr = &_arr[0]; _ptr < &_arr[COUNTOF(_arr)]; ++_ptr
void
simulated_days(area_t *area, int lower_random, int upper_random)
{
for (FORALL(sub,area->sub_area)) {
for (FORALL(data,sub->sensorData)) {
*data += ((rand() % (upper_random - lower_random + 1)) +
lower_random);
}
}
}
//Average Trash Function
void
average_trash(area_t *area)
{
double sum[NAREA] = { 0 };
int i;
#if 0
for (int i = 0; i < SIZE; i++) {
sub[i] = a
sum1 += area.sub_area1.sensorData[i];
sum2 += area.sub_area2.sensorData[i];
sum3 += area.sub_area3.sensorData[i];
sum4 += area.sub_area4.sensorData[i];
}
#else
for (FORALL(sub,area->sub_area), ++i) {
i = 0;
for (FORALL(data,sub->sensorData), ++i)
sum[i] += *data;
}
#endif
#if 0
area.sub_area1.average = sum1 / SIZE;
area.sub_area2.average = sum2 / SIZE;
area.sub_area3.average = sum3 / SIZE;
area.sub_area4.average = sum4 / SIZE;
#else
i = 0;
for (FORALL(sub,area->sub_area), ++i)
sub->average = sum[i] / SIZE;
#endif
#if 0
area.average = (area.sub_area1.average +
area.sub_area2.average +
area.sub_area3.average +
area.sub_area4.average) / 4;
#else
area->average = 0;
for (FORALL(sub,area->sub_area))
area->average += sub->average;
area->average /= NAREA;
#endif
}
#if 0
area_t
sensor_data_start(area_t area1)
{
double x = 75;
for (int i = 0; i < SIZE; i++) {
area1.sub_area1.sensorData[i] = x;
area1.sub_area2.sensorData[i] = x;
area1.sub_area3.sensorData[i] = x;
area1.sub_area4.sensorData[i] = x;
}
return area1;
}
#else
void
sensor_data_start(area_t *area)
{
double x = 75;
for (FORALL(sub,area->sub_area)) {
for (FORALL(data,sub->sensorData))
*data = x;
}
}
#endif
#if 0
area_t
compare_trash_to_empty(area_t area1, area_t area2, area_t area3, area_t area4, int *area_number_p)
{
area_t local_area = { };
int i,
highBlock = 0;
area_t block[5] = { local_area, area1, area2, area3, area4 };
for (i = 1; i <= 4; i++) {
if (block[i].average >= MARGIN) {
if (block[i].average > block[highBlock].average) {
highBlock = i;
}
}
}
*area_number_p = highBlock;
return block[highBlock];
}
#else
area_t *
compare_trash_to_empty(const area_t *blocks, area_t *all_areas)
{
area_t local_area = { };
int i, highBlock = 0;
#if 0
area_t block[5] = { local_area, area1, area2, area3, area4 };
#else
const area_t *block;
#endif
for (i = 1; i < NAREA; ++i) {
block = &blocks[i];
if (block->average >= MARGIN) {
if (block->average > blocks[highBlock].average)
highBlock = i;
}
}
all_areas[highBlock] = blocks[highBlock];
return &all_areas[highBlock];
}
#endif
#if 0
area_t
empty_trash(area_t chosen_area, int *co2_counter_p, int *time_counter_p)
{
int co2_counter = 0;
int time_counter = 0;
if (chosen_area.sub_area1.average > MARGIN2) {
co2_counter += chosen_area.sub_area1.co2_cost;
time_counter += chosen_area.sub_area1.time;
chosen_area.sub_area1.average = 0;
for (int i = 0; i < SIZE; i++) {
chosen_area.sub_area1.sensorData[i] = 0;
printf("ET %lf\t", chosen_area.sub_area1.sensorData[i]);
}
printf("\n");
}
if (chosen_area.sub_area2.average > MARGIN2) {
co2_counter += chosen_area.sub_area2.co2_cost;
time_counter += chosen_area.sub_area2.time;
chosen_area.sub_area2.average = 0;
for (int i = 0; i < SIZE; i++) {
chosen_area.sub_area2.sensorData[i] = 0;
}
}
if (chosen_area.sub_area3.average > MARGIN2) {
co2_counter += chosen_area.sub_area3.co2_cost;
time_counter += chosen_area.sub_area3.time;
chosen_area.sub_area3.average = 0;
for (int i = 0; i < SIZE; i++) {
chosen_area.sub_area3.sensorData[i] = 0;
}
}
if (chosen_area.sub_area4.average > MARGIN2) {
co2_counter += chosen_area.sub_area4.co2_cost;
time_counter += chosen_area.sub_area4.time;
chosen_area.sub_area4.average = 0;
for (int i = 0; i < SIZE; i++) {
chosen_area.sub_area4.sensorData[i] = 0;
}
}
*co2_counter_p = co2_counter;
*time_counter_p = time_counter;
return chosen_area;
}
#else
void
empty_trash(area_t *chosen_area, int *co2_counter_p, int *time_counter_p)
{
int co2_counter = 0;
int time_counter = 0;
for (FORALL(sub,chosen_area->sub_area)) {
if (sub->average > MARGIN2) {
co2_counter += sub->co2_cost;
time_counter += sub->time;
for (FORALL(data,sub->sensorData))
*data = 0;
}
}
*co2_counter_p = co2_counter;
*time_counter_p = time_counter;
}
#endif
int
main(void)
{
int co2_counter, time_counter;
int day_counter = 0;
int *co2_counter_p = &co2_counter;
int *time_counter_p = &time_counter;
int area_number;
srand(time(NULL));
#if 0
subarea_t subarea1_1 = { 50, 50, 0, {} };
subarea_t subarea1_2 = { 50, 50, 0, {} };
subarea_t subarea1_3 = { 50, 50, 0, {} };
subarea_t subarea1_4 = { 50, 50, 0, {} };
area_t area1 = { subarea1_1, subarea1_2, subarea1_3, subarea1_4, 0 };
subarea_t subarea2_1 = { 50, 50, 0, {} };
subarea_t subarea2_2 = { 50, 50, 0, {} };
subarea_t subarea2_3 = { 50, 50, 0, {} };
subarea_t subarea2_4 = { 50, 50, 0, {} };
area_t area2 = { subarea2_1, subarea2_2, subarea2_3, subarea2_4, 0 };
subarea_t subarea3_1 = { 50, 50, 0, {} };
subarea_t subarea3_2 = { 50, 50, 0, {} };
subarea_t subarea3_3 = { 50, 50, 0, {} };
subarea_t subarea3_4 = { 50, 50, 0, {} };
area_t area3 = { subarea3_1, subarea3_2, subarea3_3, subarea3_4, 0 };
subarea_t subarea4_1 = { 50, 50, 0, {} };
subarea_t subarea4_2 = { 50, 50, 0, {} };
subarea_t subarea4_3 = { 50, 50, 0, {} };
subarea_t subarea4_4 = { 50, 50, 0, {} };
area_t area4 = { subarea4_1, subarea4_2, subarea4_3, subarea4_4, 0 };
#else
area_t areamain[NAREA];
for (FORALL(area,areamain)) {
for (FORALL(sub,area->sub_area)) {
sub->co2_cost = 50;
sub->time = 50;
sub->average = 50;
for (FORALL(data,sub->sensorData))
*data = 0.0;
}
}
#endif
#if 0
area_t useless_area = { };
area_t all_areas[5] = { useless_area, area1, area2, area3, area4 };
#else
area_t *all_areas = areamain;
#endif
area_t local_area = { };
#if 0
area1 = sensor_data_start(area1);
area2 = sensor_data_start(area2);
area3 = sensor_data_start(area3);
area4 = sensor_data_start(area4);
#else
for (FORALL(area,areamain))
sensor_data_start(area);
#endif
int running = 1;
while (running) {
simulated_days(&areamain[0], 7, 10);
simulated_days(&areamain[1], 4, 7);
simulated_days(&areamain[2], 9, 12);
simulated_days(&areamain[3], 6, 9);
#if 0
for (int i = 0; i < SIZE; i++) {
printf("%lf | %lf | %lf | %lf |\n",
area1.sub_area1.sensorData[i],
area2.sub_area1.sensorData[i],
area3.sub_area1.sensorData[i],
area4.sub_area1.sensorData[i]);
}
#else
for (int i = 0; i < SIZE; i++) {
for (FORALL(area,areamain))
printf("%lf |",area->sub_area[i]);
printf("\n");
}
#endif
day_counter++;
printf("Day %d\n", day_counter);
#if 0
area1 = average_trash(area1);
area2 = average_trash(area2);
area3 = average_trash(area3);
area4 = average_trash(area4);
#else
for (FORALL(area,areamain))
average_trash(area);
#endif
printf("hihi\n");
#if 0
all_areas[area_number] =
empty_trash(compare_trash_to_empty(area1, area2, area3, area4,
&area_number), co2_counter_p, time_counter_p);
#else
area_t *area_out = compare_trash_to_empty(areamain,all_areas);
empty_trash(area_out, co2_counter_p, time_counter_p);
#endif
printf("titi\n");
#if 0
for (int i = 0; i < SIZE; i++) {
printf("Local area %lf\t", local_area.sub_area1.sensorData[i]);
}
printf("\n");
#else
do {
subarea_t *sub = area_out->sub_area;
printf("Local area ");
for (FORALL(data,sub->sensorData))
printf("%f\t", *data);
printf("\n");
} while (0);
#endif
if (day_counter == 2) {
running = 0;
}
}
}
I have trouble getting my dynamic int array to work properly. I have tried some examples but still can not get it to work. I think I am doing a minor pointer problem but I cannot figure out what. I want to have a dynamic int array and then from another function add numbers to this array. I have gotten the counter to work.
I have tried putting * at different places and trying my way but I am at this point lacking the knowledge to actually know where the * should be. I know some basics about & and * but apparently not enough
static void counterFunction(int* pointerToArray[], int* count)
{
while (*count < 10) {
*(*pointerToArray + *count) = *count;
*count = *count + 1;
}
}
static int* writeSortedToArray(void)
{
// I need to store 1000 numbers at this point
int* dynamicArray = malloc(1000 * sizeof(int));
int counter = 0;
counterFunction(&dynamicArray, &counter);
return 0;
}
The counter works properly, the dynamic array does not work at all. It only store a 0 according to my debugger (xcode)
To add to the other answers, I'd suggest a more generic approach and encapsulation of the management logic:
#include <assert.h> // assert()
#include <stddef.h> // size_t
#include <stdbool.h> // bool, true, false
#include <stdlib.h> // malloc(), calloc(), free(), EXIT_FAILURE, EXIT_SUCCESS
#include <stdio.h> // fputs(), printf(), putchar()
typedef int value_type;
char const *conversion_specifier = "%d"
size_t const initial_capacity = 10
size_t growth_factor = 2
typedef struct dynarray_tag {
size_t size;
size_t capacity;
value_type *data;
} dynarray_t;
dynarray_t dynarray_create(void)
{
dynarray_t new_dynarray = { 0, 0, NULL };
return new_dynarray;
}
dynarray_t dynarray_create_reserve(size_t capacity)
{
dynarray_t new_dynarray = { 0, capacity, NULL };
new_dynarray.data = malloc(capacity * sizeof *new_dynarray.data);
return new_dynarray;
}
dynarray_t dynarray_create_size(size_t size)
{
dynarray_t new_dynarray = { size, size, NULL };
new_dynarray.data = calloc(size, sizeof *new_dynarray.data);
return new_dynarray;
}
bool dynarray_is_valid(dynarray_t const *dynarray)
{
if (!dynarray)
return false;
if (!dynarray->size && !dynarray->capacity && !dynarray->data)
return true;
if (dynarray->size > dynarray->capacity)
return false;
if (dynarray->capacity && dynarray->data)
return true;
return false;
}
size_t dynarray_get_size(dynarray_t const *dynarray)
{
assert(dynarray_is_valid(dynarray));
return dynarray->size;
}
size_t dynarray_get_capacity(dynarray_t const *dynarray)
{
assert(dynarray_is_valid(dynarray));
return dynarray->capacity;
}
value_type* dynarray_at(dynarray_t *dynarray, size_t position)
{
assert(dynarray_is_valid(dynarray) && dynarray->size && position < dynarray->size);
return &dynarray->data[position];
}
value_type* dynarray_front(dynarray_t *dynarray)
{
assert(dynarray_is_valid(dynarray));
return dynarray_at(dynarray, 0);
}
value_type* dynarray_back(dynarray_t *dynarray)
{
assert(dynarray_is_valid(dynarray));
return dynarray_at(dynarray, dynarray->size - 1);
}
bool dynarray_reserve(dynarray_t *dynarray, size_t new_capacity)
{
assert(dynarray_is_valid(dynarray));
if (new_capacity <= dynarray->capacity)
return true;
if (new_capacity < dynarray->size)
return false;
value_type *new_data = realloc(dynarray->data, new_capacity * sizeof *new_data);
if (!new_data)
return false;
dynarray->data = new_data;
dynarray->capacity = new_capacity;
return true;
}
bool dynarray_resize(dynarray_t *dynarray, size_t new_size)
{
assert(dynarray_is_valid(dynarray));
if (new_size <= dynarray->capacity)
return true;
value_type *new_data = realloc(dynarray->data, new_size * sizeof *new_data);
if (!new_data)
return false;
dynarray->data = new_data;
dynarray->size = new_size;
dynarray->capacity = new_size;
return true;
}
bool dynarray_insert(dynarray_t *dynarray, size_t position, value_type value)
{
assert(dynarray_is_valid(dynarray));
if (dynarray->size + 1 > dynarray->capacity) {
size_t new_capacity = dynarray->capacity ? dynarray->capacity * growth_factor : initial_capacity;
if (!dynarray_reserve(dynarray, new_capacity))
return false;
}
for (size_t i = dynarray->size; i > position; --i)
dynarray->data[i] = dynarray->data[i - 1];
dynarray->data[position] = value;
dynarray->size++;
return true;
}
bool dynarray_push_front(dynarray_t *dynarray, value_type value)
{
assert(dynarray_is_valid(dynarray));
return dynarray_insert(dynarray, 0, value);
}
bool dynarray_push_back(dynarray_t *dynarray, value_type value)
{
assert(dynarray_is_valid(dynarray));
return dynarray_insert(dynarray, dynarray->size, value);
}
bool dynarray_insert_sorted(dynarray_t *dynarray, value_type value)
{
assert(dynarray_is_valid(dynarray));
if (!dynarray_get_size(dynarray) || value < *dynarray_front(dynarray))
return dynarray_push_front(dynarray, value);
if (value > *dynarray_back(dynarray))
return dynarray_push_back(dynarray, value);
size_t insert_pos = 0;
for (; insert_pos < dynarray->size && value > dynarray->data[insert_pos]; ++insert_pos);
return dynarray_insert(dynarray, insert_pos, value);
}
void dynarray_print(dynarray_t const *dynarray)
{
assert(dynarray_is_valid(dynarray));
for (size_t i = 0; i < dynarray->size; ++i) {
printf(conversion_specifier, dynarray->data[i]);
if (i + 1 < dynarray->size)
printf(", ");
}
}
void dynarray_sort(dynarray_t *dynarray) // insertion sort
{
assert(dynarray_is_valid(dynarray));
for (size_t i = 1; i < dynarray->size; i++) {
value_type key = dynarray->data[i];
size_t k = i - 1;
for (; k >= 0 && dynarray->data[k] > key; --k)
dynarray->data[k + 1] = dynarray->data[k];
dynarray->data[k + 1] = key;
}
}
void dynarray_free(dynarray_t *dynarray)
{
assert(dynarray_is_valid(dynarray));
free(dynarray->data);
dynarray->size = dynarray->capacity = 0;
dynarray->data = NULL;
}
int main(void)
{
dynarray_t arr = dynarray_create();
if (!dynarray_is_valid(&arr)) {
fputs("Not enough memory. :(\n\n", stderr);
return EXIT_FAILURE;
}
int result = EXIT_FAILURE;
for (value_type i = 2; i < 15; i += 2) {
if (!dynarray_push_back(&arr, i))
goto error_exit;
}
dynarray_print(&arr);
putchar('\n');
for (value_type i = 1; i < 14; i += 2) {
if (i != 7) {
if (!dynarray_push_front(&arr, i))
goto error_exit;
}
}
dynarray_print(&arr);
putchar('\n');
dynarray_sort(&arr);
dynarray_print(&arr);
putchar('\n');
if (!dynarray_insert_sorted(&arr, 0))
goto error_exit;
dynarray_print(&arr);
putchar('\n');
if (!dynarray_insert_sorted(&arr, 15))
goto error_exit;
dynarray_print(&arr);
putchar('\n');
if (!dynarray_insert_sorted(&arr, 7))
goto error_exit;
dynarray_print(&arr);
putchar('\n');
result = EXIT_SUCCESS;
error_exit:
result == EXIT_FAILURE && fputs("Not enough memory. :(\n\n", stderr);
dynarray_free(&arr);
return result;
}
Output:
2, 4, 6, 8, 10, 12, 14
13, 11, 9, 5, 3, 1, 2, 4, 6, 8, 10, 12, 14
1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14
0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14
0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
Todo:
dynarray_insert_range()
dynarray_create_init() from iterator pair
dynarray_from_file()
dynarray_copy()
dynarray_begin()
dynarray_end()
...
You make some mistakes:
1) int* pointerToArray[] is a pointer to pointer(s). You should use int* pointerToArray.
2) *(*pointerToArray+*count)=*count; is dereferencing pointerToArray two times, you should use *(pointerToArray + *count) = *count;.
3) dynamicArrayis already a pointer, you should not use the &operator to get its address. Then counterFunction(&dynamicArray, &counter);should be converted in counterFunction(dynamicArray, &counter);.
Finally, your code should look like:
#include <stdio.h>
#include <stdlib.h>
static void counterFunction(int * pointerToArray, int * count){
while (*count < 10) {
*(pointerToArray + *count) = *count;
*count += 1;
}
}
static int * writeSortedToArray(){
//I need to store 1000 numbers at this point
int * dynamicArray = malloc(100 * sizeof(int));
int counter = 0;
counterFunction(dynamicArray, &counter);
// as suggested, finally release the array
free(dynamicArray);
return 0;
}
int main(){
writeSortedToArray();
return 0;
}
static void counterFunction(int array[], int* count)
{
ptrdiff_t i;
for (i = *count; i < 10; i++)
array[i] = i;
*count = i;
}
static int *writeSortedToArray(void)
{
//I need to store 1000 numbers at this point
int *dynamicArray;
int counter;
dynamicArray = calloc(sizeof(*dynamicArray) * 1000);
counter = 0;
counterFunction(dynamicArray, &counter);
/* counter == 10 */
return dynamicArray;
}
First of all, if a function always returns 0, it should be void (except main(), for its own reasons). Although you probably didn't want to return 0, and instead return the array.
The counter function doesn't need to know that the array is dynamic. It can just accept any array, and use it with array notation.
I changed to a for loop, because it's more natural.
You don't need to pass a pointer to the array, and in fact you shouldn't, because then the compiler could notice the difference between a pointer to an array and a pointer to a pointer, and complain.
I don't get the purpose of your code, but this code is just the corrected version of your code.
Remember to free(dynamicArray); at some point.
Wrong use of pointer here. Your Dynamicarray from the WriteSortedToArray is already an adress so you do not need to pass it as an adress.
This should work :
static void counterFunction(int* pointerToArray, int count){
while (count < 10)
{
pointerToArray[count] = count;
count++;
}
}
static int* writeSortedToArray(void){
int* dynamicArray = malloc(1000 * sizeof(int));
int counter = 0;
counterFunction(dynamicArray, counter);
return 0;
}
If you want to keep the value of your counter when exiting your counterFunction which is 10, do this instead :
static void counterFunction(int* pointerToArray, int *count){
while (*count < 10)
{
pointerToArray[*count] = *count;
*count++;
}
}
static int* writeSortedToArray(void){
int* dynamicArray = malloc(1000 * sizeof(int));
int counter = 0;
counterFunction(dynamicArray, &counter);
return 0;
}
You should always free your memory using the free function to avoid memory leak issues.
free(dynamicArray)
I'm writing a program calculating the shortest way from point A to point B.
I have a map (matrix) with values:
0 is block (wall, no way to pass);
1 is free way (you can pass);
2 is start point;
In the code below I declare 2 arrays: an array " map"and changed array "visited" while running program demonstrating visited points.
I check the cells in 4 directions (not diagonals) for 1 or 0. If it's 1 (possible to pass), I increase the counter for 1. For do not count the previous cell I'm trying to avoid it by the condition. I realized that in two one-dimensional arrays {1 0 -1 0} and { 0, 1, 0, -1 } to check neighbor points (what mean i check [i+1][j], [i-1][j], [i][j+1] and [i][j-1]).
As a result I wanna see "visited" matrix with a few lines which shows the way to reach to the point B (1, 2, 3, ... 15). I wanna find the way to map[7][7] point.
Right now the error here that I do count++ for the previous position. How to avoid that?
Thank you.
P.S. I wrote a few functions implementing a new array with 0 values, counting free to go cells and printing arrays.
main.c:
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#define WIDTH 8
#define HEIGHT 8
int mapZero(int map[WIDTH][HEIGHT]);
int mapPrint(int map[WIDTH][HEIGHT]);
int mapInit(int map[WIDTH][WIDTH]);
int findFreeToGoCells(int map[WIDTH][HEIGHT]);
int main(int argc, char * argv[])
{
bool stop;
unsigned int count;
unsigned int max;
int visited[WIDTH][HEIGHT];
int map[WIDTH][HEIGHT] =
{
{ 1, 1, 1, 1, 1, 0, 0, 1 },
{ 0, 1, 1, 1, 1, 1, 0, 1 },
{ 0, 0, 1, 0, 1, 1, 1, 0 },
{ 1, 0, 1, 1, 1, 0, 1, 1 },
{ 0, 0, 0, 1, 0, 0, 0, 1 },
{ 1, 0, 1, 1, 1, 0, 0, 1 },
{ 0, 0, 0, 0, 1, 0, 0, 1 },
{ 0, 1, 1, 1, 1, 1, 1, 1 },
};
mapZero(visited);
printf("Matrix of zeroed-visited cells:\n\n");
mapPrint(visited);
printf("Matrix of the map:\n\n");
mapPrint(map);
printf("Free to go cells: %d\n\n", findFreeToGoCells(map));
max = WIDTH * HEIGHT - 1;
visited[0][0] = map[0][0];
count = 0;
visited[0][0] = 0;
int di[4] = { 1, -1, 0, 0 };
int dj[4] = { 0, 0, 1, -1 };
//do
{
for (int i = 0; i < WIDTH; ++i)
{
for (int j = 0; j < HEIGHT; ++j)
{
if (visited[i][j] == count)
{
for (int k = 0; k < 4; ++k)
{
int i_check = i + di[k];
int j_check = j + dj[k];
if ((i_check >= 0 && i_check < WIDTH) && (j_check >= 0 && j_check < HEIGHT) && (map[i_check][j_check] != 0))
{
visited[i_check][j_check] = count + 1;
}
}
count++;
}
}
}
}// while (visited[7][7] == 0);
if (count > max + 99999)
printf("The way couldn't be found\n");
else
{
printf("Matrix of visited cells:\n\n");
mapPrint(visited);
printf("Free to go cells from [0][0] to [7][7]: %d\n", findFreeToGoCells(visited));
}
/*************************************************************************************/
/*************************************************************************************/
int len;
int x = 7;
int y = 7;
int x_path[WIDTH * HEIGHT];
int y_path[WIDTH * HEIGHT];
len = visited[7][7];
count = len;
while (count > 0)
{
x_path[count] = x;
y_path[count] = y;
count--;
for (int k = 0; k < 4; ++k)
{
int i_check = x + di[k];
int j_check = y + dj[k];
if ((i_check >= 0 && i_check < WIDTH) && (j_check >= 0 && j_check < HEIGHT) && (map[i_check][j_check] == count))
{
x = x + di[k];
y = y + dj[k];
break;
}
}
}
x_path[0] = 0;
y_path[0] = 0;
printf("\nThe shortest way consist of %d cells\nThere are %d the shortest way to reach th the final point\n\n", len, findFreeToGoCells(visited)-len);
system("pause");
return 0;
}
int mapZero(int map[WIDTH][HEIGHT])
{
for (int i = 0; i < WIDTH; ++i)
{
for (int j = 0; j < HEIGHT; ++j)
{
map[i][j] = 0;
}
}
return 0;
}
int mapPrint(int map[WIDTH][HEIGHT])
{
for (int i = 0; i < WIDTH; ++i)
{
for (int j = 0; j < HEIGHT; ++j)
{
printf("%2d ", map[i][j]);
}
printf("\n\n");
}
printf("\n");
return 0;
}
int findFreeToGoCells(int map[WIDTH][HEIGHT])
{
int count = 0;
for (int i = 0; i < WIDTH; ++i)
{
for (int j = 0; j < HEIGHT; ++j)
{
if (map[i][j] != 0) count++;
}
}
return count;
}
Result:
I am writing a max-heap, which can change the priority/value. However, I have problems to understand what is wrong in my code.
I have followed this as reference: ref
This is my code (I have hide some functions since it not the focus here)
static void swap(MAX_HEAP *heap, int i, int j);
static void swim(MAX_HEAP *heap, int k);
static void sink(MAX_HEAP *heap, int k);
void swap(MAX_HEAP *heap, int i, int j) {
HEAP_ELEM s;
int k;
s = heap->binary_heap[i];
k = heap->keys[s.fu];
heap->binary_heap[i] = heap->binary_heap[j];
heap->keys[k] = heap->keys[heap->binary_heap[j].fu];
heap->keys[heap->binary_heap[j].fu] = k;
heap->binary_heap[j] = s;
}
void swim(MAX_HEAP *heap, int k) {
int m;
m = k / 2.0;
while (k > 1 && heap->binary_heap[m].priority < heap->binary_heap[k].priority) {
swap(heap, k, m);
k = m;
m = k / 2.0;
}
}
void sink(MAX_HEAP *heap, int k) {
int j;
while (2 * k <= heap->n) {
j = 2 * k;
if (j < heap->n && heap->binary_heap[j].priority < heap->binary_heap[j + 1].priority)
j++;
if (!(heap->binary_heap[k].priority < heap->binary_heap[j].priority))
break;
swap(heap, k, j);
k = j;
}
}
MAX_HEAP *create_maxheap(int capacity) {
int i;
MAX_HEAP *ret;
ret = (MAX_HEAP*) malloc(sizeof (MAX_HEAP));
ret->n = 0;
ret->binary_heap = (HEAP_ELEM*) malloc(sizeof (HEAP_ELEM) * (capacity + 1));
ret->binary_heap[0].fu = 0;
ret->binary_heap[0].priority = 0;
ret->max = capacity;
ret->keys = (int*) malloc(sizeof (int) * (capacity + 1));
for (i = 0; i <= capacity + 1; i++) {
ret->keys[i] = -1;
}
return ret;
}
HEAP_ELEM get_maxheap(MAX_HEAP *heap) {
HEAP_ELEM ret;
if (heap->n == 0) {
return;
}
ret = heap->binary_heap[1];
heap->keys[ret.fu] = -1;
swap(heap, 1, heap->n);
heap->n--;
sink(heap, 1);
return ret;
}
void insert_maxheap(MAX_HEAP *heap, int fu, int p) {
if (heap->n + 1 >= heap->max) {
int i;
heap->max *= 2;
heap->keys = (int*) realloc(heap->keys, sizeof (int) * (heap->max + 1));
heap->binary_heap = (HEAP_ELEM*) realloc(heap->binary_heap, sizeof (HEAP_ELEM) * (heap->max + 1));
for (i = heap->n+1; i < heap->max + 1; i++) {
heap->keys[i] = -1;
}
}
heap->n++;
heap->binary_heap[heap->n].fu = fu;
heap->binary_heap[heap->n].priority = p;
heap->keys[fu] = heap->n;
swim(heap, heap->n);
}
void modify_maxheap(MAX_HEAP *heap, int fu, int p) {
int i;
i = heap->keys[fu];
int old;
if (i == -1) {
insert_maxheap(heap, fu, p);
return;
}
old = heap->binary_heap[i].priority;
heap->binary_heap[i].fu = fu;
heap->binary_heap[i].priority = p;
heap->keys[fu] = i;
if (old < p) {
/* we need to bubble up*/
swim(heap, i);
} else if (old > p) {
//we need to bubble down
sink(heap, i);
}
}
When I have the following execution, it gives bad results... what is wrong here? For instance...
int main(int argc, char** argv) {
MAX_HEAP *heap, *heap2;
HEAP_ELEM he;
heap = create_maxheap(3);
modify_maxheap(heap, 1, 7);
modify_maxheap(heap, 2, 10);
modify_maxheap(heap, 3, 78);
modify_maxheap(heap, 4, 3);
modify_maxheap(heap, 5, 45);
printf("heap 1\n\n");
while(heap->n > 0) {
he = get_maxheap(heap);
printf("..fu: %d; value: %d\n", he.fu, he.priority);
}
printf("max size of heap1: %d\n", heap->max);
printf("\n\n");
heap2 = create_maxheap(10);
modify_maxheap(heap2, 3, 90);
modify_maxheap(heap2, 1, 7);
modify_maxheap(heap2, 2, 10);
modify_maxheap(heap2, 3, 9);
modify_maxheap(heap2, 3, 92);
modify_maxheap(heap2, 4, 3);
modify_maxheap(heap2, 3, 90);
modify_maxheap(heap2, 1, 99);
modify_maxheap(heap2, 5, 45);
modify_maxheap(heap2, 1, 89);
printf("heap 2\n\n");
while(heap2->n > 0) {
he = get_maxheap(heap2);
printf("fu: %d; value: %d\n", he.fu, he.priority);
}
return (EXIT_SUCCESS);
}
Note that I am using an array to store the indices of HEAP_ELEM in order to know the position of a HEAP_ELEM (which has as primary key the "fu" and change its priority. This is my output:
heap 1
..fu: 3; value: 78
..fu: 5; value: 45
..fu: 2; value: 10
..fu: 1; value: 7
..fu: 4; value: 3
max size of heap1: 6
heap 2
fu: 1; value: 99
fu: 3; value: 90
fu: 1; value: 89
fu: 5; value: 45
fu: 4; value: 3
I have changed my modify_maxheap function and it worked:
void modify_maxheap(MAX_HEAP *heap, int fu, int p) {
int i;
i = heap->keys[fu];
if (i == -1) {
insert_maxheap(heap, fu, p);
return;
}
heap->binary_heap[i].priority = p;
swim(heap, i);
sink(heap, i);
}
The reason is that we have to bubble-up and bubble-down in case of any modification to guarantee the heap condition. I hope it can serve as base for someone.
So I have this code thats supposed to do this
// REQUIRES: n >= 1. Elements a[0] ... a[n-1] exist.
// PROMISES
// If n == 1, returns 1.
// Returns 1 if all of a[0] <= a[1] ... a[n-2] <= a[n-1] are true.
// Otherwise, returns 0.
#include <assert.h>
#include "array-utils4F.h"
#define UNIT_TESTS 1
int is_sorted(const int *a, int n)
{
assert (n >= 1);
if (n == 1)
return 1;
int k ;
for (k = 1; k < n ; k++) {
if (a[k-1] > a[k])
return 0;
return 1;
}
}
int max_el(const int *a, int n)
{
assert(n >= 1);
int result = 0, i;
for (i = 0; i < n; i++)
if (a[i] > result)
result = a[i];
return result;
}
#ifdef UNIT_TESTS
#include <stdio.h>
#define COUNT(x) (sizeof(x)/sizeof(x[0]))
void test_is_sorted(const char *tag, const int *a, int n, int expected_rv);
void test_max_el(const char *tag, const int *a, int n, int expected_rv);
int main(void)
{
int test_01[] = { 10, 20, 30, 40, 50 };
int test_02[] = { 10, 10, 10, 10 };
int test_03[] = { 10, 20, 30, 40, 35 };
int test_04[] = { 10, 20, 30, 25, 40 };
int test_05[] = { 10, 5, 15, 25 };
test_is_sorted("test_01", test_01, COUNT(test_01), 1);
test_is_sorted("test_02", test_02, COUNT(test_02), 1);
test_is_sorted("test_03", test_03, COUNT(test_03), 0);
test_is_sorted("test_04", test_04, COUNT(test_04), 0);
test_is_sorted("test_05", test_05, COUNT(test_05), 0);
fputc('\n', stdout);
int test_06[] = { 100, 1, 2, 3 };
int test_07[] = { 1, 2, 100, 3 };
int test_08[] = { 1, 2, 3, 100 };
int test_09[] = { -1, -2, -3, -4 };
int test_10[] = { -8, -7, -6, -7, -8 };
test_max_el("test_06", test_06, COUNT(test_06), 100);
test_max_el("test_07", test_07, COUNT(test_07), 100);
test_max_el("test_08", test_08, COUNT(test_08), 100);
test_max_el("test_09", test_09, COUNT(test_09), -1);
test_max_el("test_10", test_10, COUNT(test_10), -6);
fputc('\n', stdout);
return 0;
}
void test_is_sorted(const char *tag, const int *a, int n, int expected_rv)
{
printf("Testing is_sorted for case with tag \"%s\":", tag);
if (expected_rv == is_sorted(a, n))
printf(" Pass.\n");
else
printf(" FAIL!\n");
}
void test_max_el(const char *tag, const int *a, int n, int expected_rv)
{
printf("Testing max_el for case with tag \"%s\":", tag);
if (expected_rv == max_el(a, n))
printf(" Pass.\n");
else
printf(" FAIL!\n");
}
#endif // #ifdef UNIT_TESTS
but when I test it it doesnt work, what can I change.
when i use this test int test_04[] = { 10, 20, 30, 35, 40 };
it returns 0. what am i doing wrong?I have added my entire code but the function still shows some defect, idk why it is doing this any help would be appreciated.
For now, when you did that if (a[0] <= a[k+ 1]), you just check if all value in the array are greater or equal than the first element of your array. You must check if an element is greater or equal than the previous element and if it's lesser or equal than the next element.
int is_sorted(const int *a, int n)
{
assert (n >= 1);
int k;
for (k = 1 ; k < n ; k++) {
if (a[k-1] > a[k])
return 0;
}
return 1;
}
Instead of use a variable result, you can directly return 0 when you know that the array isn't sorted.
Without added local variables
int is_sorted(const int *a, int n) {
assert (n >= 1);
while (--n)
if (a[n] < a[n-1])
return 0;
return 1;
}
Try this one
int is_sorted(const int *a, int n)
{
assert (n >= 1);
if (n == 1)
return 1;
int k, result=1;
for (k = 0; k < n - 1; k++) {
if (a[k] > a[k+ 1])
{
result = 0;
break;
}
}
return result;
}