#define _POSIX_C_SOURCE 200809L #include /* close, write, pipe */ #include /* errorno */ #include /* assert */ #include /* err, warn */ #include /* free */ #include /* strlen, memcmp */ /* Napište podprogram ‹longest_rec›, který přečte veškerá data ze * zadaného popisovače, a nalezne v nich nejdelší záznam. Záznamy * jsou ukončeny zadaným řetězcem (který zejména může mít víc než * jeden bajt). * * Výsledkem bude počet bajtů, které tomuto záznamu v souboru * předchází (tzn. adresa záznamu v souboru) a jeho délka (včetně * oddělovače). Tyto hodnoty předá volajícímu ve výstupních * parametrech. Je-li nejdelších záznamů víc, použije se první * z nich. Případný neukončený záznam na konci souboru ignorujte. * * Návratová hodnota bude 0 v případě úspěchu a -1 jinak. */ int longest_rec( int fd, const char *delim, int *offset, int *length ); /* ┄┄┄┄┄┄┄ %< ┄┄┄┄┄┄┄┄┄┄ následují testy ┄┄┄┄┄┄┄┄┄┄ %< ┄┄┄┄┄┄┄ */ #include /* openat */ static void close_or_warn( int fd, const char *name ) { if ( close( fd ) == -1 ) warn( "closing %s", name ); } static void unlink_if_exists( const char *file ) { if ( unlink( file ) == -1 && errno != ENOENT ) err( 2, "unlink" ); } static int check( const char *input, const char *delim, int expect_off, int expect_len ) { const char *name = "zt.r3_split.txt"; unlink_if_exists( name ); int fd = openat( AT_FDCWD, name, O_CREAT | O_WRONLY, 0755 ); if ( fd == -1 ) err( 2, "creating %s", name ); if ( write( fd, input, strlen( input ) ) == -1 ) err( 2, "writing into %s", name ); close_or_warn( fd, name ); fd = open( name, O_RDONLY ); if ( fd == -1 ) err( 2, "opening %s for reading", name ); int actual_off, actual_len; int result = longest_rec( fd, delim, &actual_off, &actual_len ); close_or_warn( fd, name ); int rv; dprintf( 2, "result: %d, %d\n", actual_off, actual_len ); if ( expect_off >= 0 ) rv = actual_off == expect_off && actual_len == expect_len; else rv = result == -1; unlink_if_exists( name ); return rv; } int main() { assert( check( "foobaroo", "oo", 3, 5 ) ); assert( check( "foobarooo", "oo", 3, 5 ) ); assert( check( "fooobarooo", "oo", 3, 6 ) ); assert( check( "fooobarooo", "ooo", 4, 6 ) ); assert( check( "fooobarooo", "o", 4, 4 ) ); assert( check( "xyxxyxxxyx", "xyx", 6, 4 ) ); assert( check( "xyzxyxxxyz", "xyz", 3, 7 ) ); assert( check( "xxxxyxxx", "xxx", 3, 5 ) ); assert( check( "xyzzxyzzy", "xyzzy", 0, 9 ) ); assert( check( "xyzzxyzxyzzy", "xyzzy", 0, 12 ) ); assert( check( "xyzzyxyzzxyzxyzzy", "xyzzy", 5, 12 ) ); assert( check( "aaaaabaaaaaab", "aaab", 6, 7 ) ); assert( check( "abababac", "abac", 0, 8 ) ); assert( check( "abacababac", "abac", 4, 6 ) ); assert( check( "aaaaaaaab", "b", 0, 9 ) ); assert( check( "aaaaaaaab", "ab", 0, 9 ) ); assert( check( "aaaaaaaab", "aab", 0, 9 ) ); assert( check( "aaaaaaaab", "aaab", 0, 9 ) ); assert( check( "aaaaaaaab", "aaaab", 0, 9 ) ); assert( check( "aaaaaaaab", "aaaaab", 0, 9 ) ); assert( check( "aaaaaaaab", "aaaaaab", 0, 9 ) ); assert( check( "aaaaaaaabaaaaaaaaab", "b", 9, 10 ) ); assert( check( "aaaaaaaabaaaaaaaaab", "ab", 9, 10 ) ); assert( check( "aaaaaaaabaaaaaaaaab", "aab", 9, 10 ) ); assert( check( "aaaaaaaabaaaaaaaaab", "aaab", 9, 10 ) ); assert( check( "aaaaaaaabaaaaaaaaab", "aaaab", 9, 10 ) ); assert( check( "aaaaaaaabaaaaaaaaab", "aaaaab", 9, 10 ) ); assert( check( "aaaaaaaabaaaaaaaaab", "aaaaaab", 9, 10 ) ); return 0; }