Проблема с указателем при использовании файла заголовка со структурой / массивом, приводящая к ошибке множественных определений (C)

#arrays #c #pointers #struct #typedef

#массивы #c #указатели #структура #typedef

Вопрос:

У меня есть программа (рюкзак, оптимизированная для возврата решения с наибольшим значением и наименьшим весом), для которой я хочу использовать внешние файлы для данных typedef и struct.

Но я не могу заставить его работать, где-то я путаюсь с указателями. Я получаю ошибку «множественное определение» или когда я ее меняю, я получаю ошибку «xxx не объявлено»…

/tmp/ccMy5Yw0.o:(.data 0x0): множественное определение `item1′

Любая помощь в указании на мою ошибку мышления очень ценится. (Я скомпилировал онлайн @ https://www.onlinegdb.com /)

Это сработало, когда у меня было все в одном файле, но после разделения его на разные файлы я не могу заставить его работать…

 main.c

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

#include "defs.h"
#include "data.c"

item_t *items[ITEMS_SIZE] = { amp;item1, amp;item2, amp;item3, amp;item4, amp;item5, amp;item6, amp;item7, amp;item8,   amp;item9, amp;item10 };

int *knapsack (item_t * items, int n, int w)
{
  int h, h_i, h_j, i, j, a, b, *mm, **m, *s;
  mm = calloc ((n   1) * (w   1), sizeof (int));
  m = malloc ((n   1) * sizeof (int *));
  m[0] = mm;
  h = m[0][0];
  h_i = 0;
  h_j = 0;
  for (i = 1; i <= n; i  )
    {
      m[i] = amp;mm[i * (w   1)];
      for (j = 0; j <= w; j  )
    {
      if (items[i - 1].weight > j)
        {
          m[i][j] = m[i - 1][j];
        }
      else
        {
          a = m[i - 1][j];
          b = m[i - 1][j - items[i - 1].weight]   items[i - 1].value;
          m[i][j] = a > b ? a : b;
          if (m[i][j] > h)
        {
          h = m[i][j];
          h_i = i;
          h_j = j;
        }
        }
      printf ("%dt%dt%dn", h, h_i, h_j);
    }
    }
  s = calloc (n, sizeof (int));
  for (i = h_i, j = h_j; i > 0; i--)
    {
      if (m[i][j] > m[i - 1][j])
    {
      s[i - 1] = 1;
      j -= items[i - 1].weight;
    }
    }
  free (mm);
  free (m);
  return s;
}

int main ()
{
  int i, n, tw = 0, tv = 0, *s;
  for (i = 0; i < 10; i  )
    {
      if (items[i]->SwitchOn)
    {
      items[i]->value = items[i]->value;
    }
      else
    {
      items[i]->value = 0;
    }
    }
  n = sizeof (items) / sizeof (item_t);
  s = knapsack (items, n, 690);
  for (i = 0; i < n; i  )
    {
      if (s[i])
    {
      printf ("%-22s ] ]n", items[i]->name, items[i]->weight,
          items[i]->value);
      tw  = items[i]->weight;
      tv  = items[i]->value;
    }
    }
  printf ("%-22s ] ]n", "totals:", tw, tv);
  return 0;
}
 

defs.h

     #ifndef SYSTEMDEFS_H_INCLUDED
    #define SYSTEMDEFS_H_INCLUDED
    
    #define ITEMS_SIZE 10
    
    typedef struct Item
    {
      char name[40];
      int weight;
      int value;
      bool SwitchOn;
    } item_t;
    
    extern item_t item1;
    extern item_t item2;
    extern item_t item3;
    extern item_t item4;
    extern item_t item5;
    extern item_t item6;
    extern item_t item7;
    extern item_t item8;
    extern item_t item9;
    extern item_t item10;
    
    #endif
 

data.c

 #include <stdbool.h>
#include "defs.h"

item_t item1 =
{
    .name = "part1",
    .weight = 25,
    .value = 8,
    .SwitchOn = false,
};

item_t item2 =
{
    .name = "part2",
    .weight = 40,
    .value = 2,
    .SwitchOn = true,
};

item_t item3 =
{
    .name = "part3",
    .weight = 60,
    .value = 7,
    .SwitchOn = false,
};

item_t item4 =
{
    .name = "part4",
    .weight = 100,
    .value = 6,
    .SwitchOn = false,
};

item_t item5 =
{
    .name = "part5",
    .weight = 150,
    .value = 2,
    .SwitchOn = true,
};

item_t item6 =
{
    .name = "part6",
    .weight = 380,
    .value = 10,
    .SwitchOn = true,
};

item_t item7 =
{
    .name = "part7",
    .weight = 850,
    .value = 2,
    .SwitchOn = false,
};

item_t item8 =
{
    .name = "part8",
    .weight = 75,
    .value = 15,
    .SwitchOn = true,
};

item_t item9 =
{
    .name = "part9",
    .weight = 800,
    .value = 1,
    .SwitchOn = false,
};

item_t item10 =
{
    .name = "part10",
    .weight = 75,
    .value = 8,
    .SwitchOn = true,
};
 

Комментарии:

1. Удалить #включить «data.c» из main.c.

Ответ №1:

Поскольку вы включили data.c в main.c

 #include "defs.h"
#include "data.c"
 

тогда теперь код в data.c дублируется в двух единицах перевода: один с main.c , а другой с data.c .

Удалите эту строку

 #include "data.c"
 

От main.c .

Также обратите внимание на то, что если вы объявили массив типа item_t *[ITEM_SIZE]

 item_t *items[ITEMS_SIZE] = { /*...*/ };
 

Поэтому, если вы передадите его в качестве аргумента функции, оно неявно преобразуется в указатель на его первый элемент типа item_t ** . Но вы передаете массив функции knapsack

 s = knapsack (items, n, 690);
 

первый параметр которого имеет тип item_t * .

 int *knapsack (item_t * items, int n, int w)
 

Поэтому компилятор должен выдать сообщение о том, что типы указателей не совместимы. То есть, объявлена ли функция и определена неправильно или вы вызываете ее, предоставляя неправильные аргументы.

Комментарии:

1. Дорогой Влад, теперь эта часть работает нормально, но функция knapsack не считывает значения из элементов массива… Все, что я получаю, — это 0…