Advertisement
rowers

projektc

Aug 25th, 2014
244
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.51 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4. #include <string.h>
  5.  
  6. /*
  7.  * Pomocnicze DEFINE'y.
  8.  */
  9. #define SCANFM(message, format, variable) printf(message); scanf(format, variable); stdclean();
  10.  
  11. #define SURNAME 0x01
  12. #define CITY 0x02
  13. #define PHONE 0x03
  14.  
  15. /*
  16.  * Glowna struktura.
  17.  */
  18. struct Entry {
  19.     struct Entry *next;
  20.     struct Entry *previous;
  21.  
  22.     char name[50];
  23.     char surname[50];
  24.     char city[50];
  25.     char street[50];
  26.     char phone[50];
  27. };
  28.  
  29. /*
  30.  * Czysci strumien wejscia ze smieci.
  31.  * Zapobiega sytuacja kiedy scanf pobieralby niewlasciwe dane.
  32.  */
  33. void stdclean() {
  34.     char c;
  35.  
  36.     while((c = getchar()) != '\n' && c != EOF);
  37. }
  38.  
  39. /*
  40.  * Drukuje rekord na ekran
  41.  */
  42. void print_entry(struct Entry* entry) {
  43.     printf("%s %s\n", entry->name, entry->surname);
  44.     printf("%s %s\n", entry->street, entry->city);
  45.     printf("%s\n\n", entry->phone);
  46. }
  47.  
  48.  
  49. /*
  50.  * Drukuje liste rekordow na ekran wraz z ich indeksami
  51.  */
  52. void print_list(struct Entry* listHead) {
  53.     struct Entry *pointer = listHead;
  54.     int index = 0;
  55.  
  56.     while(pointer != NULL) {
  57.         printf("[%d] ", index);
  58.         print_entry(pointer);
  59.  
  60.         pointer = pointer->next;
  61.  
  62.         index++;
  63.     }
  64. }
  65.  
  66. /*
  67.  * Funkcja zwraca dĹ‚ugość listy
  68.  */
  69. int list_length(struct Entry *listHead) {
  70.     struct Entry *pointer = listHead;
  71.     unsigned int listLength = 0;
  72.  
  73.     while(pointer != NULL) {
  74.         listLength++;
  75.  
  76.         pointer = pointer->next;
  77.     }
  78. }
  79.  
  80. /*
  81.  * Funkcja umieszczajaca nowy element na koncu listy
  82.  */
  83. struct Entry *list_push(struct Entry *listHead, struct Entry *newEntry) {
  84.     struct Entry *pointer = listHead;
  85.  
  86.     while(pointer->next != NULL) {
  87.         pointer = pointer->next;
  88.     }
  89.  
  90.     pointer->next = newEntry;
  91.     newEntry->previous = pointer;
  92.  
  93.     return listHead;
  94. }
  95.  
  96. /*
  97.  * Funkcja zwraca glowe listy
  98.  */
  99. struct Entry* list_head(struct Entry *listEntry) {
  100.     struct Entry *pointer = listEntry;
  101.  
  102.     while(pointer->previous != NULL) {
  103.         pointer = pointer->previous;
  104.     }
  105.  
  106.     return pointer;
  107. }
  108.  
  109. /*
  110.  * Funkcja zwraca element na ntej pozycji
  111.  */
  112. struct Entry* list_get(struct Entry* listHead, unsigned int pos) {
  113.     struct Entry *pointer = listHead;
  114.     unsigned int currentPos = 0;
  115.  
  116.     while(pointer != NULL && currentPos != pos) {
  117.         pointer = pointer->next;
  118.         currentPos++;
  119.     }
  120.  
  121.     return pointer;
  122. }
  123.  
  124. /*
  125.  * Funkcja usuwa element z listy
  126.  */
  127. struct Entry* list_delete(struct Entry *newEntry) {
  128.     struct Entry *previous = newEntry->previous;
  129.     struct Entry *next = newEntry->next;
  130.  
  131.     /*
  132.      * Zwolnij zasoby, usun rekord.
  133.      */
  134.     free(newEntry);
  135.  
  136.     if(previous != NULL) {
  137.         previous->next = next;
  138.     }
  139.  
  140.     if(next != NULL) {
  141.         next->previous = previous;
  142.     }
  143.  
  144.     /*
  145.      * Jezeli usuniety element byl glowa, zwroc nastepny.
  146.      * W przeciwnym wypadku zwroc glowe listy;
  147.      */
  148.     if(next->previous == NULL) {
  149.         return next;
  150.     } else {
  151.         return list_head(next);
  152.     }
  153. }
  154.  
  155. /*
  156.  * Funkcja szuka wpisu o podanym nazwisku lub jego czesci
  157.  */
  158. void list_find_by_surname(struct Entry *listHead, char *surname) {
  159.     struct Entry *pointer = listHead;
  160.     int index = 0;
  161.  
  162.     while(pointer != NULL) {
  163.         /*
  164.          * Sprawdza czy nazwisko jest rowne podanemu, lub sie od niego zaczyna
  165.          */
  166.         if(strstr(pointer->surname, surname) != NULL) {
  167.             printf("[%d] ", index);
  168.             print_entry(pointer);
  169.         }
  170.  
  171.         pointer = pointer->next;
  172.         index++;
  173.     }
  174. }
  175.  
  176. /*
  177.  * Funkcja szuka wpisu o podanym miescie
  178.  */
  179. void list_find_by_city(struct Entry *listHead, char* city) {
  180.     struct Entry *pointer = listHead;
  181.     int index = 0;
  182.  
  183.     while(pointer != NULL) {
  184.         /*
  185.          * Sprawdza czy miasto odpowiada podanemu
  186.          */
  187.         if(strcmp(pointer->city, city) == 0) {
  188.             printf("[%d] ", index);
  189.             print_entry(pointer);
  190.         }
  191.  
  192.         pointer = pointer->next;
  193.         index++;
  194.     }
  195. }
  196.  
  197. /*
  198.  * Funkcja szuka wpisu o podanym telefonie
  199.  */
  200. struct Entry* list_find_by_phone(struct Entry *listHead, char* phone) {
  201.     struct Entry *pointer = listHead;
  202.     int index = 0;
  203.  
  204.     while(pointer != NULL) {
  205.         /*
  206.          * Sprawdza czy miasto odpowiada podanemu
  207.          */
  208.         if(strcmp(pointer->phone, phone) == 0) {
  209.             printf("[%d] ", index);
  210.             print_entry(pointer);
  211.         }
  212.  
  213.         pointer = pointer->next;
  214.         index++;
  215.     }
  216. }
  217.  
  218. /*
  219.  * Funkcja tworzaca nowy element typu Entry
  220.  */
  221. struct Entry* entry_new(char *name, char *surname, char *city, char *street, char *phone) {
  222.     struct Entry *newEntry = (struct Entry*) malloc(sizeof(struct Entry));
  223.  
  224.     newEntry->previous = NULL;
  225.     newEntry->next = NULL;
  226.  
  227.     strcpy(newEntry->name, name);
  228.     strcpy(newEntry->surname, surname);
  229.     strcpy(newEntry->city, city);
  230.     strcpy(newEntry->street, street);
  231.     strcpy(newEntry->phone, phone);
  232.  
  233.     return newEntry;
  234. }
  235.  
  236. /*
  237.  * Dodaje nowy rekord do listy
  238.  */
  239. struct Entry* entry_add(struct Entry* listHead) {
  240.     char name[50];
  241.     char surname[50];
  242.     char city[50];
  243.     char street[50];
  244.     char phone[50];
  245.  
  246.     SCANFM("Podaj imie: ", "%50s", name);
  247.     SCANFM("Podaj nazwisko: ", "%50s", surname);
  248.     SCANFM("Podaj miasto: ", "%50s", city);
  249.     SCANFM("Podaj ulice: ", "%50s", street);
  250.     SCANFM("Podaj telefon: ", "%50s", phone);
  251.  
  252.     if(listHead == NULL) {
  253.         return entry_new(name, surname, city, street, phone);
  254.     } else {
  255.         return list_push(listHead, entry_new(name, surname, city, street, phone));
  256.     }
  257. }
  258.  
  259. /*
  260.  * Edytuje dany rekord listy
  261.  */
  262. void entry_edit(struct Entry* entry) {
  263.     char name[50];
  264.     char surname[50];
  265.     char city[50];
  266.     char street[50];
  267.     char phone[50];
  268.  
  269.     SCANFM("Podaj imie: ", "%50s", name);
  270.     SCANFM("Podaj nazwisko: ", "%50s", surname);
  271.     SCANFM("Podaj miasto: ", "%50s", city);
  272.     SCANFM("Podaj ulice: ", "%50s", street);
  273.     SCANFM("Podaj telefon: ", "%50s", phone);
  274.  
  275.     strcpy(entry->name, name);
  276.     strcpy(entry->surname, surname);
  277.     strcpy(entry->city, city);
  278.     strcpy(entry->street, street);
  279.     strcpy(entry->phone, phone);
  280.  
  281.     printf("Wpis zaktualizowany:\n");
  282.     print_entry(entry);
  283. }
  284.  
  285. /*
  286.  * Funkcja odpowiada za proces modyfikacji rekordow.
  287.  */
  288. struct Entry* entry_modify(struct Entry *listHead) {
  289.     char choice;
  290.     int index;
  291.  
  292.     SCANFM("Czy chcesz przejsc w tryb modyfikacji rekordow? [t/n]: ", "%c", &choice);
  293.  
  294.     if(choice == 't') {
  295.         SCANFM("Numer rekordu: ", "%d", &index);
  296.  
  297.         struct Entry *entry = list_get(listHead, index);
  298.  
  299.         if(entry == NULL) {
  300.             printf("Wybrany rekord nie istnieje.\n");
  301.             return;
  302.         }
  303.  
  304.         SCANFM("Edytuj [e], Usun[d]: ", "%c", &choice);
  305.  
  306.         if(choice == 'e') {
  307.             entry_edit(entry);
  308.         } else if(choice == 'd') {
  309.             listHead = list_delete(entry);
  310.         } else {
  311.             printf("Akcja nie istnieje.");
  312.         }
  313.     }
  314.  
  315.     return listHead;
  316. }
  317.  
  318. /*
  319.  * Funkcja zapisujaca dane do pliku binarnego.
  320.  */
  321. void db_save_data(struct Entry* listHead, char* filename) {
  322.     FILE *handle = fopen(filename, "wb");
  323.     struct Entry* pointer = listHead;
  324.     struct Entry* next = NULL;
  325.  
  326.     if(handle == NULL) {
  327.         printf("=> WRITE: Nie mozna otworzyc pliku z baza danych.");
  328.         return;
  329.     }
  330.  
  331.     unsigned int numberOfRecords = 0;
  332.  
  333.     while(pointer != NULL) {
  334.         numberOfRecords++;
  335.         /*
  336.          * Czyszczenie struktury listy. Po ponownym wczytaniu adresy z pamieci beda nieaktualne.
  337.          */
  338.         next = pointer->next;
  339.         pointer->next = NULL;
  340.         pointer->previous = NULL;
  341.  
  342.         fwrite(pointer, sizeof(struct Entry), 1, handle);
  343.  
  344.         pointer = next;
  345.     }
  346.  
  347.     printf("Zapisano %d rekordow.\n", numberOfRecords);
  348.  
  349.     fclose(handle);
  350. }
  351.  
  352. /*
  353.  * Funkcja ladujaca dane z pliku binarnego.
  354.  */
  355. struct Entry* db_load_data(char* filename) {
  356.     FILE *handle = fopen(filename, "rb");
  357.  
  358.     if(handle == NULL) {
  359.         printf("=> READ: Nie mozna otworzyc pliku z baza danych.");
  360.  
  361.         return NULL;
  362.     }
  363.  
  364.     /*
  365.      * Okresl rozmiar bazy danych.
  366.      */
  367.     fseek(handle, 0, SEEK_END);
  368.     unsigned int fileSize = ftell(handle);
  369.     fseek(handle, 0, SEEK_SET);
  370.  
  371.     struct Entry *listHead = NULL;
  372.  
  373.     /*
  374.      * Okresl ilosc rekordow zapisanych w bazie.
  375.      */
  376.     unsigned int numberOfRecords = fileSize / sizeof(struct Entry);
  377.  
  378.     unsigned int i;
  379.     for(i = 0; i < numberOfRecords; i++) {
  380.         /*
  381.          * Utworzenie bufora o typie struktury Entry.
  382.          */
  383.         struct Entry *buffer = (struct Entry*) malloc(sizeof(struct Entry));
  384.         /*
  385.          * Bezposrednie wczytanie danych do struktury z pliku binarnego.
  386.          */
  387.         fread(buffer, sizeof(struct Entry), 1, handle);
  388.  
  389.         /*
  390.          * Jezeli nie mamy jeszcze listy, zapisz glowe. W przeciwnym razie dolacz do niej dane.
  391.          */
  392.         if(listHead == NULL) {
  393.             listHead = buffer;
  394.  
  395.             buffer->previous = NULL;
  396.         } else {
  397.             list_push(listHead, buffer);
  398.         }
  399.     }
  400.  
  401.     printf("Wczytano %d rekordow.\n", numberOfRecords);
  402.  
  403.     fclose(handle);
  404.  
  405.     return listHead;
  406. }
  407.  
  408. /*
  409.  * Funkcja tworzaca testowa baze danych.
  410.  */
  411. struct Entry* test_data() {
  412.     struct Entry *head = entry_new("Jan", "Kowalski", "Rybnik", "Lipowa 15", "111222333");
  413.     struct Entry *tail = entry_new("Roman", "Jadro", "Warszawa", "Brzozowa 15", "883726621");
  414.  
  415.     list_push(head, tail);
  416.  
  417.     return head;
  418. }
  419.  
  420. * look_for_by(struct Entry* listHead, unsigned int choice) {
  421.     char input[59];
  422.  
  423.     SCANFM("Szukany ciag: ", "%50s", input);
  424.  
  425.     switch(choice) {
  426.         case SURNAME:
  427.             list_find_by_surname(listHead, input);
  428.             break;
  429.         case CITY:
  430.             list_find_by_city(listHead, input);
  431.             break;
  432.         case PHONE:
  433.             list_find_by_phone(listHead, input);
  434.             break;
  435.         default:
  436.             break;
  437.     }
  438. }
  439.  
  440. void print_info() {
  441.     printf("Witaj w ksiazce telefonicznej.\n");
  442.     printf("Dostepne opcje: \n");
  443.     printf("[0]: Zakoncz program.\n");
  444.     printf("[1]: Znajdz osobe po nazwisku.\n");
  445.     printf("[2]: Znajdz osobe po miescie.\n");
  446.     printf("[3]: Znajdz osobe po telefonie.\n");
  447.     printf("[4]: Wydrukuj liste osob.\n");
  448.     printf("[5]: Dodaj osobe do bazy.\n");
  449.     printf("[8]: Pokaz liste funkcji.\n");
  450.     printf("[9]: Utworz testowa baze danych. (jezeli zadna nie jest zaladowana) \n");
  451.     printf("\n");
  452. }
  453.  
  454. int main(int argc, char** args) {
  455.     bool shouldExit = false;
  456.     char shouldSave;
  457.  
  458.     struct Entry *data = NULL;
  459.  
  460.     /*
  461.      * Jezeli przekazano jako argument nazwe bazy danych, zaladuj ja.
  462.      * W przeciwnym wypadku sproboj zaladowac domyslna.
  463.      */
  464.     if(argc > 1) {
  465.         data = db_load_data(args[1]);
  466.     } else {
  467.         data = db_load_data("db.bin");
  468.     }
  469.  
  470.     print_info();
  471.  
  472.     while(!shouldExit) {
  473.         char userOption = '0';
  474.  
  475.         printf("Numer: ");
  476.         scanf("%c", &userOption);
  477.         stdclean();
  478.  
  479.         switch(userOption) {
  480.             case '0':
  481.                 SCANFM("Czy chcesz zapisac baze danych [t/n]: ", "%c", &shouldSave);
  482.  
  483.                 if(shouldSave == 't') {
  484.                     db_save_data(data, "db.bin");
  485.                 }
  486.  
  487.                 shouldExit = true;
  488.                 break;
  489.             case '9':
  490.                 if(data == NULL) {
  491.                     data = test_data();
  492.                 } else {
  493.                     printf("Nie mozna nadpisac aktualnej bazy danych.\n");
  494.                 }
  495.                 break;
  496.             case '1':
  497.                 look_for_by(data, SURNAME);
  498.                 data = entry_modify(data);
  499.                 break;
  500.             case '2':
  501.                 look_for_by(data, CITY);
  502.                 data = entry_modify(data);
  503.                 break;
  504.             case '3':
  505.                 look_for_by(data, PHONE);
  506.                 data = entry_modify(data);
  507.                 break;
  508.             case '4':
  509.                 print_list(data);
  510.                 data = entry_modify(data);
  511.                 break;
  512.             case '5':
  513.                 data = entry_add(data);
  514.                 break;
  515.             case '8':
  516.                 print_info();
  517.                 break;
  518.             default:
  519.                 printf("Brak funkcji dla akcji \"%c\"\n", userOption);
  520.                 break;
  521.         }
  522.     }
  523.  
  524.     return EXIT_SUCCESS;
  525. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement