C - объединить массивы - PullRequest
1 голос
/ 01 мая 2011

почему я не могу использовать Join?у него нет 4 (е) из множества B ... почему?

#include <stdio.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;

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");
}

int in_arr(int A, set B[], int B_size) {
    int res = 0;
    int counter;
    for (counter = 0; counter < B_size; counter++) {
        if (A == B[counter]) {
            res = 1;
            break;
        }
    }
    return res;
}

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)) {
            continue;
        }
        else {
            res = 0;
            break;
        }
    }
    return res;
}

int size_c(set arr1[], int arr1_size, set arr2[], int arr2_size) {
    int i;
    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++;
    printf("\nSIZE OF C: %d\n", newsize);
    return newsize;
}

int Join(set arr1[], int arr1_size, set arr2[], int arr2_size, set arr3[], int arr3_size) {
    int i, j;
    for (i = 0; i < arr1_size; i++) {
        arr3[i] = arr1[i];
    }
    for (i = 0; i < arr2_size; i++) {
        j = i+arr2_size;
        if (!in_arr(arr2[i], arr3, arr3_size)) {
            arr3[j] = arr2[i];
        }
    }
}

int main () {
    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);
    int counter;
    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");
}

Ответы [ 3 ]

3 голосов
/ 01 мая 2011

Ваша проблема в том, что вы используете i для помещения нового элемента в массив 3 и доступа к элементам из массива 2. Создайте новую переменную, скажем, j, которая используется для доступа к элементам из массива 3.

Это сработало для меня.

int Join(set arr1[], int arr1_size, set arr2[], int arr2_size, set arr3[], int arr3_size) {
    int i;
    int j = 0; /*NEW VARIABLE*/
    for (i = 0; i &#60; arr1_size; i++) {
        arr3[i] = arr1[i];
    }

    for (i = 0; i &#60; arr2_size; i++) {
        if (!in_arr(arr2[i], arr3, arr3_size)) {
            arr3[j+arr1_size] = arr2[i]; /*USE j TO ADD ELEMENT TO arr3*/
        j++; /*INCREMENT EACH TIME THIS IS DONE*/
        }
    }
}
2 голосов
/ 01 мая 2011

Основная проблема заключается в индексации присваивания во втором цикле функции 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
0 голосов
/ 01 мая 2011

Давайте пробежимся по коду в той точке, где объединение пытается, но e в объединение:

for (i = 0; i < arr2_size; i++) {
    if (!in_arr(arr2[i], arr3, arr3_size)) {
        arr3[i+arr1_size] = arr2[i];
    }
}

В этом случае индекс e в arr2 равен 4. Его нет в arr3, поэтому мы пытаемся поместить его в arr3 в позиции i+arr1_size. Вот проблема - i+arr1_size равно 6 + 4 или 10. size_c выглядит правильно, поэтому arr3_size должно быть 7. (-> 7 меньше 10)

Таким образом, код означает , признавая, что e еще не находится в arr3, и он пытается вставить его в arr3, но в этом случае это не удается учитывая, что индекс , в который он пытается поместить e, находится за пределами массива .

Вы должны будете отслеживать количество элементов в arr3 отдельно.

[править] Ах, я думаю, это в значительной степени то, о чем говорил Йоэль, я не очень хорошо прочитал это в первый раз [/ edit]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...