You are on page 1of 19

Структуре

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

int ocene[5] = {1, 2, 3, 4, 5};

char ime[20] = "Velimir Radlovacki";

double matrica[3][3] = {{1.0, 1.1, 1.2},

{2.1, 1.5, 3.3},

{8.5, 1.5, 1.7}};

Међутим, у пракси нам је често потребно да направимо колекције података различитих типова.


На пример, за евиденцију ученика у одељењу потребна нам је следећа колекција података: редни
број ученика, презиме и име ученика и просек.

int redbr;

char prezime[20];

char ime[20];

float prosek;

Овакву колекцију података није могуће сачувати у низу, јер је низ колекција података истог типа.
Јасно је да је неопходно креирати сложени тип података који може чувати елементе различитих
типова.

Структура је сложени тип података која се састоји од одређеног броја елемената који могу бити
различитих типова. У другим програмским језицима уместо назива “структура” могу се наћи и
називи “запис” или “слог”. Елементи структурe називају се чланови структуре и обележавају се
идентификаторима. Чланови структуре могу бити било којег основног или сложеног типа
података, што значи да чланови структуре могу бити и друге структуре, низови, стрингови.

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

struct ime-strukture { lista-deklaracija } ;

Кључна реч struct је настала као скраћено име за структурирани тип података. ime-strukture је


идентификатор за идентификацију структуре која се дефинише. Име структуре нема статус
идентификатора типа података, па ако постоје позивања на ову структуру, увек мора да се
наведе struct ime-strukture – само навођење имена структуре није довољно. lista-
deklaracija представља набрајања чланова структуре, где свака декларација има општи облик за
дефинисање података којег смо и до сада користили. На пример,

struct ucenik {

int redbr;
 char prezime[20];

char ime[20];

float prosek;

};

Структуре се обично дефинишу на почетку програма, пре функције main() и осталих функција, како
би се могле у њима користити.

Како је свака структура посебан тип података, то значи да се могу декларисати и иницијализовати
променљиве типа структуре. На пример, следећим кодом:

struct ucenik u1;

декларисали смо нову променљиву u1 типа структуре ucenik, или:

struct ucenik u2 = {2, "Jovanovic", "Petar", 4.67};

декларисали смо и иницијализовали нову променљиву u2 типа структуре ucenik.

Променљиве типа структуре могуће је декларисати и одмах након декларације структуре. У


следећем примеру:

struct ucenik {

int redbr;

 char prezime[20];

char ime[20];

float prosek;

}u3;

декларисали смо структуру ucenik и променљиву u3 типа структуре ucenik.

Појединачним члановима структуре приступа се коришћењем оператора тачка на следећи начин:


ime-promenljive.ime-člana. Када приступимо једном члану структуре, онда можемо прочитати,
доделити или променити његову вредност. На пример:

u4.redbr = 15;

u4.prezime = "Petrovic";

gets(u4.ime);

scanf("%f", &u4.prosek);
printf("%d %s %s %f", u4.redbr, u4.prezime, u4.ime, u4.prosek);

Постоји још један начин иницијализације чланова структуре, такозваним означеним


иницијализаторима (designated initializers) који је користан када желимо да иницијализујемо само
одређени број чланова структуре.

struct ucenik u5 = {.redbr = 5, .prosek = 3.67};

У примеру изнад иницијализовали смо само два члана структуре.

ЗАДАТАК 1. Напишите програм у програмском језику C за евиденцију података о 3 ученика


користећи структуру ucenik чији су чланови int redbr, char prezime[20], char ime[20] и float prosek.
Подаци о ученицима требају бити унети у самом кôду програма приликом иницијализације.

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

struct ucenik {

int redbr;

char prezime[20];

char ime[20];

float prosek;

};

