#define _POSIX_C_SOURCE 200809L /* Naprogramujte proceduru ‹hostname_exists›, která dostane na * vstupu zřetězený seznam jmen, o kterých ověří, je-li možné je * přeložit na adresy (tzn. zda se jedná o existující hostitelská * jména). Konkrétní typ adresy přitom není podstatný. Procedura má * dva parametry, ‹to_check› a ‹failed›: * * • oba jsou vstupně-výstupní: * ◦ jména, která existují, ponechte v ‹to_check›, * ◦ jména, která nejde přeložit, přesuňte do seznamu ‹failed›, * • na pořadí prvků: * ◦ v seznamu ‹failed› nezáleží, * ◦ v seznamu ‹to_check› musí být zachováno, * • seznam ‹failed› nemusí být nutně na začátku prázdný. * * Návratová hodnota bude -1, nastane-li nějaká fatální chyba, a * nula jinak. Nastane-li chyba, musí platit, že ze seznamu * ‹to_check› byla odstraněna pouze jména, o kterých jistě víme, že * neexistují. Každé jméno musí být po skončení (bez ohledu na * výsledek) v právě jednom ze seznamů. */ struct name_list { const char *name; struct name_list *next; }; int hostname_exists( struct name_list **to_check, struct name_list **failed ); /* ┄┄┄┄┄┄┄ %< ┄┄┄┄┄┄┄┄┄┄ následují testy ┄┄┄┄┄┄┄┄┄┄ %< ┄┄┄┄┄┄┄ */ #include /* assert */ #include /* strcmp */ void prepare_ll( struct name_list *to_check, int from, int to, char **domains ) { for ( int i = from; i < to - 1; ++ i ) { to_check->name = domains[ i ]; to_check->next = &to_check[ i - from + 1 ]; to_check = to_check->next; } to_check->name = domains[ to - 1 ]; to_check->next = NULL; } int check_inordered_ll( struct name_list *to_check, char **domains, int n ) { int same = 0; for ( int i = 0; i < n; ++ i ) { for ( struct name_list *nl = to_check; nl; nl = nl->next ) { if ( strcmp( nl->name, domains[ i ] ) == 0 ) { domains[ i ] = NULL; same += 1; break; } } } return same != n; } int check_ll( struct name_list *to_check, char **domains, int n, int ordered ) { if( !ordered ) return check_inordered_ll( to_check, domains, n ); int i = 0; int same = 0; for ( struct name_list *nl = to_check; nl; nl = nl->next, ++ same ) if ( strcmp( nl->name, domains[ i ++ ] ) != 0 ) return 1; return same != n; } int main( void ) { struct name_list to_check[ 12 ] = { 0 }, failed[ 3 ] = { 0 }; struct name_list *to_check_head, *failed_head; char *domains[] = { "relay.ip4.fi.muni.cz", "aisa.ip4.fi.muni.cz", "aisa.ip6.fi.muni.cz", "linux.org", "aisa.fi.muni.cz", "com.whois-servers.net", "tum.de", "org.whois-servers.net" }; char *domains_failed_1[] = { domains[ 3 ] }; char *domains_ok_2[] = { domains[ 4 ], domains[ 5 ], domains[ 7 ] }; char *domains_failed_2[] = { domains[ 3 ], domains[ 3 ], domains[ 6 ] }; /* Test case 1. */ to_check_head = to_check; failed_head = failed; prepare_ll( to_check_head, 0, 3, domains ); assert( check_ll( to_check_head, domains, 3, 1 ) == 0 ); assert( hostname_exists( &to_check_head, &failed_head ) == 0 ); assert( check_ll( to_check_head, domains, 3, 1 ) == 0 ); assert( failed->name == NULL && failed->next == NULL ); /* Test case 2. */ to_check_head = to_check; prepare_ll( to_check_head, 0, 4, domains ); assert( check_ll( to_check_head, domains, 4, 1 ) == 0 ); assert( hostname_exists( &to_check_head, &failed_head ) == 0 ); assert( check_ll( to_check_head, domains, 3, 1 ) == 0 ); assert( check_ll( failed_head, domains_failed_1, 1, 0 ) == 0 ); /* Test case 3. */ to_check_head = to_check + 4; prepare_ll( to_check_head, 0, 5, domains + 3 ); assert( check_ll( to_check_head, domains + 3, 5, 1 ) == 0 ); assert( hostname_exists( &to_check_head, &failed_head ) == 0 ); assert( check_ll( to_check_head, domains_ok_2, 3, 1 ) == 0 ); assert( check_ll( failed_head, domains_failed_2, 3, 0 ) == 0 ); return 0; }