Advertisement
rowers

projectc2

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