Vezbe iz Osnova programiranja – strukture (uvod)




108. NCP koji izracunava obim i povrsinu trougla i kvadrata.

/* Program uvodi strukture - geometrijske figure */


#include <stdio.h>


/* Zbog funkcije sqrt. */

#include <math.h>

/* Podsecanje : pod linux-om je potrebno program prevoditi sa

gcc -lm primer.c

kada god se koristi <math.h>

*/


/* Tacke su predstavljene sa dve koordinate. Strukturom gradimo novi tip podataka. */

struct point

{

int x;

int y;

};


/* Izracunava duzinu duzi zadatu sa dve tacke */

float segment_length(struct point A, struct point B)

{

int dx = A.x - B.x;

int dy = A.y - B.y;

return sqrt(dx*dx + dy*dy);

}



/* Izracunava povrsinu trougla Heronovim obrascem.

Argumenti funkcije su tri tacke koje predstavljaju temena trougla */

float Heron(struct point A, struct point B, struct point C)

{

/* Duzine stranica BC, AC, AB*/

float a = segment_length(B, C);

float b = segment_length(A, C);

float c = segment_length(A, B);


/* Poluobim */

float s = (a+b+c)/2;

/*Heronov obrazac */

return sqrt(s*(s-a)*(s-b)*(s-c));

}



/* Izracunava obim poligona. Argumenti funkcije su niz tacaka(niz struktura point)

koje predstavljaju temena poligona kao i njihov broj */

float circumference(struct point polygon[], int num)

{

int i; /*brojac u ciklusu */

float o = 0.0; /*obim */



/* Dodajemo duzine stranica koje spajaju susedna temena */

for (i = 0; i<num-1; i++)

o += segment_length(polygon[i], polygon[i+1]);



/* Dodajemo duzinu stranice koja spaja prvo i poslednje teme */

o += segment_length(polygon[num-1], polygon[0]);


return o;

}



/* Izracunava povsinu konveksnog poligona. Argumenti funkcije su niz tacaka koje predstavljaju temena poligona kao i njihov broj */

float area(struct point polygon[], int num)

{

float a = 0.0; /* Povrsina */

int i; /* brojacka promenljiva */


/* Poligon delimo na trouglove i posebno izracunavamo povrsinu svakoga od njih */

for (i = 1; i < num -1; i++)

a += Heron(polygon[0], polygon[i], polygon[i+1]);


return a;

}


main()

{

/* Definisemo dve promenljive tipa tacke */

struct point a;


/* Inicijalizujemo tacku b na (1,2) */

struct point b = {1, 2};


/* triangle je niz od tri tacke - trougao (0,0), (0,1), (1,0) */

struct point triangle[3];


/* square je niz od cetiri tacke - jedinicni kvadrat.

Obratiti paznju na nacin inicijalizacije niza struktura */

struct point square[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};


/* Postavljamo vrednosti koordinata tacke a*/

a.x = 0; a.y = 0;


/* Gradimo trougao (0,0), (0,1), (1,0) */

triangle[0].x = 0; triangle[0].y = 0;

triangle[1].x = 0; triangle[1].y = 1;

triangle[2].x = 1; triangle[2].y = 0;


/* Ispisujemo velicinu strukture tacka */

printf("sizeof(struct point) = %d\n", sizeof(struct point));


/* Ispisujemo vrednosti koordinata tacaka */

printf("x koordinata tacke a je %d\n", a.x);

printf("y koordinata tacke a je %d\n", a.y);

printf("x koordinata tacke b je %d\n", b.x);

printf("y koordinata tacke b je %d\n", b.y);

printf("Obim trougla je %f\n",

circumference(triangle, 3));

printf("Obim kvadrata je %f\n",

circumference(square, 4));

printf("Povrsina trougla je %f\n",

Heron(triangle[0], triangle[1], triangle[2]));



/* Broj tacaka je moguce odrediti i putem sizeof */

printf("Povrsina kvadrata je %f\n",

area(square, sizeof(square)/sizeof(struct point)));



}




Izlaz:


sizeof(struct point) = 8

x koordinata tacke a je 0

y koordinata tacke a je 0

x koordinata tacke b je 1

y koordinata tacke b je 2

Obim trougla je 3.414214

Obim kvadrata je 4.000000

Povrsina trougla je 0.500000

Povrsina kvadrata je 1.000000






109. NCP koji postavlja vrednosti koordinata tacke u 2-dimenzionoj ravni i ispisuje te koordinate. (Ilustracija koriscenja typedef.)

/* Koriscenje typedef radi lakseg rada */


#include <stdio.h>

#include <math.h>


/* Ovim se omogucava da se nadalje u programu umesto int moze koristiti ceo_broj */

typedef int ceo_broj ;


/* Ovim se omogucuje da se nadalje u programu umesto struct point moze koristiti POINT */

