Hej :)
Muszę do pewnego zadania rozpisać funkcję łączącą poszczególne tablice w jedną. Tutaj podaję fragment treści zadania związanej z tą funkcją:
Napisz i przetestuj funkcję łączącą N tablic w jedną o następującym wywołaniu:
int* result = connect(data_type_int, 2, (int []){18, -13, -10, -1}, (int []){-7, 1, 20, -2, -1});
Funkcja ma przyjmować w parametrze:
typ danych,
liczbę tablic oraz kolejne tablice; koniec danych w tablicy będzie oznaczony wartością -1.
Wartość zwracana:
W przypadku sukcesu funkcja powinna zwrócić adres zaalokowanej pamięci na tablicę wynikową,
NULL w przypadku błędnych danych wejściowych lub w przypadku niepowodzenia alokacji pamięci.
Funkcja powinna obsługiwać następujące typy danych: short, int, float, double i long. Typ danych ma być przekazany do funkcji za pomocą typu wyliczeniowego o nazwie data_type_t (umieść go w pliku nagłówkowym data_type.h.), a pola powinny mieć nazwy zgodne ze wzorcem: data_type_NAZWATYPU (np. data_typ_short).
Przyjmij następującą zależność nazwa typu data_type_t i jej wartości:
0 - short
1 - int
2 - float
3 - double
4 - long
Oto moja funckcja:
void * connect(enum data_type_t dir,int how_many, ... )
{
if( dir < 0 || dir > 4 || how_many <= 0)
{
return NULL;
}
va_list lista;
va_start ( lista, how_many );
if( dir == 0 )
{
short * pointer;
int i;
int sum_of_all_elements = 0;
for(i = 0; i < how_many;i++)
{
pointer = va_arg(lista,short *);
int j = 0;
while( *(pointer + j) != -1 )
{
j++;
}
j--;
sum_of_all_elements = j;
}
va_end(lista);
short * wynikowa = (short * ) malloc(sizeof(short) * (sum_of_all_elements + 1) );
if( wynikowa == NULL )
{
return NULL;
}
va_list lista2;
va_start(lista2,how_many);
int itr = 0;
for(i = 0; i < how_many;i++)
{
pointer = va_arg(lista2,short *);
int j = 0;
while( *(pointer + j) != -1 )
{
*(wynikowa + itr) = *(pointer + j);
itr++;
j++;
}
}
*(wynikowa + sum_of_all_elements) = -1;
va_end(lista2);
return wynikowa;
}
else if( dir == 1 )
{
int * pointer;
int i;
int sum_of_all_elements = 0;
for(i = 0; i < how_many;i++)
{
pointer = va_arg(lista,int *);
int j = 0;
while( *(pointer + j) != -1 )
{
j++;
}
j--;
sum_of_all_elements = j;
}
va_end(lista);
int * wynikowa = (int * ) malloc(sizeof(int) * (sum_of_all_elements + 1) );
if( wynikowa == NULL )
{
return NULL;
}
va_list lista2;
va_start(lista2,how_many);
int itr = 0;
for(i = 0; i < how_many;i++)
{
pointer = va_arg(lista2,int *);
int j = 0;
while( *(pointer + j) != -1 )
{
*(wynikowa + itr) = *(pointer + j);
itr++;
j++;
}
}
*(wynikowa + sum_of_all_elements) = -1;
va_end(lista2);
return wynikowa;
}
else if( dir == 2 )
{
float * pointer;
int i;
int sum_of_all_elements = 0;
for(i = 0; i < how_many;i++)
{
pointer = va_arg(lista,float *);
int j = 0;
while( *(pointer + j) != -1 )
{
j++;
}
j--;
sum_of_all_elements = j;
}
va_end(lista);
float * wynikowa = (float * ) malloc(sizeof(float) * (sum_of_all_elements + 1) );
if( wynikowa == NULL )
{
return NULL;
}
va_list lista2;
va_start(lista2,how_many);
int itr = 0;
for(i = 0; i < how_many;i++)
{
pointer = va_arg(lista2,float *);
int j = 0;
while( *(pointer + j) != -1 )
{
*(wynikowa + itr) = *(pointer + j);
itr++;
j++;
}
}
*(wynikowa + sum_of_all_elements) = -1;
va_end(lista2);
return wynikowa;
}
else if( dir == 3 )
{
double * pointer;
int i;
int sum_of_all_elements = 0;
for(i = 0; i < how_many;i++)
{
pointer = va_arg(lista,double *);
int j = 0;
while( *(pointer + j) != -1 )
{
j++;
}
j--;
sum_of_all_elements = j;
}
va_end(lista);
double * wynikowa = (double * ) malloc(sizeof(double) * (sum_of_all_elements + 1) );
if( wynikowa == NULL )
{
return NULL;
}
va_list lista2;
va_start(lista2,how_many);
int itr = 0;
for(i = 0; i < how_many;i++)
{
pointer = va_arg(lista2,double *);
int j = 0;
while( *(pointer + j) != -1 )
{
*(wynikowa + itr) = *(pointer + j);
itr++;
j++;
}
}
*(wynikowa + sum_of_all_elements) = -1;
va_end(lista2);
return wynikowa;
}
else
{
long * pointer;
int i;
int sum_of_all_elements = 0;
for(i = 0; i < how_many;i++)
{
pointer = va_arg(lista,long *);
int j = 0;
while( *(pointer + j) != -1 )
{
j++;
}
j--;
sum_of_all_elements = j;
}
va_end(lista);
long * wynikowa = (long * ) malloc(sizeof(long) * (sum_of_all_elements + 1) );
if( wynikowa == NULL )
{
return NULL;
}
va_list lista2;
va_start(lista2,how_many);
int itr = 0;
for(i = 0; i < how_many;i++)
{
pointer = va_arg(lista2,long *);
int j = 0;
while( *(pointer + j) != -1 )
{
*(wynikowa + itr) = *(pointer + j);
itr++;
j++;
}
}
*(wynikowa + sum_of_all_elements) = -1;
va_end(lista2);
return wynikowa;
}
return NULL;
}
I jeszcze rozpisany w dołączonym do programu pliku nagłówkowym typ wyliczeniowy (enum):
#ifndef DATA_TYPE_H_INCLUDED
#define DATA_TYPE_H_INCLUDED
enum data_type_t {data_type_short = 0, data_type_int = 1,data_type_float = 2, data_type_double = 3, data_type_long = 4};
#endif // DATA_TYPE_H_INCLUDED
Na chwilę obecną wyrzuca mi już całe zadanie na pierwszym teście:
### Testy jednostkowe ###
TEST 1: Sprawdzanie poprawności działania funkcji connect dla tablic typu float (limit sterty ustawiono na 105 bajtów)⏎
Wynik: PORAŻKA: Funkcja connect() powinna zwrócić NULL⏎
Sprawdź funkcję testującą TEST1(void) z pliku unit_test_v2.c, w linii 57⏎
*** Test przerwany ***⏎
### RLDebug :: Analiza wycieku zasobów ###
Wszystkie bloki pamięci zostały pomyślnie zwolnione - brak wycieków.⏎
Wszystkie pliki zostały zamknięte.⏎
main: rdebug.c:1177: rldebug_show_leaked_resources: Assertion `memory_leaked == rbase.current_heap_size' failed.⏎
Program przerwany; kod błędu=134 (Sygnał SIGABRT)
Test został przerwany; Program PRZERWANY; miał zwrócić wartość 0 a zakończył się sygnałem SIGABRT
A tutaj jeszcze przedstawiam dokładnie rozpisany test:
float expected_result[] = {9.385853, -7.621314, 5.236408, 7.880167, -2.575675, 18.044909, -0.544349, -3.259939, -16.541740, -13.286819, -19.258662, 7.845092, 0.622868, -6.778655, -3.590870, 4.721692, -1.250231, 4.138973, 10.415007, -11.544492, -9.097682, 19.849394, 9.224041, 11.988193, 15.535914, 16.962027, 17.363107, 11.490503, -15.415687, -10.801188, -1.919569, -15.331628, -3.184014, 10.258204, 19.857382, -8.252181, 1.993204, -13.460391, -1.000000};
float* result = connect(data_type_float, 9, (float []){9.385853, -7.621314, 5.236408, 7.880167, -1.000000}, (float []){-2.575675, 18.044909, -0.544349, -3.259939, -1.000000}, (float []){-16.541740, -13.286819, -19.258662, 7.845092, 0.622868, -1.000000}, (float []){-6.778655, -3.590870, 4.721692, -1.250231, 4.138973, -1.000000}, (float []){10.415007, -11.544492, -9.097682, 19.849394, 9.224041, -1.000000}, (float []){11.988193, 15.535914, 16.962027, -1.000000}, (float []){17.363107, 11.490503, -15.415687, -10.801188, -1.919569, -1.000000}, (float []){-15.331628, -3.184014, 10.258204, 19.857382, -1.000000}, (float []){-8.252181, 1.993204, -13.460391, -1.000000});
test_error(result == NULL, "Funkcja connect() powinna zwrócić NULL");
onerror_terminate(); // przerwnie wszystkich testów jednostkowych (np. coś jest mocno nie tak z kodem)
if (result != NULL)
{
int ok = 1;
for (int i = 0; i < 39; ++i)
if (*(result + i) != *(expected_result + i))
ok = 0;
if (!ok)
{
printf("Oczekiwany wynik:\n");
for (int i = 0; i < 39; ++i)
printf("%f", *(expected_result + i));
printf("Otrzymany wynik:\n");
for (int i = 0; i < 39; ++i)
printf("%f", *(result + i));
}
test_error(ok == 1, "Wartość zwrócona przez funkcję connect() jest nieprawidłowa");
free(result);
}
test_no_heap_leakage();
onerror_terminate(); // przerwnie wszystkich testów jednostkowych (np. coś jest mocno nie tak z kodem)
Tak więc coś ostro poknociłem chyba w kodzie. Czy mój sposób rozumowania wyżej tej funkcji tak jak to napisałem jest poprawny? Ponadto czy brakuje jakiś zabezpieczeń? No i dlaczego program przerywa działanie dla tego testu? Z góry dziękuję za odpowiedzi. :)