识别哪个结构包含您正在处理的值的聪明方法是什么?

What is a smart way to recognize what struct contains the value you're working on?

编辑:完整代码现已发布,您可以编译。

所以我们是一些第一学期的软件专业学生,他们在某种程度上陷入了与 c 中的结构有关的问题。 Stack overflow 已经帮了我很多次了,所以我想这次我真的会试着问一下,因为我似乎找不到我要找的东西。

我们的逻辑(见下面的代码):

  1. 主要来电empty_trash
  2. empty_trash(在其参数中)调用 compare_trash
  3. 通过 4 个区域(结构)比较垃圾解析
  4. 比较垃圾检查我们的数据平均值是否超过一定范围,如果是的话 首先检查该平均值是否高于我们的空结构, 大概有 0 个平均值,然后如果发现更高 一。这给我们留下了最高的结构的索引 平均
  5. 比较垃圾return这个结构清空垃圾,和一个整数 指向 main 的索引指针。
  6. 然后清空垃圾遍历子区域并检查它们的平均数据并重置超过 margin2 的数据
  7. 我们return重置主区
  8. 在 main 中,我们有一个结构 1-4 的数组。我们将 returned 从空垃圾中分配给 arrayofstructs[index pointed back]

在我们看来,逻辑是有道理的,但它似乎不起作用,因为我们的程序在 main 的那一行崩溃了。我们认为这是因为我们没有在 main 中正确分配结构,但不是 100% 确定。

我们有点困惑,因为当我们单独测试这两个功能时,它们各自都能正常工作,但在一起时却不行。

如有任何帮助,我们将不胜感激<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;
}

我的原评论:

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

您的回复:

@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

我做得更好了(?)我已经对你的代码进行了初步的重构。相信这不仅对自己有帮助,对其他人也有帮助。

对不起,但是(我是带着好心说的),代码需要很多重构。纯粹的 [不必要的] 复杂性可能掩盖了许多错误。

注意事项:

  1. 通过 传递 struct 危险的 。它合法的,但它使代码变得复杂。通过指针传递是 99.44% 的时间更好。您可以“就地”修改给定的结构,而不必 return 它 [再次按值]。
  2. 了解如何使用指向“当前”元素的 指针 而不是 索引 来遍历数组。您将在下面的 FORALL 循环中看到它。
  3. 不要“复制”代码。注意使用数组时会发生什么。我们有一个
  4. 而不是(例如)四个代码副本
  5. 而不是 4 个区域(例如 area1area2area3area4),if 我们有 10,000领域。您是否会像在(例如)empty_trash?
  6. 中那样将代码复制 10,000 次?
  7. 我为你的两个 struct 添加了 typedef 以简化事情。
  8. 我添加了一些高级技术,例如使用 FORALL 宏来遍历数组。

我使用预处理器条件来表示旧代码与新代码:

#if 0
// old code
#else
// new code
#endif

我已经完成了 some/most 的编辑。我已经编译了。我本可以犯无数错误。但是,它应该给你这样的想法:

#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;
        }
    }
}