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.
|
||||
* 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)
|
||||
{
|
||||
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