Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Potrzebny plik: D:\db.txt z danymi np:
- Frederik|Doane|2
- Kate|Wank|6
- Law|Harasymiak|3
- Fairy|Pannone|1
- Ripley|Loster|8
- Trenna|Jacob|7
- Evin|Nicholls|5
- Abbie|Backman|4
- Tybalt|Fargo|10
- Becka|Nitabach|9
- */
- #include <stdlib.h> // dla NULL
- #include <stdio.h> // dla printf
- #include <stdbool.h> // dla bool oraz false i true
- #include <string.h> // dla memcpy, memset i strcmp
- #include <stdarg.h> //dla va_list, va_arg, va_start|_end
- #include "Windows.h" // dla milliseconds_now()
- void remove_tail(struct sNode **head);
- void remove_head(struct sNode **head);
- enum SinglyLinkedListPushMethod { PUSH_FRONT = 0, PUSH_BACK = 1 };
- enum PersonFilterOptions { PERSON = 0, NAME = 1, SURNAME = 2, AGE = 3 };
- enum StringCompareStyle { CASE_SENSITIVE = 0, CASE_INSENSITIVE = 1 };
- /*
- Struktura reprezentująca osobę
- */
- struct sPerson
- {
- char *name;
- char *surname;
- unsigned short int age;
- };
- /*
- Struktura reprezentująca węzeł w liście jednokierunkowej
- */
- struct sNode
- {
- struct sPerson *person;
- struct sNode *next;
- };
- // Nie dotykać
- const size_t SIZE_T_UINT = sizeof(unsigned short int);
- const size_t SIZE_T_CHAR = sizeof(char);
- const size_t SIZE_T_NODE = sizeof(struct sNode);
- const size_t SIZE_T_PERSON = sizeof(struct sPerson);
- void error_alloc_person(struct sPerson **person, const char *msg)
- {
- free(*person);
- fprintf(stderr, "struct person* memory allocation error: %s\n", msg);
- *person = NULL;
- getchar();
- exit(EXIT_FAILURE);
- }
- void error_alloc_char(char **c, const char *msg)
- {
- free(*c);
- fprintf(stderr, "char* memory allocation error: %s\n", msg);
- *c = NULL;
- getchar();
- exit(EXIT_FAILURE);
- }
- void error_alloc_node(struct sNode **node, const char *msg)
- {
- free(*node);
- fprintf(stderr, "struct node* memory allocation error: %s", msg);
- *node = NULL;
- getchar();
- exit(EXIT_FAILURE);
- }
- /*
- Zwraca ilość pamięci zajmowaną przez pola w strukturze osoba
- */
- size_t person_mem_size(struct sPerson *person)
- {
- // ilosc * wielkosc typu
- // char* zajmuje de facto o jeden więcej bajt - dla znaku końca stringu czyli NULL -> '\0'
- // ponieważ mamy 2 stringi mamy dwa ekstra znaki '\0' do dodania stąd: (2 * SIZE_T_CHAR)
- return ((strlen(person->name) * SIZE_T_CHAR) + (strlen(person->surname) * SIZE_T_CHAR) + SIZE_T_UINT + (2 * SIZE_T_CHAR));
- }
- struct sPerson *alloc_person(char *imie, char *nazwisko, unsigned int wiek)
- {
- size_t name_real_size, surname_real_size;
- struct sPerson *new_person = (struct sPerson *)malloc(SIZE_T_PERSON);
- if (new_person == NULL)
- error_alloc_person(&new_person, "new_person, alloc_person()");
- if (imie == NULL)
- new_person->name = NULL;
- else
- {
- name_real_size = ((SIZE_T_CHAR * strlen(imie)) + SIZE_T_CHAR);
- new_person->name = (char *)malloc(name_real_size);
- if (!new_person->name)
- error_alloc_char(&new_person->name, "name, alloc_person()");
- memset(new_person->name, 0, name_real_size);
- memcpy(new_person->name, imie, name_real_size - SIZE_T_CHAR);
- }
- if (nazwisko == NULL)
- new_person->surname = NULL;
- else
- {
- surname_real_size = ((SIZE_T_CHAR * strlen(nazwisko)) + SIZE_T_CHAR);
- new_person->surname = (char *)malloc(surname_real_size);
- if (!new_person->surname)
- error_alloc_char(&new_person->surname, "surname, alloc_person()");
- memset(new_person->surname, 0, surname_real_size);
- memcpy(new_person->surname, nazwisko, surname_real_size - SIZE_T_CHAR);
- }
- new_person->age = wiek;
- return new_person;
- }
- void cpy_person(struct sPerson **dest, const struct sPerson *source)
- {
- *dest = alloc_person(source->name, source->surname, source->age);
- }
- bool person_cmp(const struct sPerson *person1, const struct sPerson *person2)
- {
- return ((strcmp(person1->name, person2->name) == 0) && (strcmp(person1->surname, person2->surname) == 0) && (person1->age == person2->age));
- }
- void free_person(struct sPerson *person)
- {
- free(person->name);
- person->name = NULL;
- free(person->surname);
- person->surname = NULL;
- person = NULL;
- }
- void free_node(struct sNode *node)
- {
- free_person(node->person);
- free(node);
- node = NULL;
- }
- long long milliseconds_now()
- {
- static LARGE_INTEGER s_frequency;
- BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency);
- if (s_use_qpc)
- {
- LARGE_INTEGER now;
- QueryPerformanceCounter(&now);
- return (1000LL * now.QuadPart) / s_frequency.QuadPart;
- }
- else
- {
- return GetTickCount();
- }
- }
- /*
- Dodaje osobę na początek listy jednokierunkowej
- Bez sortowania
- */
- void push_front(struct sNode **head, struct sPerson *person)
- {
- // Jeśli początek jest null to glowa = nowy element
- if (*head == NULL)
- {
- *head = (struct sNode *)malloc(SIZE_T_NODE);
- if (!*head) error_alloc_node(head, "head, insert_front()");
- (*head)->person = person;
- (*head)->next = NULL;
- }
- else
- {
- struct sNode *nowy = (struct sNode *)malloc(SIZE_T_NODE);
- if (!nowy) error_alloc_node(&nowy, "nowy, insert_front()");
- nowy->person = person;
- nowy->next = *head;
- *head = nowy;
- }
- }
- /*
- Dodaje osobę na koniec listy jednokierunkowej
- Bez sortowania
- */
- void push_back(struct sNode **head, struct sPerson *person)
- {
- // Jeśli początek jest null to glowa = nowy element
- if (*head == NULL)
- {
- *head = (struct sNode *)malloc(SIZE_T_NODE);
- if (!*head) error_alloc_node(head, "nowy, insert_back()");
- (*head)->person = person;
- (*head)->next = NULL;
- }
- else
- {
- struct sNode *node = *head;
- for (; node->next != NULL; node = node->next);
- node->next = (struct sNode *)malloc(SIZE_T_NODE);
- if (!node->next) error_alloc_node(&node->next, "node->next, insert_back()");
- node->next->next = NULL;
- node->next->person = person;
- }
- }
- // Zwalania pamięć zare. przez listę jednokierunkową
- void destroy(struct sNode **head)
- {
- struct sNode * tmp = NULL;
- for (; tmp != NULL;)
- {
- tmp = (*head)->next;
- // Zwlania węzeł
- free_node(*head);
- *head = tmp;
- }
- *head = NULL;
- }
- void list(struct sNode *head)
- {
- for (; head != NULL; head = head->next)
- printf("%s %s %d | %p -> %p\n", head->person->name, head->person->surname, head->person->age, head, head->next);
- }
- unsigned int size(struct sNode *head)
- {
- unsigned int size = 0;
- for (; head != NULL; head = head->next)
- ++size;
- return size;
- }
- void split(const int ile)
- {
- }
- /*
- Odwaraca listę. Ogon jest głową a głowa->next wskazuje na NULL`a
- */
- struct sNode *reverse(struct sNode **head)
- {
- struct sNode* new_head = NULL;
- while ((*head) != NULL)
- {
- struct sNode * next = (*head)->next;
- (*head)->next = new_head;
- new_head = *head;
- *head = next;
- }
- return new_head;
- }
- /*
- Łączy `n` ilość list. Zwraca nową listę w tym nowo przydzieloną pamięc dla każdej zmiennej dynamiczych w jej strukturze(sNode).
- Przykład 1 push_back() - opcja wolniejsza z racji działania funkcji push_back()
- Dodajemy do siebie 5 list używjąc wywołania push_back():
- NowaLista = join_multi(PUSH_BACK, 5, Lista1, Lista2, Lista3, Lista4, Lista5);
- Przykład 2 push_front - opcja najszybsza z racji działa funkcji push_front()
- Dodajemy do siebie 5 list używjąc wywołania push_front()
- NowaLista = join_multi(PUSH_FRONT, 5, Lista1, Lista2, Lista3, Lista4, Lista5 );
- */
- struct sNode *join_multi(const enum SinglyLinkedListPushMethod push_method, const int number_of_sll, ...)
- {
- struct sNode *new_ssl = NULL;
- va_list vl;
- int i;
- va_start(vl, number_of_sll);
- for (i = 0; i < number_of_sll; i++)
- {
- struct sNode *lista = va_arg(vl, struct sNode *);
- switch (push_method)
- {
- case PUSH_BACK:
- {
- for (; lista != NULL; lista = (lista)->next)
- push_back(&new_ssl, alloc_person((lista)->person->name, (lista)->person->surname, (lista)->person->age));
- }
- break;
- default:
- case PUSH_FRONT:
- {
- for (; lista != NULL; lista = (lista)->next)
- push_front(&new_ssl, alloc_person((lista)->person->name, (lista)->person->surname, (lista)->person->age));
- }
- break;
- }
- }
- va_end(vl);
- return new_ssl;
- }
- /*
- Tworzy NOWĄ listę jednokierunkową
- */
- struct sNode * join_two(struct sNode *ssl1, struct sNode *ssl2)
- {
- struct sNode *new_ssl = NULL;
- for (; ssl1 != NULL; ssl1 = ssl1->next)
- push_back(&new_ssl, alloc_person((ssl1)->person->name, (ssl1)->person->surname, (ssl1)->person->age));
- for (; ssl2 != NULL; ssl2 = ssl2->next)
- push_back(&new_ssl, alloc_person((ssl2)->person->name, (ssl2)->person->surname, (ssl2)->person->age));
- return new_ssl;
- }
- void remove_by_person(struct sNode **head, struct sPerson *person)
- {
- struct sNode* current = *head;
- struct sNode* previous = NULL;
- for (; current != NULL; current = current->next)
- {
- if (person_cmp(current->person, person) == true)
- {
- if (previous == NULL)
- {
- current = current->next;
- remove_head(head);
- }
- else
- {
- previous->next = current->next;
- free_node(current);
- current = previous->next;
- }
- }
- else
- previous = current;
- }
- }
- void remove_by_person_name(struct sNode **head, const char *name)
- {
- struct sNode* current = *head;
- struct sNode* previous = NULL;
- for (; current != NULL; current = current->next)
- {
- if (strcmp(current->person->name, name) == 0)
- {
- if (previous == NULL)
- {
- current = current->next;
- remove_head(head);
- }
- else
- {
- previous->next = current->next;
- free_node(current);
- current = previous;
- }
- }
- else
- previous = current;
- }
- }
- void remove_by_person_surname(struct sNode **head, const char *surname)
- {
- struct sNode* current = *head;
- struct sNode* previous = NULL;
- for (; current != NULL; current = current->next)
- {
- if (strcmp(current->person->surname, surname) == 0)
- {
- if (previous == NULL)
- {
- current = current->next;
- remove_head(head);
- }
- else
- {
- previous->next = current->next;
- free_node(current);
- current = previous;
- }
- }
- else
- previous = current;
- }
- }
- void remove_by_person_age(struct sNode **head, const unsigned short int min_age, const unsigned short int max_age)
- {
- if (max_age < min_age || min_age > max_age)
- return;
- struct sNode* current = *head;
- struct sNode* previous = NULL;
- for (; current != NULL; current = current->next)
- {
- if (current->person->age >= min_age && current->person->age <= max_age)
- {
- if (previous == NULL)
- {
- current = current->next;
- remove_head(head);
- }
- else
- {
- previous->next = current->next;
- free_node(current);
- current = previous;
- }
- }
- else
- previous = current;
- }
- }
- struct sNode * search_by_person(struct sNode *head, struct sPerson *person)
- {
- struct sNode *new_ssl = NULL;
- for (; head != NULL; head = head->next)
- {
- if (person_cmp(head->person, person) == true)
- push_front(&new_ssl, alloc_person(head->person->name, head->person->surname, head->person->age));
- }
- return new_ssl;
- }
- struct sNode * search_by_person_name(struct sNode *head, const char *name)
- {
- struct sNode *new_ssl = NULL;
- for (; head != NULL; head = head->next)
- {
- if (strcmp(head->person->name, name) == 0)
- push_front(&new_ssl, alloc_person(head->person->name, head->person->surname, head->person->age));
- }
- return new_ssl;
- }
- struct sNode * search_by_person_surname(struct sNode *head, const char *surname)
- {
- struct sNode *new_ssl = NULL;
- for (; head != NULL; head = head->next)
- {
- if (strcmp(head->person->surname, surname) == 0)
- push_front(&new_ssl, alloc_person(head->person->name, head->person->surname, head->person->age));
- }
- return new_ssl;
- }
- struct sNode * search_by_person_age(struct sNode *head, const unsigned short min_age, const unsigned short max_age)
- {
- if (max_age < min_age || min_age > max_age)
- return NULL;
- struct sNode *new_ssl = NULL;
- for (; head != NULL; head = head->next)
- {
- if (head->person->age >= min_age && head->person->age <= max_age)
- push_front(&new_ssl, alloc_person(head->person->name, head->person->surname, head->person->age));
- }
- return new_ssl;
- }
- struct sNode * diff(struct sNode *head1, struct sNode *head2)
- {
- struct sNode *new_ssl = NULL;
- if (head2 == NULL)
- return NULL;
- while (head1 != NULL)
- {
- if (!(person_cmp((head1)->person, head2->person)))
- push_front(&new_ssl, head2->person);
- else
- {
- while ((head2 != NULL) && (person_cmp(head2->person, (head1)->person) == false))
- {
- push_front(&new_ssl, head2->person);
- head2 = head2->next;
- }
- }
- head1 = head1->next;
- }
- return new_ssl;
- }
- void remove_by_persons_va_list(struct sNode **head, unsigned int number_of_persons, ...)
- {
- }
- struct sNode * filter_by_persons_names_va_list(struct sNode **head, unsigned int number_of_names, ...)
- {
- struct sNode *new_ssl = NULL;
- va_list vl;
- unsigned int i;
- va_start(vl, number_of_names);
- for (i = 0; i < number_of_names; i++)
- {
- char *name = va_arg(vl, char *);
- push_front(&new_ssl, alloc_person(name, NULL, 0));
- }
- va_end(vl);
- return NULL;
- }
- void remove_by_persons_surnames_va_list(struct sNode **head, unsigned int number_of_surnames, ...)
- {
- }
- void remove_by_persons_ages_va_list(struct sNode **head, unsigned int number_of_ages, ...)
- {
- bool only_one = false;
- if (number_of_ages == 0)
- return;
- if (number_of_ages == 1)
- only_one = true;
- }
- void sort_by_person_name()
- {
- }
- void sort_by_person_surname()
- {
- }
- void bubble_sort_by_person_age(struct sNode **head)
- {
- struct sNode *tmp = *head;
- struct sNode *next = NULL;
- struct sNode *prev = NULL;
- }
- void rotate(struct sNode **head)
- {
- struct sNode *nastepny = NULL;
- struct sNode *aktualny = NULL;
- aktualny = *head;
- // lista musi miec conajmniej dwa wezly
- if (aktualny == NULL || aktualny->next == NULL)
- exit(EXIT_FAILURE);
- while (aktualny->next != NULL)
- {
- nastepny = aktualny->next;
- aktualny = nastepny;
- aktualny->next = nastepny->next;
- (aktualny)->next = aktualny;
- aktualny = aktualny->next;
- }
- int z = 9;
- /*for (; glowa->next != NULL; glowa = glowa->next)
- {
- nastepny = glowa->next; //node1
- glowa->next = nastepny->next; //node2
- glowa = nastepny;
- }*/
- }
- void remove_tail(struct sNode **head)
- {
- struct sNode *one_before_last = *head;
- for (; one_before_last->next->next != NULL; one_before_last = one_before_last->next);
- struct sNode *last = one_before_last->next;
- one_before_last->next = NULL;
- free_person(last->person);
- free(last);
- last = NULL;
- }
- void remove_head(struct sNode **head)
- {
- // copy addr of second in list
- struct sNode *tmp = (*head)->next;
- free_person((*head)->person);
- free(*head);
- *head = tmp;
- }
- size_t list_mem_size(struct sNode *head)
- {
- size_t sum = 0;
- struct sNode *current = head;
- int count_nodes = 0;
- while (current != NULL)
- {
- // zwraca ilosc pamięci zarezw. przez samego Node: czyli wielkosc wskaźnika next* + wielkosc wskaźnika person*
- sum += sizeof(current);
- // zwraca ilosc pamieci zarez. przez osobe
- sum += person_mem_size(current->person);
- // Node sam z siebie też jest wskaźnikiem - musimy sumować ich całkowitą liczbę i dodać przy return
- count_nodes++;
- current = current->next;
- }
- return (sum + (count_nodes * SIZE_T_NODE));
- }
- unsigned int load_from_csv(const char *filename, struct sNode **head)
- {
- unsigned int size = 0;
- FILE *fh = NULL;
- char buffer[BUFSIZ];
- errno_t err = fopen_s(&fh, filename, "r");
- if (err == 0)
- {
- while (fgets(buffer, sizeof(buffer), fh))
- {
- char *next = NULL;
- char *imie = strtok_s(buffer, "|", &next);
- char *nazwisko = strtok_s(NULL, "|", &next);
- char *tmp_age = strtok_s(NULL, "|", &next);
- unsigned int age = (unsigned int)strtoul(tmp_age, NULL, 0);
- push_back(head, alloc_person(imie, nazwisko, age));
- ++size;
- }
- }
- else
- {
- }
- fclose(fh);
- return size;
- }
- int main(void)
- {
- struct sNode *List1 = NULL;
- unsigned int size = 0;
- long long start;
- int i;
- start = milliseconds_now();
- size = load_from_csv("D:\\db.txt", &List1);
- rotate(&List1);
- printf("[Load] Time taken: %lld [ms], Size = %i;\n", (milliseconds_now() - start), size);
- list(List1);
- printf("po\n");
- list(List1);
- start = milliseconds_now();
- destroy(&List1);
- printf("[Destroy] Time taken: %lld [ms], Size = %i\n", (milliseconds_now() - start), size);
- getchar();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement