Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions MyList.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "MyList.h"
#define SIZE 10 // максимальный размер двоичного числа


// Функция для инициализации списка
void initList(DoublyLinkedList* list) {
list->head = NULL;
list->tail = NULL;
list->size = 0;
}


// Функция выделения памяти под новый узел
Node* createNode(int value) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL) {
printf("Memory allocation error!\n");
exit(1); // аварийное завершение
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не пойму что значит 1. Введи типы ошибок и их условные обозначения.

Enum {
E_MEMORY_1
E_SOMETHING_2
E_SOMETHING_3
}

Что-то на подобие этого и обрабатывай разные виды ошибок. Как минимум с сложном коде по названию будет понятно что за тип ошибки, если не до конца ясно логике в коде

}
newNode->data = value;
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}

// Функция добавления элемента в конец списка
void append(DoublyLinkedList* list, int value) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А если передать указатель, который null ?

Node* newElement = createNode(value);
if (list -> head == NULL){ // если список пустой
newElement -> prev = NULL;
list -> head = newElement;
}
else { // уже не пустой
newElement -> prev = list -> tail; // связь текущего с предыдущим
list -> tail -> next = newElement; // связь предыдущего с текущим
}
list -> tail = newElement; // переопределение конца(указателя) на новый элемент
++(list -> size); // увеличение списка
}

// Функция освобождения памяти
void freeList(DoublyLinkedList* list) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

также с null

Node* current = list->head;
while (current != NULL) {
Node* temp = current;
current = current->next; // освобождаем память, запоминая указатель на следующий элемент
free(temp);
}
list->head = NULL; // уничтожаем указатели непосредственно списка
list->tail = NULL;
list->size = 0;
}

// Функция вывода списка от начала к концу
void printForward(const DoublyLinkedList* list){
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Также с null

Node* current = list -> head;
printf("Dec list: ");
while(current != NULL){
printf("%d ", current -> data);
current = current -> next;
}
printf("\n");
}

// Функция вывода списка от конца к началу
void printBackward(const DoublyLinkedList* list){
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Также с null

Node* current = list -> tail;
printf("Dec list: ");
while(current != NULL){
printf("%d ", current -> data);
current = current -> prev;
}
printf("\n");
}