typedef struct point POINT;


struct point

{

int x;

int y;

};



main()

{


/* Umesto int mozemo koristiti ceo_broj */

ceo_broj x = 3;


/* Definisemo promenljivu tipa tacke. Umesto struct point mozemo koristiti POINT */

POINT a;

printf("x = %d\n", x);


/* Postavljamo vrednosti koordinata tacke a*/

a.x = 1; a.y = 2;


/* Ispisujemo velicinu strukture tacka */

printf("sizeof(struct point) = %d\n", sizeof(POINT));


/* Ispisujemo vrednosti koordinata tacaka */

printf("x koordinata tacke a je %d\n", a.x);


printf("y koordinata tacke a je %d\n", a.y);

}



Izlaz:


x = 3

sizeof(struct point) = 8

x koordinata tacke a je 1

y koordinata tacke a je 2





110. 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 nulom!!!) 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;
}



111. Strukture se u funkcije cesto prenose po referenci. Moguce je koristiti pokazivace na strukture.
Sta je rezultat rada sledeceg programa?



#include <stdio.h>


typedef struct point

{

int x, y;

} POINT;


/* Zbog prenosa po vrednosti tacka ne moze biti ucitana */

void get_point_wrong(POINT p)

{

printf("x = ");

scanf("%d", &p.x);

printf("y = ");

scanf("%d", &p.y);

}


/* Koriscenjem prenosa preko pokazivaca, uspevamo */

void get_point(POINT* p)

{

/* p->x je skraceni zapis za (*p).x */

printf("x = ");

scanf("%d", &p->x);

printf("y = ");

scanf("%d", &p->y);

}


main()

{

POINT a = {0, 0};

printf("get_point_wrong\n");

get_point_wrong(a);

printf("a: x = %d, y = %d\n", a.x, a.y);


printf("get_point\n");

get_point(&a);

printf("a: x = %d, y = %d\n", a.x, a.y);

}


112. NCP koji sa standardnog ulaza ucitava dva pravougaonika u ravni A, B i na standardni 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. Ucitavanje paravougaonika, nalazenje preseka dva pravougaonika i izracunavanje povrsine pravougaonika izdvojiti u posebne funkcije!!!

#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 );
}



113. Sa standardnog ulaza se ucitava niz od n (n<100) tacaka u ravni takvih da nikoje tri tacke nisu kolinearne. Tacke se zadaju parom svojih koordinata (celi brojevi). Ispitati da li taj niz tacaka odredjuje konveksni mnogougao i rezultat ispisati na standardni izlaz.


#include<stdio.h>


typedef struct tacka

{

int x;

int y;

} TACKA;


/* F-ja ispituje da li se tacke T3 i T4 nalaze sa iste strane prave odredjene tackama T1 i T2.*/

int SaIsteStranePrave(TACKA T1,TACKA T2, TACKA T3, TACKA T4)

{

int t3 = (T3.y - T1.y)*(T2.x - T1.x) - (T2.y - T1.y) * (T3.x - T1.x);

int t4 = (T4.y - T1.y)*(T2.x - T1.x) - (T2.y - T1.y) * (T4.x - T1.x);

return (t3 * t4 > 0);

}


main()

{

TACKA mnogougao[100];

int j,i;

int n;

int konveksan = 1;


do

{

printf("Unesite broj temena mnogougla:\n");

scanf("%d",&n);


if(n<3) printf("Greska! Suvise malo tacaka! Pokusajte ponovo!\n");

}

while(n<3);


printf("Unesite koordinate temena mnogougla takve da nikoja tri temena nisu kolinearna!\n");


for(i=0;i<n;i++) scanf("%d %d", &mnogougao[i].x, &mnogougao[i].y);


/* Da bi mnogougao bio konveksan potrebno (i dovoljno) je da kada se

povuce prava kroz bilo koja dva susedna temena mnogougla sva ostala

temena budu sa iste strane te prave.*/

for(i=0;konveksan&&i<n-1;i++)

{

for(j=0;konveksan&&j<i-1;j++) konveksan=konveksan && SaIsteStranePrave(mnogougao[i], mnogougao[i+1],mnogougao[j],mnogougao[j+1]);


for(j=i+2;konveksan&&j<n-1;j++) konveksan=konveksan && SaIsteStranePrave(mnogougao[i],mnogougao[i+1],mnogougao[j],mnogougao[j+1]);


if(i!=0&&i!=n-1&&i+1!=0&&i+1!=n-1) konveksan=konveksan && SaIsteStranePrave(mnogougao[i], mnogougao[i+1],mnogougao[0],mnogougao[n-1]);

}


for(j=1;konveksan&&j<n-2;j++) konveksan=konveksan && SaIsteStranePrave(mnogougao[0], mnogougao[n-1],mnogougao[j],mnogougao[j+1]);


if(konveksan) printf("Uneti mnogougao jeste konveksan!\n");

else printf("Uneti mnogougao nije konveksan!\n");


}



