Основная проблема заключается в индексации присваивания во втором цикле функции Join()
:
int Join(set arr1[], int arr1_size, set arr2[], int arr2_size, set arr3[], int arr3_size)
{
int i;
for (i = 0; i < arr1_size; i++)
arr3[i] = arr1[i];
for (i = 0; i < arr2_size; i++)
{
if (!in_arr(arr2[i], arr3, arr3_size))
arr3[i+arr1_size] = arr2[i];
}
}
Вам необходимо сохранить счетчик, который правильно проходит через массив arr3
, даже когда i
сбрасывается на ноль (и некоторые значения i
не добавляются).Функция объявлена для возврата значения, но не делает этого - еще одна ошибка.Либо верните фактический размер массива результатов (показанный ниже), либо объявите функцию, возвращающую void
.Так как возвращаемое значение не используется, второй вариант может быть лучше.Это может помочь:
int Join(set arr1[], int arr1_size, set arr2[], int arr2_size, set arr3[], int arr3_size)
{
int i;
int k = 0;
for (i = 0; i < arr1_size; i++)
arr3[k++] = arr1[i];
for (i = 0; i < arr2_size; i++)
{
if (!in_arr(arr2[i], arr3, arr3_size))
arr3[k++] = arr2[i];
}
assert(k <= arr3_size);
return k;
}
Одна незначительная проблема (производительность, а не корректность):
int newsize = 0;
for (i = 0; i < arr1_size; i++)
{
if (!in_arr(arr1[i], arr2, arr2_size))
newsize++;
}
for (i = 0; i < arr2_size; i++)
newsize++;
Второй цикл можно записать более кратко, как:
newsize += arr2_size;
Или, действительно, вы можете инициализировать newsize = arr2_size;
, а затем подсчитать дополнительные.
int newsize = arr2_size;
for (i = 0; i < arr1_size; i++)
{
if (!in_arr(arr1[i], arr2, arr2_size))
newsize++;
}
В arr_in_arr()
есть сомнительный оператор printf()
:
int arr_in_arr(set smaller[], int smaller_size, set bigger[], int bigger_size)
{
int res = 1;
int counter;
for (counter = 0; counter < smaller_size; counter++)
{
if (in_arr(smaller[counter], bigger, bigger_size))
printf("%d ", smaller[counter]);
else
{
res = 0;
break;
}
}
return res;
}
Либо, он должен иметь '%d
' в строке формата или условное выражение должно быть инвертировано, а вся функция упрощена:
int arr_in_arr(set smaller[], int smaller_size, set bigger[], int bigger_size)
{
int counter;
for (counter = 0; counter < smaller_size; counter++)
{
if (!in_arr(smaller[counter], bigger, bigger_size))
return 0;
}
return 1;
}
Переменная counter
в main()
не используется.
Если смотреть структурно, ваша абстракция 'set' невелика;Вы должны передавать массив и размер каждый раз, когда вызываете функцию.Также у вас может быть переменная set x;
, которая содержит один элемент (а не набор).Вы можете улучшить это с помощью структуры, но это может привести к слишком большому выделению памяти на данный момент.
Нет также кода, который бы гарантировал, что наборы не содержат дубликатов.То есть, если вы определили набор:
set D[] = { a, c, a, d };
Результирующий набор операции Join()
, где это был левый (первый) операнд, будет содержать два элемента a
в выводе.Кстати, операцию Join()
можно также рассматривать как объединение множеств, a ∪ b
.
Я получил следующий код:
#include <stdio.h>
#include <assert.h>
#define SIZEOF_A 6
#define SIZEOF_B 6
typedef enum
{
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
} set;
static void dispSet(set numbers[], int size_numbers)
{
int i;
printf("[ ");
for (i = 0; i < size_numbers-1; i++)
printf("%d, ", numbers[i]);
printf("%d ]", numbers[size_numbers-1]);
printf("\n");
}
static int in_arr(set A, set B[], int B_size)
{
int res = 0; // XXX: uninitialized
int counter;
for (counter = 0; counter < B_size; counter++)
{
if (A == B[counter])
{
res = 1;
break;
}
}
return res;
}
static int arr_in_arr(set smaller[], int smaller_size, set bigger[], int bigger_size)
{
int counter; // XXX: simplified
for (counter = 0; counter < smaller_size; counter++)
{
if (!in_arr(smaller[counter], bigger, bigger_size))
return 0;
}
return 1;
}
static int size_c(set arr1[], int arr1_size, set arr2[], int arr2_size)
{
int i;
int newsize = arr2_size; // XXX: compacted
for (i = 0; i < arr1_size; i++)
{
if (!in_arr(arr1[i], arr2, arr2_size))
newsize++;
}
printf("\nSIZE OF C: %d\n", newsize);
return newsize;
}
static int Join(set arr1[], int arr1_size, set arr2[], int arr2_size, set arr3[], int arr3_size)
{
int i;
int k; // XXX: fixed
for (i = 0; i < arr1_size; i++)
arr3[k++] = arr1[i];
for (i = 0; i < arr2_size; i++)
{
if (!in_arr(arr2[i], arr3, arr3_size))
arr3[k++] = arr2[i];
}
assert(k <= arr3_size);
return k;
}
int main(void)
{
set A[SIZEOF_A] = {c, d, f, a, b, j};
set B[SIZEOF_B] = {a, b, c, d, e, f};
int SIZEOF_C = size_c(A, SIZEOF_A, B, SIZEOF_B);
printf("For the sets,\n");
printf("A: ");
dispSet(A, SIZEOF_A);
printf("B: ");
dispSet(B, SIZEOF_B);
printf("C: ");
set C[SIZEOF_C];
Join(A, SIZEOF_A, B, SIZEOF_B, C, SIZEOF_C);
dispSet(C, SIZEOF_C);
printf("%s\n", (arr_in_arr(A, SIZEOF_A, B, SIZEOF_B) == 1)?"B contains A":"B does not contain A");
}
Функции сделаны статическимипотому что нет никакого другого файла, использующего их, ни какого-либо заголовка, объявляющего их (и это отключает предупреждения компилятора от -Wmissing-prototypes
).Я скомпилировал его (на MacOS X 10.6.7 с использованием Apple GCC 4.2.1), используя:
gcc -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes join.c -o join
Выход:
SIZE OF C: 7
For the sets,
A: [ 2, 3, 5, 0, 1, 9 ]
B: [ 0, 1, 2, 3, 4, 5 ]
C: [ 2, 3, 5, 0, 1, 9, 4 ]
B does not contain A