int main(void) {

struct ucenik u1 = { 4, "Milanovic", "Ana", 4.50 };

struct ucenik u2 = { 9, "Jovanovic", "Petar", 4.67 };

struct ucenik u3 = { 23, "Petrovic", "Jovan", 4.00 };

printf("%d %s %s %.2f\n", u1.redbr, u1.prezime, u1.ime, u1.prosek);

printf("%d %s %s %.2f\n", u2.redbr, u2.prezime, u2.ime, u2.prosek);

printf("%d %s %s %.2f", u3.redbr, u3.prezime, u3.ime, u3.prosek);


return 0;

ЗАДАТАК 2. Преправите претходни задатак тако да се подаци о ученицима уносе са стандардног


улаза (тастатуре).

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

struct ucenik {

int redbr;

char prezime[20];

char ime[20];

float prosek;

};

int main(void) {

struct ucenik u1, u2, u3;

printf("Unesi red.br. 1. ucenika: ");

scanf("%d", &u1.redbr);

printf("Unesi prezime 1. ucenika: ");

scanf("%s", &u1.prezime);

printf("Unesi ime 1. ucenika: ");

scanf("%s", &u1.ime);

printf("Unesi prosek 1. ucenika: ");

scanf("%f", &u1.prosek);

printf("Unesi red.br. 2. ucenika: ");

scanf("%d", &u2.redbr);
printf("Unesi prezime 2. ucenika: ");

scanf("%s", &u2.prezime);

printf("Unesi ime 2. ucenika: ");

scanf("%s", &u2.ime);

printf("Unesi prosek 2. ucenika: ");

scanf("%f", &u2.prosek);

printf("Unesi red.br. 3. ucenika: ");

scanf("%d", &u3.redbr);

printf("Unesi prezime 3. ucenika: ");

scanf("%s", &u3.prezime);

printf("Unesi ime 3. ucenika: ");

scanf("%s", &u3.ime);

printf("Unesi prosek 3. ucenika: ");

scanf("%f", &u3.prosek);

printf("%d %s %s %.2f\n", u1.redbr, u1.prezime, u1.ime, u1.prosek);

printf("%d %s %s %.2f\n", u2.redbr, u2.prezime, u2.ime, u2.prosek);

printf("%d %s %s %.2f", u3.redbr, u3.prezime, u3.ime, u3.prosek);

return 0;

Можете приметити да је кôд програма за евиденцију података за само 3 ученика прилично


дугачак, да се и приликом уноса и приликом исписа података одређене ствари понављају, као и да
би било елегантније да се овај задатак реши помоћу низа чији су елементи структуре.

Низ структура

У случајевима када нам је потребно више променљивих типа одређене структуре, није практично
да их декларишемо појединачно, што се види из претходног примера. Функционалније решење је
да декларишемо низ кога чине елементи који су типа структуре.
Низ структура декларишемо исто као и било који други низ. На пример, ако је декларисана
структура ucenik:

struct ucenik {

int redbr;

 char prezime[20];

char ime[20];

float prosek;

};

а ми желимо да декларишемо низ од 30 елемената типа структуре ucenik, то би урадили на


следећи начин:

struct ucenik ucenici[30];

или би низ декларисали одмах након декларације структуре:

struct ucenik {

int redbr;

char prezime[20];

char ime[20];

float prosek;

}ucenici[30];

Као и код низова које смо до сада користили, сваки елемент у низу има тачно одређену позицију
на основу које му се додељује јединствени индекс. Вредност индекса првог елемента је 0,
другог 1, трећег 2 итд. што значи да је индекс низа типа int.

ЗАДАТАК 3. Преправите ЗАДАТАК 2. тако да се подаци о ученицима уносе са стандардног улаза и


чувају у низу чији су елементи типа структуре.

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

struct ucenik {

int redbr;

char prezime[20];
char ime[20];

float prosek;

}ucenici[3];

int main(void) {

int i;

for (i = 0; i < 3; i++) {

printf("Unesi red.br. %d. ucenika: ", i + 1);

scanf("%d", &ucenici[i].redbr);

printf("Unesi prezime %d. ucenika: ", i + 1);

scanf("%s", &ucenici[i].prezime);

printf("Unesi ime %d. ucenika: ", i + 1);

scanf("%s", &ucenici[i].ime);

printf("Unesi prosek %d. ucenika: ", i + 1);

scanf("%f", &ucenici[i].prosek);

for (i = 0; i < 3; i++) {

printf("%d %s %s %.2f\n", ucenici[i].redbr, ucenici[i].prezime,

ucenici[i].ime, ucenici[i].prosek);

return 0;

Задатак је сада много елегантније решен, а кôд програма можемо лако преправити за евиденцију
података о било ком броју ученика променом броја елемената низа.

Дефиниција типа података структуре


Структуре се често користе заједно са ознаком за дефиницију типа typedef што значи да се уводи
нови тип података структуре.

typedef struct ime-strukture { lista-deklaracija } ime-tipa;

Идентификатор ime-tipa може касније да се користи као идентификатор типа без навођења


службене речи struct. Идентификатор за идентификацију структуре ime-strukture којег смо
користили приликом декларације структуре се обично изоставља.

У следећем примеру:

typedef struct {

int redbr;

 char prezime[20];

char ime[20];

float prosek;

}ucenik;

...

ucenik u1, u2;

увели смо нови тип података структуре ucenik и дефинисали две променљиве тог типа u1 и u2.

ЗАДАТАК 4. Како би јасно видели разлику између коришћења структуре и коришћења типа
података структуре, напишите програм у којем је дефинисана структура ucenik и тип података
структуре nastavnik, па су потом додељене исписане вредности за једног ученика и једног
наставника.

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <string.h>

struct ucenik {

int redbr;

char prezime[20];

char ime[20];

};
typedef struct {

char prezime[20];

char ime[20];

char predmet[80];

}nastavnik;

int main(void) {

struct ucenik u1;

nastavnik n1;

u1.redbr = 1;

strcpy(u1.prezime, "Peric");

strcpy(u1.ime, "Pera");

puts("Ucenik:");

printf("Redni broj: %d\n", u1.redbr);

printf("Prezime: %s\n", u1.prezime);

printf("Ime: %s\n\n", u1.ime);

strcpy(n1.prezime, "Radlovacki");

strcpy(n1.ime, "Velimir");

strcpy(n1.predmet, "Programiranje");

puts("Nastavnik:");

printf("Prezime: %s\n", n1.prezime);

printf("Ime: %s\n", n1.ime);

printf("Ime: %s\n", n1.predmet);

return 0;

 
Угнежђене структуре

Структура може бити члан структуре (структура у структури, угнежђена структура). Члановима
угнежђене структуре приступамо користећи операторе тачка, наводећи прво променљиве типа
спољашње, па променљиве типа унутрашње (угнежђене) структуре, па име члана.

ЗАДАТАК 5. Напишите програм у коме је дефинисана структура kontakt унутар структуре ucenik.


Доделите вредности члановима структуре, па их потом испишите на стандардни излаз.

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

#include<string.h>

struct kontakt {

char ulicaiBroj[80];

char mesto[30];

int pttBroj;

char telefon[20];

};

struct ucenik {

int redbr;

char prezime[20];

char ime[20];

struct kontakt k1;

};

int main(void) {

struct ucenik u1 = { 7, "Peric", "Pera", "Vrsacka 1", "Vrsac", 26300,

"+381 63 834 5678" };

printf("Redni broj: %d\n", u1.redbr);

printf("Prezime i ime: %s %s\n", u1.prezime, u1.ime);

printf("Ulica i broj: %s\n", u1.k1.ulicaiBroj);


printf("Mesto i PTT: %s %d\n", u1.k1.mesto, u1.k1.pttBroj);

printf("Telefon: %s\n", u1.k1.telefon);

return 0;

Структуре и функције

Структуре се могу прослеђивати као аргументи функцијa и такође, структура може бити вредност


коју враћа функција!

ЗАДАТАК 6. Напишите програм у коме је дефинисан тип структуре ucenik и две функције – прва
функција kreirajUcenika као аргументе узима појединачне вредности чланова структуре и враћа
вредност типа структуре, а друга stampajUcenika као параметар добија структуру и исписује
вредности свих њених чланова (не враћа ништа).

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

#include<string.h>

typedef struct {

int redbr;

char prezime[20];

char ime[20];

}ucenik;

ucenik kreirajUcenika(int redbr, char prezime[20], char ime[20]) {

ucenik u;

u.redbr = redbr;

strcpy(u.prezime, prezime);

strcpy(u.ime, ime);

return u;

}
void stampajUcenika(ucenik u) {

printf("Redni broj: %d\n", u.redbr);

printf("Prezime: %s\n", u.prezime);

printf("Ime: %s\n", u.ime);

};

int main(void) {

ucenik u1, u2;

u1.redbr = 12;

strcpy(u1.prezime, "Peric");

strcpy(u1.ime, "Pera");

puts("Ucenik 1:");

stampajUcenika(u1);

u2 = kreirajUcenika(13, "Anic", "Ana");

puts("Ucenik 2:");

stampajUcenika(u2);

return 0;

Показивачи на структуре

Показиваче на структуре дефинишемо као и показиваче на податке било ког другог типа. На
пример, ако имамо дефинисан тип података структуре ucenik, можемо дефинисати
показивач pUcenik на тип структуре ucenik:

typedef struct {

int redbr;

 char prezime[20];
char ime[20];

}ucenik;

...

ucenik *pUcenik;

Показивачу на структуру можемо доделити адресу променљиве типа структуре. На пример:

typedef struct {

int redbr;

 char prezime[20];

char ime[20];

}ucenik;

...

ucenik *pUcenik, u1;

pUcenik = &u1;

Члановима у структури можемо приступити помоћу показивача коришћењем оператора ->. На


пример:

typedef struct {

int redbr;

 char prezime[20];

char ime[20];

}ucenik;

...

ucenik *pUcenik, u1;

u1.redbr = 15;

strcpy(u1.ime, "Pera");

strcpy(u1.prezime, "Peric");

pUcenik = &u1;

printf("%s %s %d", pUcenik->redbr, pUcenik->prezime, pUcenik->ime);

Уместо коришћења оператора -> као што је приказано у претходном примеру:

pUcenik->ime
члановима структуре можемо приступити и на следећи начин:

(*pUcenik).ime

са напоменом да су заграде обавезне због приоритета оператора, као и да се овај начин ређе
користи.

Показивачи на низ структура

Већ смо у претходним примерима дефинисали низ структура и додељивали вредности његовим
елементима, на пример:

typedef struct {

int redbr;

 char prezime[20];

char ime[20];

}ucenik;

...

ucenik ucenici[30];

ucenici[0].redbr = 1;

strcpy(ucenici[0].prezime, "Aleksic");

strcpy(ucenici[0].ime, "Aleksa");

Елементима низа структура можемо доделити вредности и помоћу показивача. На пример,


доделимо вредности следећем елементу претходно дефинисаног низа:

(ucenici+1)->redbr = 2;

strcpy((ucenici+1)->prezime, "Boric");

strcpy((ucenici+1)->ime, "Bora");

 1. Комплексни број представља се у облику структуре која садржи реални и имагинарни део
комплексног броја. Пројектовати програмски модул за рад са комплексним бројевима који садржи
следеће функције:
– састављање комплексног броја од реалног и имагинарног дела
– израчунавање збира, разлике, производа и количника два комплексна броја
– читање комплексног броја преко главног улаза рачунара
– писање комплексног броја на главни излаз рачунара
Написати главни програм за приказивање могућности горњег модула.
Решење:
/* kompleks.c */
#include<math.h>
#include<stdio.h>
typedef struct {double re, im; } Kompl;

Kompl kompl (double r, double i){


Kompl c;
c.re=r; c.im=i; return c;}

Kompl zbir (Kompl a, Kompl b){


a.re+=b.re; a.im+=b.im; return a;}

Kompl razlika (Kompl a, Kompl b){


a.re-=b.re; a.im-=b.im; return a;}

Kompl proizvod (Kompl a, Kompl b){


Kompl c;
c.re=a.re*b.re-a.im*b.im; c.im=a.im*b.re+a.re*b.im; return c;}

Kompl kolicnik (Kompl a, Kompl b){


Kompl c; double d=pow(b.re,2)+pow(b.im,2);
c.re=(a.re*b.re+a.im*b.im)/d;c.im=(a.im*b.re-a.re*b.im)/d; return c;}

Kompl citaj (void){


Kompl c;
scanf("%lf%lf",&c.re,&c.im); return c;}

void pisi(Kompl a){ printf("%.3f%cj%.3f",a.re,(a.im<0?'-':'+'),fabs(a.im));}

/* glavni program */
#include"kompleks.c"

main()
{
Kompl x,y,z,j={0,1};
while(1)
{
printf("\nprvi broj(re,im)? "); x=citaj();
printf("\ndrugi broj(re,im)? "); y=citaj();
if(y.re==0&&y.im==0)break;
z=zbir(x,y);printf("x+y= ");pisi(z);printf("\n");
z=razlika(x,y);printf("x-y= ");pisi(z);printf("\n");
z=proizvod(x,y);printf("x*y= ");pisi(z);printf("\n");
z=kolicnik(x,y);printf("x/y= ");pisi(z);printf("\n");
}
z=proizvod(j,j);printf("\nj^2= ");pisi(z);printf("\n");
}
2. Структура studenti садржи следећа поља: prezime, ime, broj_indeksa и mesto_stanovanja. Написати
програм који уноси податке за n студената (n<100), сортира их по пољу prezime и штампа сортиран низ.
Решење:
I – један модул, само главни програм
#include<stdio.h>

#include<string.h>
#define MAX 100

main()
{
struct studenti
{
char prezime[15];
char ime[15];
int broj_indeksa;
char mesto_stanovanja[15];
};

struct studenti student[MAX], pom;


int n, i, j;
printf("unesi broj studenata: ");scanf("%d", &n);
printf("\n");
printf("********************************\n"
"* PODACI O STUDENTIMA *\n"
"********************************\n");
for(i=0;i<n;i++)
{
printf("R.B.%d\n",i+1);
printf("Prezime: ");scanf("%s", &student[i].prezime);
printf("Ime: ");scanf("%s", &student[i].ime);
printf("Broj indeksa: ");scanf("%d", &student[i].broj_indeksa);
printf("Mesto stanovanja: ");scanf("%s", &student[i].mesto_stanovanja);
printf("\n\n");
}
for(i=0; i<n-1; i++)
{
for(j=i+1; j<n; j++)
{
if(strcmp(student[j].prezime,student[i].prezime)<0)
{
pom=student[i];
student[i]=student[j];
student[j]=pom;
}
}
}
for(i=0; i<n; i++)
{
printf("%15s%15s ",student[i].prezime,student[i].ime);
printf("%5d%15s\n",student[i].broj_indeksa,student[i].mesto_stanovanja);
}
}
II – модуларно решење:
/* student.c */
#include<stdio.h>
#include<string.h>
#define MAX 100

typedef struct {
char prezime[15];
char ime[15];
int broj_indeksa;
char mesto_stanovanja[15]; } Studenti;

void unesi(Studenti student[],int n)


{
int i;
for(i=0;i<n;i++)
{
printf("R.B.%d\n",i+1);
printf("Prezime: ");scanf("%s", &student[i].prezime);
printf("Ime: ");scanf("%s", &student[i].ime);
printf("Broj indeksa: ");scanf("%d", &student[i].broj_indeksa);
printf("Mesto stanovanja: ");scanf("%s", &student[i].mesto_stanovanja);
printf("\n\n");
}
}

void sortiraj(Studenti student[],int n)


{
int i,j; Studenti pom;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(strcmp(student[j].prezime,student[i].prezime)<0){
pom=student[i];student[i]=student[j];student[j]=pom;}
}

void pisi(Studenti student[],int n)


{
int i;
for(i=0; i<n; i++)
{
printf("%15s%15s ",student[i].prezime,student[i].ime);
printf("%5d%15s\n",student[i].broj_indeksa,student[i].mesto_stanovanja);
}
}

/* glavni program */
#include<stdio.h>
#include<string.h>
#include"strukturaStudent.c"
#define MAX 100

main()
{
Studenti student[MAX];
int n;
printf("unesi broj studenata: ");scanf("%d", &n);
printf("\n");
printf("********************************\n"
"* PODACI O STUDENTIMA *\n"
"********************************\n");
unesi(student,n);
sortiraj(student,n);
pisi(student,n);
}
3. Написати програмски модул у коме се описује структура Tacka чија су поља координате тачке, и у
коме су описане функције за рад са структуром Tacka:
– формирање податка Tacka од два цела броја
– одређивање растојања између две тачке
– одређивање координата најближе тачке координатном почетку из датог скупа тачака.
У главном програму унети низ тачака и приказати координате најближе тачке.
Решење:
/* tacka.c */

typedef struct {int x,y;} Tacka;

Tacka pravi_tacku (int x, int y)


{
Tacka t;
t.x=x;t.y=y;
return t;
}

#include<math.h>
double rastojanje (Tacka g, Tacka h)
{
return sqrt(pow(g.x-h.x,2)+pow(g.y-h.y,2));
}

const Tacka NULA={0,0};

Tacka *najbliza (Tacka a[], int n)


{
Tacka *min=a;
double r=rastojanje(a[0],NULA);int i;
for(i=1;i<n;i++)
{
double s=rastojanje(a[i],NULA);
if (s<r) {r=s;min=a+i;}
}
return min;
}

/* glavni program */
#include<stdio.h>
#include"tacka.c"

main()
{
Tacka a[100], r; int i, n;
printf("unesi n: ");scanf("%d",&n);
printf("unesi elemente niza:\n");
for(i=0;i<n;i++)
{
printf("%d. x= ",i+1);scanf("%d",&a[i].x);
printf("y= ");scanf("%d",&a[i].y);
printf("\n");
}
r=*najbliza(a,n);
printf("koordinate najblize tacke koordinatnom pocetku su: x=%d, y=%d\n",r.x,r.y);
}

 Zadaci za vežbu

1. Uneti ime i prezime učenika te broj opravdanih i neopravdanih časova. Ispisati ime,

prezime, broj opravdanih i neopravdanih časova, te ukupan broj izostanaka!

2. Uneti ime, prezime te opšti uspeh za 2 učenika. Ispisati ime i prezime učenika koji ima

bolji uspeh!

3. Uneti ime, prezime učenika te ocene iz Srpskog, Matematike, Fizike i Engleskog. Ispisati

ime, prezime te prosečnu ocenu iz navedenih predmeta!

4. U biblioteci se nalazi n knjiga sa sledecim podacima

- Naziv knjige

- Naziv autora

- Tema knjige

- ID knjige

- Godina izdavanja

Napisati program koji ce sortirati knjige u opadajucem poretku po Godini izdavanja

5. U biblioteci se nalazi n knjiga sa sledecim podacima

- Naziv knjige

- Naziv autora

- Tema knjige

- ID knjige

- Godina izdavanja

Napisati program koji ce sortirati knjige u opadajucem poretku po nazivu knjig

You might also like