114. Sa standardnog ulaza se unose koordinate četiri tačke A, B, C i D (realni brojevi) koje pripadaju istoj ravni. Proveriti da li tačka D pripada ili ne pripada unutrasnjosti trougla ABC (tačke A, B, C nisu kolinearne) i dobijeni rezultat ispisati na standardni izlaz.



#include<stdio.h>



typedef struct tacka

{

float x;

float y;

} TACKA;



/* F-ja ispituje da li se tacke T3 i T4 nalaze sa iste strane prave odredjene tackama T1 i T2. Pri tom, ukoliko neka od tacaka T3 i T4 lezi na odgovarajucoj pravoj smatra se da tacke nisu sa iste strane te prave. */

int SaIsteStranePrave(TACKA T1,TACKA T2, TACKA T3, TACKA T4)

{

int t3 = (T3.y - T1.y)*(T2.x - T1.x) - (T2.y - T1.y) * (T3.x - T1.x);

int t4 = (T4.y - T1.y)*(T2.x - T1.x) - (T2.y - T1.y) * (T4.x - T1.x);

return (t3 * t4 > 0);

}



main()

{

TACKA A, B, C, D;

printf("Unesite koordinate temena trougla:\n");

printf("Unesite koordinate temena A:\n");

scanf("%f %f", &A.x, &A.y);

printf("Unesite koordinate temena B:\n");

scanf("%f %f", &B.x, &B.y);

printf("Unesite koordinate temena C:\n");

scanf("%f %f", &C.x, &C.y);

printf("Unesite koordinate tacke D za koju se ispituje da li pripada trouglu ABC:\n");

scanf("%f %f", &D.x, &D.y);



if(SaIsteStranePrave(A,B,C,D) && SaIsteStranePrave(B,C,A,D) && SaIsteStranePrave(A,C,B,D))

printf("Tacka D pripada trouglu ABC!\n");

else printf("Tacka D ne pripada trouglu ABC!\n");

}



Zadaci za vezbu:


Zadatak 1. NCP koji unosi sa standardnog ulaza unosi kompleksan broj (Realni, Imaginarni deo) i ispisuje na standardni izlaz njemu konjugovan kompleksan broj i moduo.



Zadatak 2. Opisati sve greške u sledećem C programu.

include <stdio.h>


define OFFSET 3;
define greska(msg) fprintf(stderr,#msg" %s\n",argv);
int length, width;
long area;


struct coord_p
{ int x,
int y }mypt


void f(void);

struct rectangle
{ coord_p topleft,
coord_p bottomrt } mybox

main(int argc, char argv**) {

if( argv = 3 ) /korektan broj argumenata /
{greska(Ne moze da se otvori)
exit(1)
} else
{ f();
}


return 3;
}


void f(void);
{boolean coord_test;
scanf("%d", mybox.topleft.x, mybox.topleft.y);
scanf("%d", mybox.bottomrt.x);

fscanf("%d", mybox.bottomrt.y);
coord_test=(bottomrt.x - topleft.x)*(bottomrt.y - topleft.y) > 0;
if (coord_test){ / izracunavanje duzine, visine i povrsine /
width = OFFSET+ bottomrt.x - topleft.x; length = OFFSET + bottomrt.y - topleft.y; Area = width * length;


printf("\nPovrsina je %l\n", area); }
}


Zadatak 3. Napisati program koji za dva polinoma stepena ne većeg od 20 unosi koeficijente (realni brojevi), a na standardni izlaz ispisuje:

    a) zbir ta dva polinoma
    b) vrednost oba polinoma u tački x, koja se zadaje kao argument komandne linije

Pretpostaviti da polinom je zadat strukturom

typedef struct polinom pol;
/*definicija polinoma - svaki polinom karakterisu stepen i koeficijenti */
struct polinom
{  int stepen;
   double koef[MAXEL];
};

Zadatak 4. Data je struktura

struct tacka{

int a;

int b;

char naziv[5];}

Ovom strukturom opisana je tacka sa koordinatama (a,b) u ravni kojoj je dodeljeno ima naziv. NCP koji ucitava dve tacke sa standardnog ulaza (ucitavaju se koordinate svake tacke i naziv) i ispisuje da li su date dve tacke jednake. Dve tacke su jednake ako su im iste obe koordinate.


Zadatak 5. Data je struktura

struct tacka{

int a;

int b;

char naziv[5];}

Ovom strukturom opisana je tacka sa koordinatama (a,b) u ravni kojoj je dodeljeno ima naziv. Napisati funkciju koja za dve promenljive tipa tacka kopira opis prve tacke u drugu promenljivu. NCP koji ucitava tacku sa standardnog ulaza (ucitavaju se koordinate tacke i naziv) i kopira je u drugu tacku.