Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include <string.h>
- /*
- * Pomocnicze DEFINE'y.
- */
- #define SCANFM(message, format, variable) printf(message); scanf(format, variable); stdclean();
- #define SURNAME 0x01
- #define CITY 0x02
- #define PHONE 0x03
- /*
- * Glowna struktura.
- */
- struct Entry {
- struct Entry *next;
- struct Entry *previous;
- char name[50];
- char surname[50];
- char city[50];
- char street[50];
- char phone[50];
- };
- /*
- * Czysci strumien wejscia ze smieci.
- * Zapobiega sytuacja kiedy scanf pobieralby niewlasciwe dane.
- */
- void stdclean() {
- char c;
- while((c = getchar()) != '\n' && c != EOF);
- }
- /*
- * Drukuje rekord na ekran
- */
- void print_entry(struct Entry* entry) {
- printf("%s %s\n", entry->name, entry->surname);
- printf("%s %s\n", entry->street, entry->city);
- printf("%s\n\n", entry->phone);
- }
- /*
- * Drukuje liste rekordow na ekran wraz z ich indeksami
- */
- void print_list(struct Entry* listHead) {
- struct Entry *pointer = listHead;
- int index = 0;
- while(pointer != NULL) {
- printf("[%d] ", index);
- print_entry(pointer);
- pointer = pointer->next;
- index++;
- }
- }
- /*
- * Funkcja zwraca długość listy
- */
- int list_length(struct Entry *listHead) {
- struct Entry *pointer = listHead;
- unsigned int listLength = 0;
- while(pointer != NULL) {
- listLength++;
- pointer = pointer->next;
- }
- }
- /*
- * Funkcja umieszczajaca nowy element na koncu listy
- */
- struct Entry *list_push(struct Entry *listHead, struct Entry *newEntry) {
- struct Entry *pointer = listHead;
- while(pointer->next != NULL) {
- pointer = pointer->next;
- }
- pointer->next = newEntry;
- newEntry->previous = pointer;
- return listHead;
- }
- /*
- * Funkcja zwraca glowe listy
- */
- struct Entry* list_head(struct Entry *listEntry) {
- struct Entry *pointer = listEntry;
- while(pointer->previous != NULL) {
- pointer = pointer->previous;
- }
- return pointer;
- }
- /*
- * Funkcja zwraca element na ntej pozycji
- */
- struct Entry* list_get(struct Entry* listHead, unsigned int pos) {
- struct Entry *pointer = listHead;
- unsigned int currentPos = 0;
- while(pointer != NULL && currentPos != pos) {
- pointer = pointer->next;
- currentPos++;
- }
- return pointer;
- }
- /*
- * Funkcja usuwa element z listy
- */
- struct Entry* list_delete(struct Entry *newEntry) {
- struct Entry *previous = newEntry->previous;
- struct Entry *next = newEntry->next;
- /*
- * Zwolnij zasoby, usun rekord.
- */
- free(newEntry);
- if(previous != NULL) {
- previous->next = next;
- }
- if(next != NULL) {
- next->previous = previous;
- }
- /*
- * Jezeli usuniety element byl glowa, zwroc nastepny.
- * W przeciwnym wypadku zwroc glowe listy;
- */
- if(next->previous == NULL) {
- return next;
- } else {
- return list_head(next);
- }
- }
- /*
- * Funkcja szuka wpisu o podanym nazwisku lub jego czesci
- */
- void list_find_by_surname(struct Entry *listHead, char *surname) {
- struct Entry *pointer = listHead;
- int index = 0;
- while(pointer != NULL) {
- /*
- * Sprawdza czy nazwisko jest rowne podanemu, lub sie od niego zaczyna
- */
- if(strstr(pointer->surname, surname) != NULL) {
- printf("[%d] ", index);
- print_entry(pointer);
- }
- pointer = pointer->next;
- index++;
- }
- }
- /*
- * Funkcja szuka wpisu o podanym miescie
- */
- void list_find_by_city(struct Entry *listHead, char* city) {
- struct Entry *pointer = listHead;
- int index = 0;
- while(pointer != NULL) {
- /*
- * Sprawdza czy miasto odpowiada podanemu
- */
- if(strcmp(pointer->city, city) == 0) {
- printf("[%d] ", index);
- print_entry(pointer);
- }
- pointer = pointer->next;
- index++;
- }
- }
- /*
- * Funkcja szuka wpisu o podanym telefonie
- */
- struct Entry* list_find_by_phone(struct Entry *listHead, char* phone) {
- struct Entry *pointer = listHead;
- int index = 0;
- while(pointer != NULL) {
- /*
- * Sprawdza czy miasto odpowiada podanemu
- */
- if(strcmp(pointer->phone, phone) == 0) {
- printf("[%d] ", index);
- print_entry(pointer);
- }
- pointer = pointer->next;
- index++;
- }
- }
- /*
- * Funkcja tworzaca nowy element typu Entry
- */
- struct Entry* entry_new(char *name, char *surname, char *city, char *street, char *phone) {
- struct Entry *newEntry = (struct Entry*) malloc(sizeof(struct Entry));
- newEntry->previous = NULL;
- newEntry->next = NULL;
- strcpy(newEntry->name, name);
- strcpy(newEntry->surname, surname);
- strcpy(newEntry->city, city);
- strcpy(newEntry->street, street);
- strcpy(newEntry->phone, phone);
- return newEntry;
- }
- /*
- * Dodaje nowy rekord do listy
- */
- struct Entry* entry_add(struct Entry* listHead) {
- char name[50];
- char surname[50];
- char city[50];
- char street[50];
- char phone[50];
- SCANFM("Podaj imie: ", "%50s", name);
- SCANFM("Podaj nazwisko: ", "%50s", surname);
- SCANFM("Podaj miasto: ", "%50s", city);
- SCANFM("Podaj ulice: ", "%50s", street);
- SCANFM("Podaj telefon: ", "%50s", phone);
- if(listHead == NULL) {
- return entry_new(name, surname, city, street, phone);
- } else {
- return list_push(listHead, entry_new(name, surname, city, street, phone));
- }
- }
- /*
- * Edytuje dany rekord listy
- */
- void entry_edit(struct Entry* entry) {
- char name[50];
- char surname[50];
- char city[50];
- char street[50];
- char phone[50];
- SCANFM("Podaj imie: ", "%50s", name);
- SCANFM("Podaj nazwisko: ", "%50s", surname);
- SCANFM("Podaj miasto: ", "%50s", city);
- SCANFM("Podaj ulice: ", "%50s", street);
- SCANFM("Podaj telefon: ", "%50s", phone);
- strcpy(entry->name, name);
- strcpy(entry->surname, surname);
- strcpy(entry->city, city);
- strcpy(entry->street, street);
- strcpy(entry->phone, phone);
- printf("Wpis zaktualizowany:\n");
- print_entry(entry);
- }
- /*
- * Funkcja odpowiada za proces modyfikacji rekordow.
- */
- struct Entry* entry_modify(struct Entry *listHead) {
- char choice;
- int index;
- SCANFM("Czy chcesz przejsc w tryb modyfikacji rekordow? [t/n]: ", "%c", &choice);
- if(choice == 't') {
- SCANFM("Numer rekordu: ", "%d", &index);
- struct Entry *entry = list_get(listHead, index);
- if(entry == NULL) {
- printf("Wybrany rekord nie istnieje.\n");
- return;
- }
- SCANFM("Edytuj [e], Usun[d]: ", "%c", &choice);
- if(choice == 'e') {
- entry_edit(entry);
- } else if(choice == 'd') {
- listHead = list_delete(entry);
- } else {
- printf("Akcja nie istnieje.");
- }
- }
- return listHead;
- }
- /*
- * Funkcja zapisujaca dane do pliku binarnego.
- */
- void db_save_data(struct Entry* listHead, char* filename) {
- FILE *handle = fopen(filename, "wb");
- struct Entry* pointer = listHead;
- struct Entry* next = NULL;
- if(handle == NULL) {
- printf("=> WRITE: Nie mozna otworzyc pliku z baza danych.");
- return;
- }
- unsigned int numberOfRecords = 0;
- while(pointer != NULL) {
- numberOfRecords++;
- /*
- * Czyszczenie struktury listy. Po ponownym wczytaniu adresy z pamieci beda nieaktualne.
- */
- next = pointer->next;
- pointer->next = NULL;
- pointer->previous = NULL;
- fwrite(pointer, sizeof(struct Entry), 1, handle);
- pointer = next;
- }
- printf("Zapisano %d rekordow.\n", numberOfRecords);
- fclose(handle);
- }
- /*
- * Funkcja ladujaca dane z pliku binarnego.
- */
- struct Entry* db_load_data(char* filename) {
- FILE *handle = fopen(filename, "rb");
- if(handle == NULL) {
- printf("=> READ: Nie mozna otworzyc pliku z baza danych.");
- return NULL;
- }
- /*
- * Okresl rozmiar bazy danych.
- */
- fseek(handle, 0, SEEK_END);
- unsigned int fileSize = ftell(handle);
- fseek(handle, 0, SEEK_SET);
- struct Entry *listHead = NULL;
- /*
- * Okresl ilosc rekordow zapisanych w bazie.
- */
- unsigned int numberOfRecords = fileSize / sizeof(struct Entry);
- unsigned int i;
- for(i = 0; i < numberOfRecords; i++) {
- /*
- * Utworzenie bufora o typie struktury Entry.
- */
- struct Entry *buffer = (struct Entry*) malloc(sizeof(struct Entry));
- /*
- * Bezposrednie wczytanie danych do struktury z pliku binarnego.
- */
- fread(buffer, sizeof(struct Entry), 1, handle);
- /*
- * Jezeli nie mamy jeszcze listy, zapisz glowe. W przeciwnym razie dolacz do niej dane.
- */
- if(listHead == NULL) {
- listHead = buffer;
- buffer->previous = NULL;
- } else {
- list_push(listHead, buffer);
- }
- }
- printf("Wczytano %d rekordow.\n", numberOfRecords);
- fclose(handle);
- return listHead;
- }
- /*
- * Funkcja tworzaca testowa baze danych.
- */
- struct Entry* test_data() {
- struct Entry *head = entry_new("Jan", "Kowalski", "Rybnik", "Lipowa 15", "111222333");
- struct Entry *tail = entry_new("Roman", "Jadro", "Warszawa", "Brzozowa 15", "883726621");
- list_push(head, tail);
- return head;
- }
- * look_for_by(struct Entry* listHead, unsigned int choice) {
- char input[59];
- SCANFM("Szukany ciag: ", "%50s", input);
- switch(choice) {
- case SURNAME:
- list_find_by_surname(listHead, input);
- break;
- case CITY:
- list_find_by_city(listHead, input);
- break;
- case PHONE:
- list_find_by_phone(listHead, input);
- break;
- default:
- break;
- }
- }
- void print_info() {
- printf("Witaj w ksiazce telefonicznej.\n");
- printf("Dostepne opcje: \n");
- printf("[0]: Zakoncz program.\n");
- printf("[1]: Znajdz osobe po nazwisku.\n");
- printf("[2]: Znajdz osobe po miescie.\n");
- printf("[3]: Znajdz osobe po telefonie.\n");
- printf("[4]: Wydrukuj liste osob.\n");
- printf("[5]: Dodaj osobe do bazy.\n");
- printf("[8]: Pokaz liste funkcji.\n");
- printf("[9]: Utworz testowa baze danych. (jezeli zadna nie jest zaladowana) \n");
- printf("\n");
- }
- int main(int argc, char** args) {
- bool shouldExit = false;
- char shouldSave;
- struct Entry *data = NULL;
- /*
- * Jezeli przekazano jako argument nazwe bazy danych, zaladuj ja.
- * W przeciwnym wypadku sproboj zaladowac domyslna.
- */
- if(argc > 1) {
- data = db_load_data(args[1]);
- } else {
- data = db_load_data("db.bin");
- }
- print_info();
- while(!shouldExit) {
- char userOption = '0';
- printf("Numer: ");
- scanf("%c", &userOption);
- stdclean();
- switch(userOption) {
- case '0':
- SCANFM("Czy chcesz zapisac baze danych [t/n]: ", "%c", &shouldSave);
- if(shouldSave == 't') {
- db_save_data(data, "db.bin");
- }
- shouldExit = true;
- break;
- case '9':
- if(data == NULL) {
- data = test_data();
- } else {
- printf("Nie mozna nadpisac aktualnej bazy danych.\n");
- }
- break;
- case '1':
- look_for_by(data, SURNAME);
- data = entry_modify(data);
- break;
- case '2':
- look_for_by(data, CITY);
- data = entry_modify(data);
- break;
- case '3':
- look_for_by(data, PHONE);
- data = entry_modify(data);
- break;
- case '4':
- print_list(data);
- data = entry_modify(data);
- break;
- case '5':
- data = entry_add(data);
- break;
- case '8':
- print_info();
- break;
- default:
- printf("Brak funkcji dla akcji \"%c\"\n", userOption);
- break;
- }
- }
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement