#define _POSIX_C_SOURCE 200809L #include /* close, write, pipe */ #include /* errorno */ #include /* assert */ #include /* err, warn */ #include /* free */ #include /* strlen, memcmp */ /* Napište podprogram ‹read_trunc›, který přečte ze vstupu jeden * záznam (každý záznam je ukončen bajtem ‹delim›), až do maximální * délky ‹size›. Je-li záznam delší, je načteno jen jeho prvních * ‹size› bajtů a zbytek je přeskočen – další volání ‹read_trunc› * vrátí další záznam (případně podobně zkrácený), atd. až než * narazí na konec souboru. Načtená data uloží do předaného pole * ‹out› (které má prostor minimálně pro ‹size› bajtů). * * Abychom mohli data načítat efektivně, bude volající proceduře * ‹read_trunc› navíc předávat ukazatel na strukturu ‹trunc_buffer›, * ve které lze uchovat data, která již byla načtena, ale nejsou * součástí aktuálního záznamu. * * Návratovou hodnotou bude v případě úspěchu skutečný počet bajtů, * které byly v záznamu uloženy, nebo -1 nepodaří-li se záznam * načíst. */ /* Strukturu ‹trunc_buffer› si můžete navrhnout dle vlastního * uvážení. Nesmí ale překročit velikost 512 bajtů. */ struct trunc_buffer { // … }; int read_trunc( int fd, char delim, int size, char *out, struct trunc_buffer *buffer ); /* ┄┄┄┄┄┄┄ %< ┄┄┄┄┄┄┄┄┄┄ 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 create_file( const char *data ) { 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, data, strlen( data ) ) == -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 ); return fd; } int main() { int fd; char rbuf[ 64 ]; struct trunc_buffer *tbuf = calloc( 1, 512 ); fd = create_file( "f\nbar\nbazinga\n" ); assert( read_trunc( fd, '\n', 2, rbuf, tbuf ) == 2 ); assert( memcmp( rbuf, "f\n", 2 ) == 0 ); assert( read_trunc( fd, '\n', 2, rbuf, tbuf ) == 4 ); assert( memcmp( rbuf, "ba", 2 ) == 0 ); assert( read_trunc( fd, '\n', 3, rbuf, tbuf ) == 8 ); assert( memcmp( rbuf, "baz", 3 ) == 0 ); assert( read_trunc( fd, '\n', 2, rbuf, tbuf ) == 0 ); free( tbuf ); close( fd ); return 0; }