Vezbe iz Osnova programiranja
62. NCP koji unosi sa standardnog ulaza unosi dva kompleksna broja (Realni, Imaginarni deo) i
ispisuje na standardni izlaz njihov zbir, razliku, proizvod, kolicnik. Ako je drugi broj 0, onda prekinuti dalje ucitavanje i ispis (deljenje nulaom!!!) i ispisati vrednost imaginarne jedinice(0+i).
/* STRUKTURE */
#include <math.h> /*zbog pow(x,2) */
#include <stdio.h>
typedef struct { double re, im; } Kompl; /* Struktura kompleksnog broja. */
/*alternativa: struct KB { double re, im; }; typedef struct KB Kompl ; */
Kompl zbir (Kompl a, Kompl b); /*funkcija racuna a+b, kao rezultat vraca strukturu, tj. kompleksan broj */
Kompl razlika (Kompl a, Kompl b); /* a-b */
Kompl proizvod (Kompl a, Kompl b); /* funkcija racuna a*b, kao rezultat vraca strukturu, tj. kompleksan broj */
Kompl kolicnik (Kompl a, Kompl b) ; /* a/b */
main () {
Kompl x, y, z;
Kompl j = {0, 1}; /*primer eksplicitnog zadavanja polja strukture Kompl: prvo polje re=0, drugo polje im=1 */
/*ucitavanje dva kompleksna broja - brojevi sa tastature se unose u polja strukture */
while (1) {
printf ("\nUnesite prvi broj x- Re, Im: "); scanf ("%lf%lf", &x.re, &x.im);
printf ( "Unesite drugi broj y- Re, Im: "); scanf ("%lf%lf", &y.re, &y.im);
if (y.re==0 && y.im==0) break; /*bez deljenja nulom */
printf ("x = (%f,%f)\n", x.re, x.im);
printf ("y = (%f,%f)\n", y.re, y.im);
z = zbir (x, y); printf ("x+y = (%f,%f)\n", z.re, z.im);
z = razlika (x, y); printf ("x-y = (%f,%f)\n", z.re, z.im);
z = proizvod (x, y); printf ("x*y = (%f,%f)\n", z.re, z.im);
z = kolicnik (x, y); printf ("x/y = (%f,%f)\n", z.re, z.im);
}
z = proizvod (j, j); printf ("\nj^2 = (%f,%f)\n", z.re, z.im);
}
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;
}
63. NCP koji učitava iz datoteke ulaz.htm informacije(naziv hale, lokacija:ulica i grad, kapacitet
izrazen u broju mesta za gledaoce, cenu renoviranja) o sportskim halama regiona (do 4 hale),
a potom ispisuje na standardni izlaz sve rasplozive informacije za hale cija cena renoviranja ne prelazi 10000.
Jednostavnosti radi, moze se prtpostaviti da se svi pojavni nazivi u ulaznoj datoteci sastoje od jedne reci (fscanf(...)).
#include
#define MARKER_KRAJ_STRINGA 1
#define MAX_ZNAK 30
#define MAX_HALA 4
struct hala_podatak {
char naziv [ MAX_ZNAK + MARKER_KRAJ_STRINGA ], /*naziv hale */
ulica[ MAX_ZNAK + MARKER_KRAJ_STRINGA ], /*naziv ulice hale */
grad [ MAX_ZNAK + MARKER_KRAJ_STRINGA ]; /*ime grada kome pripada hala*/
int mesta; /*kapacitet hale */
float cena; /*cena radova */
};
main( )
{
struct hala_podatak NizHala[ MAX_HALA ]; /*niz struktura koji sadrzi podatke o halama */
int i; /*brojac u petlji */
char s[6]; /* pomocna niska */
float cenafix;
FILE *f;
f=fopen("ulaz.txt", "r");
/*ucitavanje podataka o svakoj hali iz datoteke ulaz.txt */
for( i = 0; i < MAX_HALA; i++ )
{
fscanf(f, "%s", NizHala[ i ].naziv);
fscanf(f, "%s", NizHala[ i ].ulica);
fscanf(f, "%s", NizHala[ i ].grad);
fscanf(f, "%d", &NizHala[ i ].mesta);
fscanf(f, "%f", &cenafix);
NizHala[ i ].cena = cenafix;
printf("\n\n");
}
/*formatiran ispis hala cija cena renoviranja ne prelazi 10000*/
for( i = 0; i < MAX_HALA; i++ )
if (NizHala[ i ].cena <= 10000)
{ printf("\n");
printf("==============HALA %d ================ "
"\nNaziv:\t\t%25s"
"\nUlica:\t\t%25s"
"\nGrad:\t\t%25s"
"\nKapacitet:\t%25d"
"\nCenaRadova:\t\t%25.2f",
i+1,
NizHala[ i ].naziv,
NizHala[ i ].ulica,
NizHala[ i ].grad,
NizHala[ i ].mesta,
NizHala[ i ].cena);
}
fclose(f);
return 0;
}
64. Grupa od N ljudi redom numerisanih od 1 do N obrazovala je krug. Počevši od prvog čoveka, a krećući se u smeru kazaljke na satu iz kruga redom izlazi M-ti čovek. Preostali ljudi obrazuju novi manji krug
pri čemu odbrojavanje počinje od levog suseda izbačenog. Celi brojevi M, N nisu unapred poznati, već se unose sa standardnog ulaza. NCP koji ispisuje redne brojeve osoba u redosledu napuštanja kruga.
/*josif zadatak */
#include <stdio.h>
#include <stdlib.h>
typedef struct covek_cvor
{ int rbr;
struct covek_cvor *sledeci;
}covek;
main()
{ int i; /*brojac u petljama */
int N; /*broj ljudi u krugu */
int M; /*redni broj za izbacivanje */
covek *prvi,*p,*pom;
/*covek *p;
covek *prvi;
covek *pom;
*/
printf("Unesite N za ukupan broj ljudi koji obrazuje krug i M za svaki M-ti koji se izbacuje iz kruga ");
scanf("%d %d",&N,&M);
/*prvi clan liste ljudi u krugu */
prvi=(covek*) malloc(sizeof(covek));
prvi->rbr=1;
p=prvi;
/*formiranje susednih clanova liste */
for(i=2;i < N+1;i++)
{ if ( (p->sledeci= (covek*) malloc(sizeof(covek) ) ) == NULL)
{ printf("Nema u memoriji dovoljno mesta za malloc\n");
exit(1);
}
p=p->sledeci;
p->rbr=i;
}
/*zatvaranje kruga */
p->sledeci=prvi;
/*izbacivanje M-tog */
while( p != p->sledeci) /*tj. dok ne ostane samo jedan u krugu */
{
for(i=1;i< M;i++) p=p->sledeci;
printf("Izbaciti %d\n", p->sledeci->rbr);
pom=p->sledeci;
p->sledeci=p->sledeci->sledeci;
free(pom);
}
/*ispis rezultata */
printf("I na kraju ostao je %d\n",p->rbr);
}
65. NCP koji iz neprazne datoteke broj.txt ucitava paran broj celih brojeva x[1], x[2],...,x[n], gde n nije unapred poznato.
Ispisati poruku na standardni izlaz da li vazi da x[1]==x[n], x[2]==x[n-1],..., x[k]=x[k+1], k=1..n/2
#include <stdio.h>
#include <stdlib.h>
typedef struct listacv dvlista;
/*dvostruko povezana linearna lista*/
struct listacv
{ int broj; /*informaciono polje je clan niza x*/
dvlista *sledeci, *prethodni;
};
dvlista *ubaci(dvlista *tek, int broj);
/*dodaje broju u clan liste tek i vraca cvor sa kraja liste*/
main()
{
dvlista *prvi, *kraj; /*prvi i poslednji cvor dvostruke liste*/
int n; /*broj ucitanih celih brojeva*/
int broj; /*tekuci broj sa ulaza*/
int jednak; /*indikator jednakosti dva clana - cuva vrednost 0 ili 1 */
FILE *ulaz;
int i; /*brojacka promenljiva*/
/*otvaranje datoteke za citanje i upis brojeva iz datoteke u
dvostruku povezanu listu */
ulaz=fopen("broj.txt", "r");
fscanf(ulaz, "%d", &broj);
/*kreiranje prvog cvora liste za prvi ucitan broj */
prvi=(dvlista*)malloc(sizeof(dvlista));
prvi->broj=broj;
prvi->sledeci=NULL;
prvi->prethodni=NULL;
kraj=prvi; n=1; //za sada ucita je samo jedan clan
/*formiranje liste od brojeva koji se ucitavaju sve do kraja datoteke - feof(ulaz) */
while (!feof(ulaz))
{ fscanf(ulaz, "%d", &broj);
kraj=ubaci (kraj, broj);
n++;
}
fclose(ulaz);
/*testiranje jednakih parova uz poeranje tekuceg prvog clana i tekuceg poslednjeg
clana ka sredini liste*/
jednak=1;
for(i=1; i<=n/2 && jednak; i++)
{ jednak=jednak&&(prvi->broj==kraj->broj);
prvi=prvi->sledeci; /*pomeranje ka sredini liste */
kraj=kraj->prethodni; /*pomeranje ka sredini liste */
}
printf("Za unete broje jednakost ");
if(!jednak) printf("ne ");
printf("vazi\n");
return 0;
}
dvlista *ubaci(dvlista *kraj, int broj)
{
dvlista *novi; /*novi cvor za umetanje u listu*/
novi=(dvlista *)malloc(sizeof(dvlista)); /*alokacija memorije za novi cvor liste*/
novi->broj=broj; /*inicijalizacija polja broj u cvoru novi */
novi->sledeci=NULL;
novi->prethodni=kraj; /*novi element se dodaje na kraj postojece liste*/
kraj->sledeci=novi; /* do tada poslednji cvor kraj je ispred clana novi*/
kraj=novi; /*poslednji dodat element je novi kraj liste*/
return kraj;
}
66. NCP koji sa standardnog ulaza ucitava dva pravougaonika u ravni A, B i na standrdni izlaz ispisuje povrsinu preseka
pravougaonika, povrsinu unije pravougaonika, povrsinu razlike pravougaonika(A\B). Pravougaonik se zadaje preko
x,y koordinata donjeg levog i gornjeg desnog temena pravougaonika. Stranice pravougaonika su paralelne koordinatnim osama.
#include <stdio.h>
#include <stdlib.h>
typedef struct _rect
{ float x,y; /*koordinate donjeg levog ugla */
float x1,y1; /*koordinate gornjeg desnog ugla */
} Pravougaonik ;
void ucitavanje (Pravougaonik *P); /*ucitavanje donjeg levog i gornjeg desnog temena pravougaonika */
Pravougaonik Presek(Pravougaonik *A, Pravougaonik *B); /*presek pravougaonika A i pravougaonika B */
float Povrsina (Pravougaonik *A); /*izracunavanje povrsine datog pravougaonika */
main()
{ Pravougaonik A,B ; /*zadati pravougaonici */
Pravougaonik presekAB ; /*presek zadata dva pravougaonika */
float povrsinaA; /*povrsina pravougaonika A*/
float povrsinaB; /*povrsina pravougaonika B*/
float povrsAB; /*povrsina preseka pravougaonika A i pravougaonika B*/
/*ucitavanja pravougaonika sa standardnog ulaza */
ucitavanje(&A);
ucitavanje(&B);
/*odredjivanje A*B */
presekAB = Presek (&A , &B);
/*izracunavanje povrsine datih pravougaonika i njihovog preseka */
povrsinaA=Povrsina(&A);
povrsinaB=Povrsina(&B);
povrsAB= Povrsina (&presekAB);
/*ispis rezultata */
printf( "Povrsina unije : %g\n", povrsinaA+povrsinaB-povrsAB);
printf( "Povrsina preseka : %g\n", povrsAB);
printf( "Povrsina prve razlike : %g\n", povrsinaA - povrsAB);
return 0;
}
void ucitavanje (Pravougaonik * P)
{ /*ucitavanje koordinata za odgovarajuca dva temena */
scanf("%f%f%f%f", &P->x, &P->y, &P->x1, &P->y1);
}
Pravougaonik Presek (Pravougaonik *A, Pravougaonik *B)
{
/*Racuna se i vraca presek pravougaonika A i B.
Ako se A i B ne seku , funkcija vraca pravougaonik cije su sve koordinate jednake 0 */
Pravougaonik rezultat; /*presek zadata dva pravougaonika */
/*odredjivanje koordinata donjeg levog ugla preseka-uociti tacka i strelica notaciju kod rezultat i kod A, B */
rezultat.x = (A->x > B->x) ? A->x : B->x;
rezultat.y = (A->y > B->y) ? A->y : B->y;
/*odredjivanje koordinata gornjeg desnog ugla preseka => relacijski operator manje */
rezultat.x1 = (A->x1 < B->x1) ? A->x1 : B->x1;
rezultat.y1 = (A->y1 < B->y1) ? A->y1 : B->y1;
/*pravljenje korekcije u slucaju da je rezultat preseka prazan */
if (rezultat.x >= rezultat. x1 || rezultat.y >= rezultat.y1 )
rezultat.x=rezultat.y = rezultat.x1 = rezultat.y1 = 0;
return rezultat;
}
float Povrsina (Pravougaonik *P )
{ /*vraca se rezultat mnozenja duzina dveju susednih stranica znajuci za paralelnost sa koordinatnim osama */
return (P->x1 -P->x) * (P->y1 - P->y );
}
67. Pod pretpostavkom da postoji bar jedna reč na ulazu, ispisati na standardni izlaz samo različite reči sortirane leksikografski. Uz svaku reč ispisati i broj pojava. Kraj unosa je marker kraja (EOF),
a dužina reči nije veća od 30 karaktera. Smatrati da 1) reč je niska sastavljen isključivo
od slova i cifara 2) tip int je dovoljan za čuvanje broja pojava svake reči
/* Samoreferentne strukture , binarno pretrazivacko stablo */
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define MAXREC 31
typedef struct drvo_tag
{
char *rec; /* pokazuje na rec teksta */
int broj; /* broj pojavljivanja pod pretpostavkom da je int dovoljan */
struct drvo_tag *levo; /* leva grana */
struct drvo_tag *desno; /* desna grana */
} drvo;
/* Prototipovi funkcija */
drvo *addtree(drvo *, char *);
void treeprint(drvo *);
int uzmi_rec(char *, int);
drvo *talloc( void );
char *strdpl(char *);
void osloboditi( drvo *k);
main()
{
drvo *koren; /*koren stabla pretrazivanja */
char rec[MAXREC]; /*sadrzaj reci sa ulaza */
/*ucitavanje reci ciji broj pojavljivanja se broji */
koren = NULL;
while( 1 )
{
int kraj = uzmi_rec(rec, MAXREC);
/*dodavanje novog cvora u stablo ili izmena nad poljem broj vec postojeceg cvora */
if( strlen(rec)) koren = addtree( koren, rec);
if(kraj == EOF) break; /*ucitavanje se vrsi do markera kraja */
}
/*stampanje sadrzaja stabla -leksikografski poredak reci */
treeprint(koren);
/*oslobadjanje zauzetog prostora za stablo pretrage */
osloboditi(koren);
return 0;
}
/* addtree - dodaje cvor sa tekstom na koji pokazuje w, na ili ispod p u drvetu*/
drvo *addtree( drvo *p, char *w )
{
int cond;
if( p == NULL ) /* naisla nova rec */
{
p = talloc();
p->rec = strdpl(w);
p->broj = 1;
p->levo = p->desno = NULL;
}
else if ((cond = strcmp(w,p->rec)) == 0 )
p->broj++; /* ponovljena rec */
else if ( cond < 0 ) /* manje => levi ogranak */
p->levo = addtree(p->levo, w);
else /*vece =>desni ogranak*/
p->desno = addtree(p->desno, w);
return p;
}
void treeprint(drvo *p) /* treeprint - rekurzivno stampanje drveta*/
{
if( p != NULL )
{
treeprint( p->levo );
printf("%4d %s\n", p->broj, p->rec );
treeprint( p->desno );
}
}
int uzmi_rec(char s[], int lim)
{
char c, i = 0;
/* preskociti sve znake do slova ili cifre */
while( !isalnum(c = s[0] = getchar()) && c!=EOF);
if( c==EOF ) {s[0] = '\0'; return EOF;} /* prazna rec i vratiti EOF */
/* ucitati ostatak reci: (u s[0] se vec nalazi prvo slovo) */
while( (c = getchar()) != EOF && isalnum(c) && i < lim) s[++i] = c;
s[++i] = '\0'; /* zavrsiti nisku */
if( c==EOF ) return EOF;
return i;
}
/* talloc pravi jedan cvor drveta */
drvo *talloc(void)
{ return (drvo *) malloc(sizeof(drvo)); }
char *strdpl(char *s) /* pravi se kopija niske s */
{
char *p;
p = (char *) malloc(strlen(s) + 1 );
if( p != NULL ) strcpy(p,s);
return p;
/* u <string.h> postoji standardna funkcija "strdup" koja obavlja navedene operacije*/
}
void osloboditi( drvo *k)
{ /*rekurzivno se oslobadja levo i desno podstablo korena zadatog stabla */
if (k->levo) osloboditi (k->levo);
if (k->desno) osloboditi (k->desno);
free (k); /*brisanje cvora koji predstavlja koren zadatog stabla */
}
e-mail: Jelena Grmuša
Copyright © 2002, Jelena Grmusa
Poslednja izmena: februar 2004.
URL:
http://www.matf.bg.ac.yu/~jelenagr/op/