четвртак, 25 априла, 2024
Како да...?

Увод у програмски језик C (7. део)

Аутор: Стефан Ножинић

Структуре

Структура у програмском језику C означава комплексан тип података који у себи садржи блок од неколико примитивних типова података као што су integer и char. Овде је потребно напоменути да структура може садржати и показиваче, што ће нам касније бити корисно када будемо видели конкретну примену структура. Овакви типови се дефинишу кључном речи struct на следећи начин:

struct A // A je naziv strukture
{
	int a; 
	bool b; 
	char c; 
}

Овде смо дефинисали структуру под називом A, која се састоји од три примитивне променљиве: целобројна променљива (integer), променљива која одређује логичко стање (boolean) и променљива која може садржати један карактер (char).

Овим примитивним променљивама приступамо на следећи начин:

A.a = 1; 
A.b = true;
A.c = 'h';

Као што можемо видети, овде се ради о додели вредности. Потребно је напоменути да не морају све променљиве дате структуре да имају додељене вредности.

Следи конкретан пример употребе структуре која представља комплексан број. Овакви бројеви имају два дела: реални и имагинарни део. У нашем примеру ћемо за оба дела користити double тип података, како бисмо могли представити бројеве који нису цели.

#include <stdio.h>

struct Complex 
{
	double real; 
	double imaginary;
}

void main(void) 
{
	struct Complex c;
	c.real = 2.0;
	c.imaginary = 1.41;
	// ... ispis vrednosti ide ovde 
}

Примећујете да приликом дефинисања нове променљиве типа наше структуре морамо користити struct Complex а не само Complex. Ово је могуће превазићи употребом typedef наредбе на следећи начин:

typedef struct Complex 
{
	double real; 
	double imaginary;
} Complex;

Сада је могуће дефинисати нашу променљиву која нам представља комплексан број на следећи начин:

Complex c; 

Листе

Листа је једна конкретна примена структура. Листа је структура података која се разликује од низа тиме што је динамичка. То значи да се њена величина може мењати током извршавања програма док смо код низова имали случај да приликом дефиниције низа морамо одредити тачну његову дужину и не можемо је после мењати. Листа овај проблем превазилази на следећи начин – сваки елемент листе је структура са две променљиве: једна променљива је вредност датог елемента, а друга променљива је показивач на следећи елемент. Ово омогућава да елементи листе буду разбацани по меморији а не једни до других, што нам омогућава динамичност. Када желимо да додамо нови елемент или да обришемо постојећи, довољно је само да га уклонимо из меморије и да показиваче његовог претходника поставимо да показују на његовог следбеника. Овакве листе се зову једноструко повезане листе, јер се са једног елемента може ићи само на следећи елемент и не може се ићи на претходни.

Следи пример дефиниције структуре која представља елемент листе:

typedef struct Element 
{
	int value; 
	struct Element* next; 
} Element;

По дефиницији, видимо да структура Element има две променљиве, једна је типа integer која представља вредност елемента (могу бити и други типови података, прим. аут.), а друга представља показивач на структуру Element који је заправо показивач на следећи елемент.

Следеће што нам је потребно, јесте функција за убацивање новог елемента у листу и функција за брисање.

Element* insert(Element* e, int a) 
{
	Element* new = (Element*) malloc(sizeof(Element));
	Element* next = e->next;
	e.next = new; 
	new->next = next;
	new->value = a;
	return new;
}

void delete(Element* e) 
{
	if (e.next != NULL) {
		Element* next = e->next; 
		Element* nextnext = next->next;
		e->next = nextnext; 
		free(next);
	}
}

Функција insert узима две вредности као аргументе, прва је елемент после ког ће бити убачен нови елемент, а друга је вредност за нови елемент. Овде је потребно обратити пажњу на оператор који се користи уместо тачке, ако се приступа елементима структуре на коју показивач показује. Ова функција враћа показивач на новоубачени елемент.

Функција за брисање прво „размешта” показиваче, а потом користи free позив како би ослободила меморију од обрисаног елемента.

Предност овакве структуре смо већ споменули – динамичност. Мана овакве структуре је та да приступ елементима траје много дуже него што је случај код низова, јер морамо да се „прошетамо” кроз све претходнике датог елемента док не дођемо до њега, јер немамо његову адресу унапред у меморији, као што је то био случај са низовима.

У следећем броју ћемо писати о још неким структурама и показати њихове примене.

Наредни део овог серијала можете прочитати овде.

Претходни део овог серијала можете прочитати овде.