void generateRandomList(DoublyLinkedList* list, int count){
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Также с null

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

У тебя foo(...) { или foo(...){ . Приведи в порядок

// Инициализация генератора случайных чисел
srand(time(NULL));
for (int i = 0; i < count; ++i){
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

такая же проблема с codestyle

append(list, rand() % 100);
}
}

// Функция для вывода списка в двоичном виде
void printBinaryValue(const DoublyLinkedList* list) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Также с null

printf("Binary list: ");
Node* current = list -> head;
int numberDec;
int count = -1;
while(current != NULL){
numberDec = current -> data;
int* numberBin = (int*)calloc(SIZE, sizeof(int));
if (numberBin == NULL){
printf("Memory allocation error!\n");
exit(1);
}
//printf("%d ", numberDex);
numberBin[++count] = numberDec % 2;
while (numberDec != 0){
numberDec /= 2;
numberBin[++count] = numberDec % 2; // добываем 0 и 1 из числа
}


// разворачиваем двоичное число
for (int i = 0; i < count / 2; ++i){
int bubble = numberBin[i];
numberBin[i] = numberBin[count - 1 - i]; // обмен крайних элементов, двигаемся к середине
numberBin[count - 1 - i] = bubble;
}
// вывод в консоль
for (int i = 0;i < count; ++i){
printf("%d",numberBin[i]);
}
printf(" "); // пробел между двоичными числами
free(numberBin); // освобождаем память
numberBin = NULL;
numberDec = 0;
count = -1;
current = current -> next;
}
printf("\n");
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

потерял \n

49 changes: 49 additions & 0 deletions MyList.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef MYLIST_H
#define MYLIST_H

/* Концепция двухсвязного спиcка

NULL <- [prev0 data0 next0] <-> [prev1 data1 next1] <-> [prev2 data2 next2] -> NULL

Node0(head) Node1 Node2(tail)


next0 = &Node1
next1 = &Node2
next2 = NULL

prev0 = NULL
prev1 = &Node0
prev2 = &Node1

*/

// Cтруктура узла двухсвязного списка (один элемент списка)
typedef struct Node {
int data;
struct Node* prev; // указатель на прерыдущий элемент
struct Node* next; // указатель на следующий элемент
} Node;

// Структура самого списка
typedef struct {
Node* head; // указатель на первый элемент
Node* tail; // указатель на последний элемент
int size; // счетчик элементов списка
} DoublyLinkedList;


void initList(DoublyLinkedList* list);
Node* createNode(int value);
void append(DoublyLinkedList* list, int value);
void freeList(DoublyLinkedList* list);

void printForward(const DoublyLinkedList* list);
void printBackward(const DoublyLinkedList* list);

void generateRandomList(DoublyLinkedList* list, int count);

void printBinaryValue(const DoublyLinkedList* list);


#endif // MYLIST_H
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

потерял \n

106 changes: 106 additions & 0 deletions MyThreads.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#include <pthread.h>
#include <stdio.h>
#include "MyThreads.h"

// Функция для посчета нулевых битов в числе
int countZeroBits(int numberDec){
int count = 0;
while(numberDec != 0){
if (numberDec % 2 == 0){
++count;
}
numberDec /= 2;
}
return count;
}

// Функция для подсчета единичных битов в числе
int countOneBits(int numberDec){
int count = 0;
while(numberDec != 0){
if (numberDec % 2 == 1){
++count;
}
numberDec /= 2;
}
return count;
}
// Функция инициализации и запуска потоков
void threadStart(ThreadArgs* args1, ThreadArgs* args2){
// Создание потоков
pthread_t thread1;
pthread_t thread2;

if (pthread_create(&thread1, NULL, threadExecution, args1) != 0) {
printf("Failed to create thread 1");
exit(1); // аварийное завершение
}
if (pthread_create(&thread2, NULL, threadExecution, args2) != 0) {
printf("Failed to create thread 2");
exit(1); // аварийное завершение
}
/* разбор функции pthread_create
&thread1 - Указатель на переменную типа pthread_t, в которую будет записан идентификатор созданного потока
NULL - Указатель на атрибуты потока (используем атрибуты по умолчанию)
threadExecution - Функция обработки данных в потоке
&args1 - Указатель на аргументы, которые будут переданы в функцию threadExecution
*/

// Ожидание завершения потоков
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
}

// функция выполнения обработки данных в потоке
void* threadExecution(void* args) {
ThreadArgs* targs = (ThreadArgs*)args; // преобразуем принятые аргументы в структуру

Node* currentNode = NULL; // объявляем текущий узел
Node* nextNode = NULL; // и следующий

currentNode = targs -> flag ? targs -> head : targs -> tail;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Пиши доступ к указателю без пробелов targs->flag. Все codestyle я не знаю, но нигде не видел, чтобы так рекомендовали писать


while (1) {

// блокируем список на время чтения узла
pthread_mutex_lock(targs -> listMutex);

// разблокировка, если конец списка
if (currentNode == NULL) {
pthread_mutex_unlock(targs -> listMutex);
break;
}

// Сохраняем данные и следующий узел локально
int data = currentNode -> data;
nextNode = targs -> flag ? currentNode -> next : currentNode -> prev;

// теперь разблокируем список (чтение завершено)
pthread_mutex_unlock(targs -> listMutex);

// Обработка данных
if (targs -> flag) {
targs -> countZero += countZeroBits(data);
} else {
targs -> countOne += countOneBits(data);
}
++(targs -> countNodes);
currentNode = nextNode;
}
targs = NULL;
return NULL;
}

// функция для вывода результата в консоль
void threadPrint(ThreadArgs* args1, ThreadArgs* args2){
printf("\n");
printf("Thread 1:\n");
printf("Zero bits: %d\n", args1 -> countZero);
printf("Count nodes: %d\n", args1 -> countNodes);
printf("\n");
printf("Thread 2:\n");
printf("One bits: %d\n", args2 -> countOne);
printf("Count nodes: %d\n", args2 -> countNodes);
}


22 changes: 22 additions & 0 deletions MyThreads.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef MYTHREADS_H
#define MYTHREADS_H
#include "MyList.h"

// Структура аргументов для работы с потоком
typedef struct {
Node* head; // Указатель на голову списка
Node* tail; // Указатель на хвост списка
int countZero; // Счетчик нулевых битов (для потока 1)
int countOne; // Счетчик единичных битов (для потока 2)
int countNodes; // Счетчик обработанных элементов
int flag; // Флаг направления обхода (1 - от головы, 0 - от хвоста)
pthread_mutex_t* listMutex; // Мьютекс для синхронизации доступа к списку
} ThreadArgs;

int countZeroBits(int numberDec);
int countOneBits(int numberDec);
void threadStart(ThreadArgs* args1, ThreadArgs* args2);
void* threadExecution(void* args);
void threadPrint(ThreadArgs* args1, ThreadArgs* args2);

#endif //MYTHREADS_H
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

потерял \n

16 changes: 16 additions & 0 deletions delay.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "delay.h"

#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

// функция для задержки консоли в Linux или Windows
void delay_ms(int milliseconds) {
#ifdef _WIN32
Sleep(milliseconds);
#else
usleep(milliseconds * 1000);
#endif
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

потерял \n

7 changes: 7 additions & 0 deletions delay.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef DELAY_H
#define DELAY_H


void delay_ms(int milliseconds);

#endif // DELAY_H
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

потерял \n

49 changes: 49 additions & 0 deletions main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include <stdio.h>
#include <pthread.h>
#include "MyList.h"
#include "delay.h"
#include "MyThreads.h"


int main() {
// Подготовка данных
int sizeList = 0;
printf("Enter a number of type int: ");
scanf("%d", &sizeList);
printf("\n");
DoublyLinkedList MyList;
initList(&MyList);
generateRandomList(&MyList, sizeList);

// Смотрим на подготовленные данные
printForward(&MyList); // десятичный вид
printBinaryValue(&MyList); // двоичный вид

// Многопоточность

// Инициализация мьютекса
pthread_mutex_t listMutex = PTHREAD_MUTEX_INITIALIZER;
/*
Мьютексы нужны для защиты от одновременного
доступа сразу нескольких потоков к одному
обЪекту. Их необходимо использовать, если
предполагается, что список будет не просто
считываться, а изменяться в разных потоках.

*/

// Подготовка аргументов для потоков (инициализация структур)
ThreadArgs args1 = {MyList.head, MyList.tail, 0, 0, 0, 1, &listMutex}; // Поток 1 (от головы)
ThreadArgs args2 = {MyList.head, MyList.tail, 0, 0, 0, 0, &listMutex}; // Поток 2 (от хвоста)

// Запуск многопоточной обработки
threadStart(&args1, &args2);

// Вывод результатов
threadPrint(&args1, &args2);

delay_ms(5000); // задержка отображения в консоли (Linux|Windows)
pthread_mutex_destroy(&listMutex); // Уничтожение мьютекса
freeList(&MyList); // освобождение памяти
return 0;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

потерял \n

Loading