generated from freudenreichan/info2Praktikum-DobleSpiel
Implement createNumbers alternative + tests
This commit is contained in:
parent
a1debfe55a
commit
83b96c9442
103
numbers.c
103
numbers.c
@ -11,16 +11,105 @@
|
|||||||
* Duplizieren eines zufälligen Eintrags im Array.
|
* Duplizieren eines zufälligen Eintrags im Array.
|
||||||
* in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */
|
* in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */
|
||||||
|
|
||||||
// Returns len random numbers between 1 and 2x len in random order which are all different, except for two entries.
|
|
||||||
// Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while
|
|
||||||
// creating random numbers.
|
|
||||||
unsigned int *createNumbers(unsigned int len)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// Vergleichsfunktion für qsort (Aufsteigend sortieren)
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
static int compareUnsignedInt(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const unsigned int *ia = a;
|
||||||
|
const unsigned int *ib = b;
|
||||||
|
|
||||||
|
if (*ia < *ib) return -1;
|
||||||
|
if (*ia > *ib) return 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns only the only number in numbers which is present twice. Returns zero on errors.
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// createNumbers
|
||||||
|
// Erzeugt ein Array aus len Zufallszahlen (1..2*len), alle verschieden.
|
||||||
|
// Danach wird genau EIN zufälliger Eintrag dupliziert.
|
||||||
|
// Parameter: len = Anzahl der gewünschten Zufallszahlen
|
||||||
|
// Rückgabe: Pointer auf das erzeugte Array (muss mit free() freigegeben werden)
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
unsigned int *createNumbers(unsigned int len)
|
||||||
|
{
|
||||||
|
if (len < 2)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
|
unsigned int *numbers = malloc(len * sizeof(unsigned int));
|
||||||
|
if (!numbers)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
unsigned int count = 0;
|
||||||
|
|
||||||
|
// alle Werte verschieden erzeugen
|
||||||
|
while (count < len)
|
||||||
|
{
|
||||||
|
unsigned int value = (rand() % (2 * len)) + 1;
|
||||||
|
|
||||||
|
// Duplikatsprüfung (linear)
|
||||||
|
int exists = 0;
|
||||||
|
for (unsigned int i = 0; i < count; i++) {
|
||||||
|
if (numbers[i] == value) {
|
||||||
|
exists = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exists)
|
||||||
|
numbers[count++] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EIN Duplikat erzeugen
|
||||||
|
unsigned int i1 = rand() % len;
|
||||||
|
unsigned int i2 = rand() % len;
|
||||||
|
while (i2 == i1)
|
||||||
|
i2 = rand() % len;
|
||||||
|
|
||||||
|
numbers[i2] = numbers[i1];
|
||||||
|
|
||||||
|
return numbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// getDuplicate
|
||||||
|
// Findet die einzige Zahl, die im Array zweimal vorkommt.
|
||||||
|
// Sortiert dazu eine Kopie des Arrays und vergleicht benachbarte Werte.
|
||||||
|
// Parameter: numbers = Array von Zufallszahlen
|
||||||
|
// len = Anzahl der Elemente
|
||||||
|
// Rückgabe: die doppelte Zahl oder 0 bei Fehler
|
||||||
|
// -------------------------------------------------------------
|
||||||
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
|
unsigned int getDuplicate(const unsigned int numbers[], unsigned int len)
|
||||||
{
|
{
|
||||||
|
if (!numbers || len < 2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
}
|
// Kopie erzeugen, damit das Original unverändert bleibt
|
||||||
|
unsigned int *copy = malloc(len * sizeof(unsigned int));
|
||||||
|
if (!copy)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memcpy(copy, numbers, len * sizeof(unsigned int));
|
||||||
|
|
||||||
|
// Sortieren
|
||||||
|
qsort(copy, len, sizeof(unsigned int), compareUnsignedInt);
|
||||||
|
|
||||||
|
// benachbarte Elemente vergleichen
|
||||||
|
unsigned int duplicate = 0;
|
||||||
|
for (unsigned int i = 1; i < len; i++) {
|
||||||
|
if (copy[i] == copy[i - 1]) {
|
||||||
|
duplicate = copy[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(copy);
|
||||||
|
return duplicate;
|
||||||
|
}
|
||||||
|
|||||||
BIN
test_numbers
Executable file
BIN
test_numbers
Executable file
Binary file not shown.
152
test_numbers.c
Normal file
152
test_numbers.c
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "unity.h"
|
||||||
|
#include "numbers.h"
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// Hilfsfunktion: zählt, wie oft ein Wert im Array vorkommt
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
static unsigned int countOccurrences(const unsigned int *arr, unsigned int len, unsigned int value)
|
||||||
|
{
|
||||||
|
unsigned int count = 0;
|
||||||
|
for (unsigned int i = 0; i < len; i++)
|
||||||
|
if (arr[i] == value)
|
||||||
|
count++;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// Test 1: Array wird korrekt erzeugt (nicht NULL)
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
void test_createNumbersReturnsNotNull(void)
|
||||||
|
{
|
||||||
|
unsigned int len = 20;
|
||||||
|
unsigned int *numbers = createNumbers(len);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(numbers);
|
||||||
|
|
||||||
|
free(numbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// Test 2: Alle Zahlen liegen im erlaubten Bereich (1..2*len)
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
void test_numbersAreInCorrectRange(void)
|
||||||
|
{
|
||||||
|
unsigned int len = 50;
|
||||||
|
unsigned int *numbers = createNumbers(len);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(numbers);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_TRUE(numbers[i] >= 1);
|
||||||
|
TEST_ASSERT_TRUE(numbers[i] <= 2 * len);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(numbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// Test 3: Es gibt GENAU EIN Duplikat
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
void test_exactlyOneDuplicateExists(void)
|
||||||
|
{
|
||||||
|
unsigned int len = 80;
|
||||||
|
unsigned int *numbers = createNumbers(len);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(numbers);
|
||||||
|
|
||||||
|
unsigned int duplicatesFound = 0;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
unsigned int occurrences = countOccurrences(numbers, len, numbers[i]);
|
||||||
|
if (occurrences == 2)
|
||||||
|
duplicatesFound++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Da das Duplikat an zwei Positionen vorkommt,
|
||||||
|
// erwarten wir duplicatesFound == 2
|
||||||
|
TEST_ASSERT_EQUAL_UINT(2, duplicatesFound);
|
||||||
|
|
||||||
|
free(numbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// Test 4: getDuplicate() findet die richtige doppelte Zahl
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
void test_getDuplicateFindsCorrectValue(void)
|
||||||
|
{
|
||||||
|
unsigned int len = 100;
|
||||||
|
unsigned int *numbers = createNumbers(len);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(numbers);
|
||||||
|
|
||||||
|
unsigned int duplicate = getDuplicate(numbers, len);
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(duplicate >= 1);
|
||||||
|
TEST_ASSERT_TRUE(duplicate <= 2 * len);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_UINT(2, countOccurrences(numbers, len, duplicate));
|
||||||
|
|
||||||
|
free(numbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// Test 5: createNumbers() erzeugt len Elemente
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
void test_arrayLengthIsCorrect(void)
|
||||||
|
{
|
||||||
|
unsigned int len = 30;
|
||||||
|
unsigned int *numbers = createNumbers(len);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(numbers);
|
||||||
|
|
||||||
|
// Unity-Funktion prüft nicht direkt Länge, aber wir können checken,
|
||||||
|
// ob Zugriff auf alle Elemente möglich ist (Segfault würde Test crashen).
|
||||||
|
for (unsigned int i = 0; i < len; i++)
|
||||||
|
TEST_ASSERT_TRUE(numbers[i] >= 1);
|
||||||
|
|
||||||
|
free(numbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// Leere setUp/tearDown
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
void setUp(void) {}
|
||||||
|
void tearDown(void) {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// Hauptprogramm für Unity-Tests
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
printf("\n============================\nNumbers tests\n============================\n");
|
||||||
|
|
||||||
|
RUN_TEST(test_createNumbersReturnsNotNull);
|
||||||
|
RUN_TEST(test_numbersAreInCorrectRange);
|
||||||
|
RUN_TEST(test_exactlyOneDuplicateExists);
|
||||||
|
RUN_TEST(test_getDuplicateFindsCorrectValue);
|
||||||
|
RUN_TEST(test_arrayLengthIsCorrect);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
BIN
test_numbers.o
Normal file
BIN
test_numbers.o
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user