Search
FILE *fopen(const char *path, const char *mode); size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); int fclose( FILE *stream );
book.h
#ifndef __BOOK_H__ #define __BOOK_H__ #include <stdio.h> #define MAX_NAME_SIZE 19 struct Book { int year; char title[MAX_NAME_SIZE]; char* abstract; }; typedef struct Book Book; struct BookList { Book** books; size_t size; }; typedef struct BookList BookList; Book* create_book(int year, const char* title, const char* abstract); void destroy_book(Book* b); void print_book(Book* b); BookList* create_book_list(); void destroy_book_list(BookList* bl); void add_book(BookList* bl, Book* b); void print_book_list(BookList* bl); #endif
book.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "book.h" Book* create_book(int year, const char* title, const char* abstract) { Book* p = (Book*)malloc(sizeof(Book)); if (p == NULL) { printf("Error: malloc failed in create_book\n"); return NULL; } p->year = year; for (size_t i = 0; i < MAX_NAME_SIZE; i++) { p->title[i] = '\0'; // erase "dangerous" leftover data } for (size_t i = 0; i < MAX_NAME_SIZE-1; i++) { p->title[i] = title[i]; if (title[i] == '\0') { break; } } if (abstract == NULL) { p->abstract = NULL; } else { p->abstract = (char*)malloc(strlen(abstract) + 1); if (p->abstract == NULL) { printf("Error: malloc abstract failed in create_book\n"); free(p); return NULL; } strcpy(p->abstract, abstract); } return p; } void destroy_book(Book* p) { free(p->abstract); free(p); } void print_book(Book* p) { printf("Title: %s, Publication year: %d, Abstract: %s\n", p->title, p->year, p->abstract); } BookList* create_book_list() { BookList* pl = (BookList*)malloc(sizeof(BookList)); if (pl == NULL) { printf("Error: malloc failed in create_book_list\n"); return NULL; } pl->books = NULL; pl->size = 0; return pl; } void add_book(BookList* pl, Book* p) { Book** people_ = (Book**) realloc(pl->books, (pl->size + 1) * sizeof(Book*)); if (people_ == NULL) { printf("Warning: Adding failed, no modification is being done.\n"); return; } pl->books = people_; (pl->books)[pl->size] = p; pl->size++; } void destroy_book_list(BookList* pl) { for (size_t i = 0; i < pl->size; i++) { destroy_book(pl->books[i]); pl->books[i] = NULL; } free(pl->books); free(pl); } void print_book_list(BookList* pl) { for (size_t i = 0; i < pl->size; i++) { printf("Book %zu:\n", i); print_book(pl->books[i]); } }
main.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "book.h" BookList* get_example_list(); void test_list_contents(); int main() { test_list_contents(); return 0; } BookList* get_example_list() { BookList* pl = create_book_list(); Book* p1 = create_book(2005, "Programming in C", "Programming in C will teach you how to write programs in the C programming language."); Book* p2 = create_book(161, "Meditations", NULL); Book* p3 = create_book(-1500, "Poor Man of Nipur", ""); add_book(pl, p1); add_book(pl, p2); add_book(pl, p3); return pl; } void test_list_contents() { BookList* pl = get_example_list(); print_book_list(pl); destroy_book_list(pl); }
run
$ gcc -Wall -pedantic -O3 -g main.c book.c -o app $ ./app Book 0: Title: Programming in C, Publication year: 2005, Abstract: Programming in C will teach you how to write programs in the C programming language. Book 1: Title: Meditations, Publication year: 161, Abstract: (null) Book 2: Title: Poor Man of Nipur, Publication year: -1500, Abstract:
Poskytnutá knihovna pracuje s kolekcí struktur Book, která uchovává informace o jednotlivých svazcích. Naším úkolem je tuto kolekci uložit do (a načíst z) binárního souboru. Z paměťového hlediska chceme překopírovat bajty rozmístěné v operační paměti do sekvence (stream) bajtů reprezentované FILE.
Book
hexdump -C
BookList *pl = get_example_list(); Book *p = pl->books[0]; fwrite(p, sizeof(Book), 1, f);
.title
.abstract
.year
.abstract=“”
.abstract=NULL
Použijte nově nabité znalosti k implementaci knihovny:
book_serializer.h
#ifndef __BOOK_SERIALIZER_H__ #define __BOOK_SERIALIZER_H__ #include <stdio.h> #include "book.h" void serialize_book(FILE* f, Book* p); Book* deserialize_book(FILE* f); void serialize_book_list(FILE* f, BookList* pl); BookList* deserialize_book_list(FILE* f); #endif
serialize_book
deserialize_book
test_list_contents()
serialize_book_list
deserialize_book_list
V Structure Layout jsme se dočetli, že padding ve struct závisí na lokální platformě. Lokální reprezentace hodnot v paměti se ale může lišit i v pořadí bajtů, tzv. endianita. Pokud místo na disk bychom posílali bajty přes síť, tak dle konvencí (např. v IP) bajtové pořadí má být big-endian (tedy platforma která přijímá data ze sítě očekává big-endian).
le_to_be
stdint.h
uint32_t le_to_be(uint32_t v);
uint32_t host_to_net32(uint32_t v)
uint32_t htonl(uint32_t hostlong);
float