Razlomci
Definisati strukturu Razlomak sa poljima br i im. Učitati dva razlomka (brojilac i imenilac, imenioci su pozitivni) i ispisati njihov zbir u skraćenom obliku br/im.
Primer 1
Ulaz
1 2 1 3Izlaz
5/6Primer 2
Ulaz
3 4 1 4Izlaz
1/1Struktura (struct) spaja više podataka različitih tipova u jednu celinu – npr. ime, razred i prosek učenika. Umesto tri odvojena niza imamo jedan niz učenika. U ovoj lekciji su definisanje, pristup poljima, nizovi struktura, slanje u funkcije i sortiranje.
Struktura se definiše van funkcije main. Svaki deo strukture zove se polje (član). Polju se pristupa tačkom: t.x.
#include <stdio.h>
/* nov tip: tačka u ravni */
struct Tacka {
int x;
int y;
};
int main(void) {
struct Tacka a; /* promenljiva tipa struct Tacka */
a.x = 3;
a.y = 4;
struct Tacka b = {1, 2}; /* inicijalizacija redom polja */
struct Tacka c = {.y = 7, .x = 5}; /* ili po imenima polja */
printf("a = (%d, %d)\n", a.x, a.y);
printf("b = (%d, %d)\n", b.x, b.y);
printf("c = (%d, %d)\n", c.x, c.y);
b = a; /* dodela kopira sva polja */
printf("posle b = a: (%d, %d)\n", b.x, b.y);
return 0;
}
Strukture se mogu dodeljivati (b = a), ali se ne mogu porediti sa == – poredi se polje po polje.
Da ne bismo stalno pisali struct Tacka, uvodi se kraće ime pomoću typedef:
#include <stdio.h>
typedef struct {
char ime[30];
int razred;
double prosek;
} Ucenik; /* sada je Ucenik ime tipa */
int main(void) {
Ucenik u;
scanf("%29s %d %lf", u.ime, &u.razred, &u.prosek);
printf("%s, %d. razred, prosek %.2f\n", u.ime, u.razred, u.prosek);
return 0;
}
Za tekstualno polje (char ime[30]) u scanf se ne piše & – ime niza je već adresa. Broj 29 čuva mesto za završni znak '\0' (vidi Stringovi u jeziku C).
Najčešća upotreba: niz struktura umesto više paralelnih nizova. Element niza je cela struktura, a polju se pristupa sa niz[i].polje.
#include <stdio.h>
typedef struct {
char ime[30];
int poeni;
int vreme; /* u minutima */
} Takmicar;
int main(void) {
int n;
Takmicar t[100];
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%29s %d %d", t[i].ime, &t[i].poeni, &t[i].vreme);
/* najbolji: više poena; kod istih poena – kraće vreme */
int best = 0;
for (int i = 1; i < n; i++)
if (t[i].poeni > t[best].poeni ||
(t[i].poeni == t[best].poeni && t[i].vreme < t[best].vreme))
best = i;
printf("Pobednik: %s (%d poena, %d min)\n", t[best].ime, t[best].poeni, t[best].vreme);
return 0;
}
Uporedi sa rešenjem bez struktura: tri niza ime[], poeni[], vreme[] čiji elementi sa istim indeksom „pripadaju“ istom takmičaru. Kod sortiranja bi trebalo zamenjivati sva tri niza – sa strukturom menjamo jedan element.
Struktura se funkciji predaje po vrednosti – funkcija dobija kopiju i ne može da promeni original. Da bi funkcija menjala strukturu, prosleđuje joj se pokazivač, a polju se pristupa operatorom -> (p->x je isto što i (*p).x).
#include <stdio.h>
typedef struct {
int x, y;
} Tacka;
/* po vrednosti: dobija kopiju, vraća rezultat */
int kvadratRastojanja(Tacka a, Tacka b) {
int dx = a.x - b.x, dy = a.y - b.y;
return dx * dx + dy * dy;
}
/* preko pokazivača: menja original */
void pomeri(Tacka *p, int dx, int dy) {
p->x += dx; /* isto što i (*p).x += dx */
p->y += dy;
}
int main(void) {
Tacka a = {0, 0}, b = {3, 4};
printf("d^2 = %d\n", kvadratRastojanja(a, b));
pomeri(&a, 1, 1);
printf("a = (%d, %d)\n", a.x, a.y);
printf("d^2 = %d\n", kvadratRastojanja(a, b));
return 0;
}
Za velike strukture i kada se ne menjaju, pokazivač se šalje i radi brzine – ne kopira se ceo sadržaj. Tada se piše const Tacka *p. Više o pokazivačima: Pokazivači u jeziku C.
Polje strukture može biti druga struktura:
#include <stdio.h>
typedef struct {
int dan, mesec, godina;
} Datum;
typedef struct {
char ime[30];
Datum rodjen; /* polje koje je i samo struktura */
} Osoba;
/* vraća negativan broj ako je d1 pre d2, 0 ako su jednaki, pozitivan inače */
int uporediDatume(Datum d1, Datum d2) {
if (d1.godina != d2.godina) return d1.godina - d2.godina;
if (d1.mesec != d2.mesec) return d1.mesec - d2.mesec;
return d1.dan - d2.dan;
}
int main(void) {
Osoba a = {"Mila", {12, 5, 2013}};
Osoba b = {"Teodor", {3, 11, 2012}};
Osoba *stariji = uporediDatume(a.rodjen, b.rodjen) < 0 ? &a : &b;
printf("Stariji je %s, rodjen %d.%d.%d.\n", stariji->ime,
stariji->rodjen.dan, stariji->rodjen.mesec, stariji->rodjen.godina);
return 0;
}
Funkcija qsort iz stdlib.h sortira bilo kakav niz. Dobija niz, broj elemenata, veličinu jednog elementa i funkciju poređenja koja vraća negativan broj ako prvi element ide ispred drugog, nulu ako su jednaki i pozitivan broj inače.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char ime[30];
int poeni;
} Takmicar;
/* više poena ide prvo; kod jednakih poena – abecedno */
int poredi(const void *a, const void *b) {
const Takmicar *x = a, *y = b;
if (x->poeni != y->poeni)
return y->poeni - x->poeni;
return strcmp(x->ime, y->ime);
}
int main(void) {
int n;
Takmicar t[100];
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%29s %d", t[i].ime, &t[i].poeni);
qsort(t, n, sizeof(Takmicar), poredi);
for (int i = 0; i < n; i++)
printf("%d. %s %d\n", i + 1, t[i].ime, t[i].poeni);
return 0;
}
U C++-u isti posao radi sort sa lambda funkcijom – vidi STL u C++-u. Unije (union) i raspored struktura u memoriji objašnjeni su u lekciji Uvod u strukture i unije.
Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.
Definisati strukturu Razlomak sa poljima br i im. Učitati dva razlomka (brojilac i imenilac, imenioci su pozitivni) i ispisati njihov zbir u skraćenom obliku br/im.
1 2 1 35/63 4 1 41/1Učitava se n, pa za svakog učenika ime i ocene iz 5 predmeta. Ispisati imena učenika sa prosekom bar 4,50, poređana po proseku opadajuće (kod istog proseka abecedno), uz prosek na dve decimale. Ako takvih nema, ispisati NEMA.
4
Marko 5 5 4 5 4
Ana 5 5 5 5 4
Iva 4 4 5 3 5
Luka 5 5 5 4 4Ana 4.80
Luka 4.60
Marko 4.60struct Tacka { int x, y; };.typedef tip se zove struct Tacka, a ne samo Tacka.t.x) se koristi za promenljivu-strukturu, strelica (p->x) za pokazivač na strukturu.==; napiši funkciju koja poredi polja.qsort ne vraćaj razliku realnih brojeva (x->prosek - y->prosek) – rezultat se odseca na int i 0.3 postaje 0.1. Kako se pristupa polju ime promenljive u tipa struct Ucenik?
2. Ako je p pokazivač na strukturu, šta je p->x?
3. Šta funkcija dobija kada joj se struktura preda po vrednosti?
4. Šta treba da vrati funkcija poređenja za qsort kada prvi element ide ispred drugog?