Advertisement
rowers

progrc

Sep 1st, 2014
256
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.61 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 != NULL && next->previous == NULL) {
  149.         return next;
  150.     } else if(next != NULL && next->previous != NULL) {
  151.         return list_head(next);
  152.     } else {
  153.         return previous;
  154.     }
  155. }
  156.  
  157. /*
  158.  * Funkcja szuka wpisu o podanym nazwisku lub jego czesci
  159.  */
  160. void list_find_by_surname(struct Entry *listHead, char *surname) {
  161.     struct Entry *pointer = listHead;
  162.     int index = 0;
  163.  
  164.     while(pointer != NULL) {
  165.         /*
  166.          * Sprawdza czy nazwisko jest rowne podanemu, lub sie od niego zaczyna
  167.          */
  168.         if(strstr(pointer->surname, surname) != NULL) {
  169.             printf("[%d] ", index);
  170.             print_entry(pointer);
  171.         }
  172.  
  173.         pointer = pointer->next;
  174.         index++;
  175.     }
  176. }
  177.  
  178. /*
  179.  * Funkcja szuka wpisu o podanym miescie
  180.  */
  181. void list_find_by_city(struct Entry *listHead, char* city) {
  182.     struct Entry *pointer = listHead;
  183.     int index = 0;
  184.  
  185.     while(pointer != NULL) {
  186.         /*
  187.          * Sprawdza czy miasto odpowiada podanemu
  188.          */
  189.         if(strcmp(pointer->city, city) == 0) {
  190.             printf("[%d] ", index);
  191.             print_entry(pointer);
  192.         }
  193.  
  194.         pointer = pointer->next;
  195.         index++;
  196.     }
  197. }
  198.  
  199. /*
  200.  * Funkcja szuka wpisu o podanym telefonie
  201.  */
  202. struct Entry* list_find_by_phone(struct Entry *listHead, char* phone) {
  203.     struct Entry *pointer = listHead;
  204.     int index = 0;
  205.  
  206.     while(pointer != NULL) {
  207.         /*
  208.          * Sprawdza czy miasto odpowiada podanemu
  209.          */
  210.         if(strcmp(pointer->phone, phone) == 0) {
  211.             printf("[%d] ", index);
  212.             print_entry(pointer);
  213.         }
  214.  
  215.         pointer = pointer->next;
  216.         index++;
  217.     }
  218. }
  219.  
  220. /*
  221.  * Funkcja tworzaca nowy element typu Entry
  222.  */
  223. struct Entry* entry_new(char *name, char *surname, char *city, char *street, char *phone) {
  224.     struct Entry *newEntry = (struct Entry*) malloc(sizeof(struct Entry));
  225.  
  226.     newEntry->previous = NULL;
  227.     newEntry->next = NULL;
  228.  
  229.     strcpy(newEntry->name, name);
  230.     strcpy(newEntry->surname, surname);
  231.     strcpy(newEntry->city, city);
  232.     strcpy(newEntry->street, street);
  233.     strcpy(newEntry->phone, phone);
  234.  
  235.     return newEntry;
  236. }
  237.  
  238. /*
  239.  * Dodaje nowy rekord do listy
  240.  */
  241. struct Entry* entry_add(struct Entry* listHead) {
  242.     char name[50];
  243.     char surname[50];
  244.     char city[50];
  245.     char street[50];
  246.     char phone[50];
  247.  
  248.     SCANFM("Podaj imie: ", "%50s", name);
  249.     SCANFM("Podaj nazwisko: ", "%50s", surname);
  250.     SCANFM("Podaj miasto: ", "%50s", city);
  251.     SCANFM("Podaj ulice: ", "%50s", street);
  252.     SCANFM("Podaj telefon: ", "%50s", phone);
  253.  
  254.     if(listHead == NULL) {
  255.         return entry_new(name, surname, city, street, phone);
  256.     } else {
  257.         return list_push(listHead, entry_new(name, surname, city, street, phone));
  258.     }
  259. }
  260.  
  261. /*
  262.  * Edytuje dany rekord listy
  263.  */
  264. void entry_edit(struct Entry* entry) {
  265.     char name[50];
  266.     char surname[50];
  267.     char city[50];
  268.     char street[50];
  269.     char phone[50];
  270.  
  271.     SCANFM("Podaj imie: ", "%50s", name);
  272.     SCANFM("Podaj nazwisko: ", "%50s", surname);
  273.     SCANFM("Podaj miasto: ", "%50s", city);
  274.     SCANFM("Podaj ulice: ", "%50s", street);
  275.     SCANFM("Podaj telefon: ", "%50s", phone);
  276.  
  277.     strcpy(entry->name, name);
  278.     strcpy(entry->surname, surname);
  279.     strcpy(entry->city, city);
  280.     strcpy(entry->street, street);
  281.     strcpy(entry->phone, phone);
  282.  
  283.     printf("Wpis zaktualizowany:\n");
  284.     print_entry(entry);
  285. }
  286.  
  287. /*
  288.  * Funkcja odpowiada za proces modyfikacji rekordow.
  289.  */
  290. struct Entry* entry_modify(struct Entry *listHead) {
  291.     char choice;
  292.     int index;
  293.  
  294.     SCANFM("Czy chcesz przejsc w tryb modyfikacji rekordow? [t/n]: ", "%c", &choice);
  295.  
  296.     if(choice == 't') {
  297.         SCANFM("Numer rekordu: ", "%d", &index);
  298.  
  299.         struct Entry *entry = list_get(listHead, index);
  300.  
  301.         if(entry == NULL) {
  302.             printf("Wybrany rekord nie istnieje.\n");
  303.  
  304.             return;
  305.         }
  306.  
  307.         SCANFM("Edytuj [e], Usun[d]: ", "%c", &choice);
  308.  
  309.         if(choice == 'e') {
  310.             entry_edit(entry);
  311.         } else if(choice == 'd') {
  312.             listHead = list_delete(entry);
  313.         } else {
  314.             printf("Akcja nie istnieje.");
  315.         }
  316.     }
  317.  
  318.     return listHead;
  319. }
  320.  
  321. /*
  322.  * Funkcja zapisujaca dane do pliku binarnego.
  323.  */
  324. void db_save_data(struct Entry* listHead, char* filename) {
  325.     FILE *handle = fopen(filename, "wb");
  326.     struct Entry* pointer = listHead;
  327.     struct Entry* next = NULL;
  328.  
  329.     if(handle == NULL) {
  330.         printf("=> WRITE: Nie mozna otworzyc pliku z baza danych.");
  331.         return;
  332.     }
  333.  
  334.     unsigned int numberOfRecords = 0;
  335.  
  336.     while(pointer != NULL) {
  337.         numberOfRecords++;
  338.         /*
  339.          * Czyszczenie struktury listy. Po ponownym wczytaniu adresy z pamieci beda nieaktualne.
  340.          */
  341.         next = pointer->next;
  342.         pointer->next = NULL;
  343.         pointer->previous = NULL;
  344.  
  345.         fwrite(pointer, sizeof(struct Entry), 1, handle);
  346.  
  347.         pointer = next;
  348.     }
  349.  
  350.     printf("Zapisano %d rekordow.\n", numberOfRecords);
  351.  
  352.     fclose(handle);
  353. }
  354.  
  355. /*
  356.  * Funkcja ladujaca dane z pliku binarnego.
  357.  */
  358. struct Entry* db_load_data(char* filename) {
  359.     FILE *handle = fopen(filename, "rb");
  360.  
  361.     if(handle == NULL) {
  362.         printf("=> READ: Nie mozna otworzyc pliku z baza danych.");
  363.  
  364.         return NULL;
  365.     }
  366.  
  367.     /*
  368.      * Okresl rozmiar bazy danych.
  369.      */
  370.     fseek(handle, 0, SEEK_END);
  371.     unsigned int fileSize = ftell(handle);
  372.     fseek(handle, 0, SEEK_SET);
  373.  
  374.     struct Entry *listHead = NULL;
  375.  
  376.     /*
  377.      * Okresl ilosc rekordow zapisanych w bazie.
  378.      */
  379.     unsigned int numberOfRecords = fileSize / sizeof(struct Entry);
  380.  
  381.     unsigned int i;
  382.     for(i = 0; i < numberOfRecords; i++) {
  383.         /*
  384.          * Utworzenie bufora o typie struktury Entry.
  385.          */
  386.         struct Entry *buffer = (struct Entry*) malloc(sizeof(struct Entry));
  387.         /*
  388.          * Bezposrednie wczytanie danych do struktury z pliku binarnego.
  389.          */
  390.         fread(buffer, sizeof(struct Entry), 1, handle);
  391.  
  392.         /*
  393.          * Jezeli nie mamy jeszcze listy, zapisz glowe. W przeciwnym razie dolacz do niej dane.
  394.          */
  395.         if(listHead == NULL) {
  396.             listHead = buffer;
  397.  
  398.             buffer->previous = NULL;
  399.         } else {
  400.             list_push(listHead, buffer);
  401.         }
  402.     }
  403.  
  404.     printf("Wczytano %d rekordow.\n", numberOfRecords);
  405.  
  406.     fclose(handle);
  407.  
  408.     return listHead;
  409. }
  410.  
  411. /*
  412.  * Funkcja tworzaca testowa baze danych.
  413.  */
  414. struct Entry* test_data() {
  415.     struct Entry *head = entry_new("Jan", "Kowalski", "Rybnik", "Lipowa 15", "111222333");
  416.     struct Entry *tail = entry_new("Roman", "Jadro", "Warszawa", "Brzozowa 15", "883726621");
  417.  
  418.     list_push(head, tail);
  419.  
  420.     return head;
  421. }
  422.  
  423. * look_for_by(struct Entry* listHead, unsigned int choice) {
  424.     char input[59];
  425.  
  426.     SCANFM("Szukany ciag: ", "%50s", input);
  427.  
  428.     switch(choice) {
  429.         case SURNAME:
  430.             list_find_by_surname(listHead, input);
  431.             break;
  432.         case CITY:
  433.             list_find_by_city(listHead, input);
  434.             break;
  435.         case PHONE:
  436.             list_find_by_phone(listHead, input);
  437.             break;
  438.         default:
  439.             break;
  440.     }
  441. }
  442.  
  443. void print_info() {
  444.     printf("Witaj w ksiazce telefonicznej.\n");
  445.     printf("Dostepne opcje: \n");
  446.     printf("[0]: Zakoncz program.\n");
  447.     printf("[1]: Znajdz osobe po nazwisku.\n");
  448.     printf("[2]: Znajdz osobe po miescie.\n");
  449.     printf("[3]: Znajdz osobe po telefonie.\n");
  450.     printf("[4]: Wydrukuj liste osob.\n");
  451.     printf("[5]: Dodaj osobe do bazy.\n");
  452.     printf("[8]: Pokaz liste funkcji.\n");
  453.     printf("[9]: Utworz testowa baze danych. (jezeli zadna nie jest zaladowana) \n");
  454.     printf("\n");
  455. }
  456.  
  457. int main(int argc, char** args) {
  458.     bool shouldExit = false;
  459.     char shouldSave;
  460.  
  461.     struct Entry *data = NULL;
  462.  
  463.     /*
  464.      * Jezeli przekazano jako argument nazwe bazy danych, zaladuj ja.
  465.      * W przeciwnym wypadku sproboj zaladowac domyslna.
  466.      */
  467.     if(argc > 1) {
  468.         data = db_load_data(args[1]);
  469.     } else {
  470.         data = db_load_data("db.bin");
  471.     }
  472.  
  473.     print_info();
  474.  
  475.     while(!shouldExit) {
  476.         char userOption = '0';
  477.  
  478.         printf("Numer: ");
  479.         scanf("%c", &userOption);
  480.         stdclean();
  481.  
  482.         switch(userOption) {
  483.             case '0':
  484.                 SCANFM("Czy chcesz zapisac baze danych [t/n]: ", "%c", &shouldSave);
  485.  
  486.                 if(shouldSave == 't') {
  487.                     db_save_data(data, "db.bin");
  488.                 }
  489.  
  490.                 shouldExit = true;
  491.                 break;
  492.             case '9':
  493.                 if(data == NULL) {
  494.                     data = test_data();
  495.                 } else {
  496.                     printf("Nie mozna nadpisac aktualnej bazy danych.\n");
  497.                 }
  498.                 break;
  499.             case '1':
  500.                 look_for_by(data, SURNAME);
  501.                 data = entry_modify(data);
  502.                 break;
  503.             case '2':
  504.                 look_for_by(data, CITY);
  505.                 data = entry_modify(data);
  506.                 break;
  507.             case '3':
  508.                 look_for_by(data, PHONE);
  509.                 data = entry_modify(data);
  510.                 break;
  511.             case '4':
  512.                 print_list(data);
  513.                 data = entry_modify(data);
  514.                 break;
  515.             case '5':
  516.                 data = entry_add(data);
  517.                 break;
  518.             case '8':
  519.                 print_info();
  520.                 break;
  521.             default:
  522.                 printf("Brak funkcji dla akcji \"%c\"\n", userOption);
  523.                 break;
  524.         }
  525.     }
  526.  
  527.     return EXIT_SUCCESS;
  528. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement