Programiranje

Pascal: školski zadaci

mbaksa sri 8.12.2010 20:30
Plahi kaže...
mbaksa kaže...
Plahi kaže...
Ne pita me za izbor, nego sam nastavlja program. Gdje je greška? Vjerojatno negdje u poretku... Ili, kako bi vi riješili?

Zasto bi te pitao za unos vrijednosti u varijablu izbor? Oznaci u kodu naredbu u kojoj bi te trebao pitati za izbor! {#} Ne mozes? E pa to je zato sto je nisi napisao. Program radi samo ono sto mu ti napises da radi. Kako nisi napisao da te trazi unos varijable izbor, on to ni ne cini. Isto kao sto ti nece ispisati pi na deset decimala - zasto bi ti to ispisao, ako nisi zadao/napisao tu naredbu?

Kakvu naredbu da me pita? Nije dovoljno " until izbor='n'; " ?

Koju vrijednost ti drzi varijabla izbor (odgovorit cu ti to - drzi ti ASCII znak s rednim brojem 0 - zato jer nigdje nije definirana)? Gdje mijenjas njezinu vrijednost? Gdje korisnik u nju unosi vrijednost (slovo d ili n)? NIGDJE.

 

Kako onda until izbor='n'; moze biti dovoljno, kad je to isto kao da si napisao:

until Asc(0)='n';

ili

until 0=Ord('n');

 

Ni jedan od tih uvjeta NIKAD nece biti ispunjen jer usporedjujes u osnovi dvije konstante (ti varijablu izbor koristis prakticki kao konstantu), koje imaju razlicite vrijednosti.

 

 

E, da. Da bi ti stvar bila jasnija, pogledaj si gdje u programu i na koji nacin koristis "varijablu" izbor:

Program prvi;
var x,i:integer; superprost:boolean; izbor:char;
 begin
    repeat
    writeln('Upisi neki broj:');
     readln(x);
      superprost:=true;
   repeat
     for i:=2 to round(sqrt(x)) do
      if x mod i=0 then
       superprost:=false;
       x:=x div 10;
   until x=0;
     if superprost=true then
      writeln('Broj je superprost!')
     else
      writeln('Broj nije superprost!');
      writeln('Zelite li ponovno? d/n');
   until izbor='n';
    readln;
end.

 

Nigdje, ali bas nigdje nisi toj varijabli dodijelio vrijednost.

mbaksa sri 8.12.2010 20:42

Usporedi to s proslim svojim programom:

 

Program slucajni_odabir;
var x:integer;
   izbor:char;
 begin
   repeat
   writeln('Pritisnite enter za pocetak:');
   readln(izbor);
     if izbor='enter' then
     x:= random(29);
    writeln('Vas broj je: ',x);
    writeln('Zelite li jos jednom? d/n');
    readln(izbor);
 until izbor='n';
  readln;

end.

 

Tu si cak na dva mjesta trazio od korisnika unos vrijednosti u varijablu izbor.

mbaksa sri 8.12.2010 20:59

LOL naravno da ne postoji. Razmisli si kako bi do toga mogao doci. Meni na pamet nadaju dva nacina:

  • vrtis petlju sve dok x nije razlicit od recimo 50
  • napravis x:=random(99) i onda ako je x >= 50, onda ga uvecas za 1 (znaci, 50 postaje 51, 51 postaje 52, itd., a 99 postaje 100)
emerik uto 14.12.2010 17:19

Može mi netko riješiti problem?Treba napraviti program u kojem upisujemo mjesec i u proceduri računa koliko tekući ima dana i koliko slijedeći ima dana.Hvala.Koja mi je greška?

 

 

program dva;
var m,bd,nbd:integer;
procedure zovi(mj:integer; var b,nb:integer);
begin
begin
case mj of
1,3,5,7,8,10,12: b:=31;
2: b:=28;
4,6,9,11: b:=30;
end;
case mj+1 of
3,5,7,8,10: nb:=30;
2: nb:= 31;
12: nb:=31;
1: nb:=28;
4,6,9,11: nb:=31;
end;
begin

writeln('Upisi mjesec');
readln(m);
zovi(m,bd,nbd);
writeln('Ovaj mjesec ima ', bd ,' dana,a slijedeći mjesec ima ',nbd,' dana');
readln;

end.

mbaksa uto 14.12.2010 19:47

vidim da si posve promasio poantu proceduralnog programiranja. koristio si proceduru za bezveze. proceduru moras pozvati dvaput-jednom za mjesec, drugi put za mjesec+1. btw kaze se sljedeci, a ne slijedeci.

emerik uto 14.12.2010 20:09

Na zapovijed!!!{#}

 

program dva;

   var m,bd,nbd:integer;

   procedure zovi(mj:integer; var b,nb:integer);

    begin

    b:=0;

    nb:=0;

    case mj of

    1: begin

       b:=31;

       nb:=28;

      end;

    2: begin

       b:=28;

       nb:=30;

      end;

    3,5,8,10: begin

           b:=31;

           nb:=30;

         end;

    4,6,9,11: begin

           b:=30;

           nb:=31;

         end;

    7,12: begin

         b:=31;

         nb:=31;

       end;

    end;

    end;

 

begin

writeln('Upisi mjesec');

readln(m);

zovi(m,bd,nbd);

writeln('Ovaj mjesec ima ',bd,' dana ,a sljedeci ',nbd,' dana');

readln;

end.

mbaksa uto 14.12.2010 20:23

ne valja. procedura ti mora uzimati dva argumena (ili jos bolje, to bi trebala biti funkcija koja uzima jedan argument) i tu proceduru/funkciju iz glavnog programa trebas pozvati dvaput-za mjesec i mjesec+1.

ihush uto 14.12.2010 21:21
emerik kaže...

Razumijem ja tebe,ali nama je to u školi dovoljno.

 -ako misliš na ocjenu 2... nije ni to.

Smisao škole (i foruma) je da nešto naučir, razumiješ... u suprotnom prepiši na testu i nadaj se prolazu.

Profesor ti za prošli primjer nebi smio dati dvojku, ako ti i da... razmisli, dali će ti to pomoći 'sutra' kad to nećeš znati primjeniti u konkretnom problemu-poslu.

 

Procedura ti nevalja. Mora biti takva da za svaku ulaznu vrijednost (1-12) daje točan rezultat, u slučaju da tražiš idući mjesec +1 ili +3.., samo još treba 'prebacit brojač' ako premaši 12....

-ponovi (ili odustani).

emerik uto 14.12.2010 21:58

Gledajte,mi proceduru radimo 3 školska sata i profesor je rekao da ćemo pravi smisao procedure i funkcije dobiti kasnije u 3. razredu kada budemo to radili opširnije.Budem još probal kasnije.

EDIT:@iHush ,mislim da si krivo shvatio zadatak ,ne treba ispisati sljedeći mjesec nego koliko sljedeći mjesec ima dana.

mbaksa uto 14.12.2010 22:50
emerik kaže...

Gledajte,mi proceduru radimo 3 školska sata i profesor je rekao da ćemo pravi smisao procedure i funkcije dobiti kasnije u 3. razredu kada budemo to radili opširnije.

Evo me konacno na laptopu - prethodne odgovore sam kuckao na mobitelu. To sto cete vi tek nekad u buducnosti uciti pravi smisao procedura i funkcija, tebe ne sprecava da ti vec sad naucis neke stvari. Na kraju krajeva, ako ti je samo bitna zadaca, to si mogao prepisati od nekog kolege. A ja ovdje odgovaram ne da bi tebi napisao zadjacu, nego da tebe, ali i druge forumase koji prate ovu temu naucim neke stvari.

 

Bolje je ne uopce uciti nesto, nego uciti pogresno.  Procedure se, na nacin na koji si ih ti koristio, NIKAD ne koriste. Smisao procedura je da, ovisno o proslijedjenim parametrima, obave neku radnju. Za ovo tvoje zapravo su primjerenije funkcije, ali dobro... Tebi ta tvoja procedura uopce nema smisla - ona izgleda kao da si jednostavno dio koda iz glavnog programa reda radi odvojio u proceduru, a da ti ta procedura i dalje zapravo koristi varijable iz glavnog programa! Znaci, vizualno je odvojena, ali funkcionalno ne! To se tesko uopce moze smatrati procedurom. Da bi procedura imala smisla, treba biti tako koncipirana da je ima smisla pozvati vise od jednom. Tvoju nema. Program bi ti bio jednostavniji i smislediji da uopce nisi koristio proceduru, nego ovako kako si je koristio.

 

 

U tvom slucaju, smisao procedure trebao je biti racunanje koliko dana ima neki mjesec, koji je proslijedjen kao prvi argument. Procedura mora racunati broj dana iskljucivo za JEDAN mjesec. Zasto ne za dva? Zato jer onda radis gluposti - onda dvaput radis istu stvar i strasno kompliciras cijelu situaciju. Onda bi vise smisla imalo da imas jos jednu proceduru ili funkciju koja ce racunati broj dana za odredjeni mjesec, pa da ti ta tvoja procedura dvaput poziva ovu proceduru koja racuna broj dana.

 

 

Promotri ovaj kod:

 

program dva;
  procedure KolikoDana(Mjesec: Integer; var BrojDana: Integer);  begin    if Mjesec > 12 then Mjesec := (Mjesec - 1) mod 12 + 1;
    case Mjesec of      2: BrojDana := 28;      1, 3, 5, 7, 8, 10, 12: BrojDana := 31;      else BrojDana := 30;    end;end;

varMjesec, BrojDana: Integer;
begin  WriteLn('Upisi mjesec');  ReadLn(Mjesec);
  KolikoDana(Mjesec, BrojDana);  Write('Ovaj mjesec ima ', BrojDana);
  KolikoDana(Mjesec+1, BrojDana);  WriteLn(', a sljedeci ', BrojDana, ' dana.');
  ReadLn;end.
Meni se procedura ne zove zovi, nego KolikoDana. Vodi se za tim - imenuj nazive varijabli i procedura/funkcija tako da je svakome jasno cemu ta varijabla ili funkcija sluzi. Vidis sad na sto sam te pokusao navesti? Moja procedura racuna broj dana samo za jedan mjesec. Ali zato u glavnom programu dvaput trazim da mi izracuna broj dana - jednom za upisani mjesec, a drugi put za sljedeci mjesec (Mjesec + 1).

 

Razmisli si koja je razlika izmedju Mjeseca i Mjeseca + 1. NEMA RAZLIKE! Ako je korisnik upisao 1 za Mjesec, Mjesec + 1 iznosi 2. Znaci, u drugom slucaju trazi se racunanje Mjeseca = 2 - isto kao da je korisnik za Mjesec upisao 2! Kuzis sad?

 

I sad - ako bi htio znati koliko dana ima prek-sljedeci mjesec, sto moras napraviti? Moras samo pozvati proceduru s parametrom Mjesec + 2! Dakle:

KolikoDana(Mjesec+2, BrojDana);

 

Ako hoces prek-preksljedeci mjesec, trazis Mjesec+3. Itd. Proceduru uopce ne diras! A sto bi ti morao napraviti sa svojom procedurom ako bi trebao ispisati i broj dana za sljedeca dva mjeseca? Koji bi to kaos nastao!  {#}

 

ihush sri 15.12.2010 00:00
emerik kaže...

Gledajte,mi proceduru radimo 3 školska sata i profesor je rekao da ćemo pravi smisao procedure i funkcije dobiti kasnije u 3. razredu kada budemo to radili opširnije.Budem još probal kasnije.

EDIT:@iHush ,mislim da si krivo shvatio zadatak ,ne treba ispisati sljedeći mjesec nego koliko sljedeći mjesec ima dana.

- pokušavam te navesti da 'zagrizeš' u temu.. (ako si već tu na forumu, vjerojatno te zanima..)

- ne samo dati rješenje koje radi po sistemu čorava kokoš.

primjer, 2+2=4

neki broj + neki broj = neki broj

... ili x+y=z to je formula, zamisli proceduru. Jednom napravljena procedura je kalikulator, radi uvijek bez greške (dok se ne pokvari).

-Takva mora bit i tvoja procedura da bi dobila dovoljan. Za višu ocjenu, mora biti uredna, dokumentirana, imati nešto... itd.

mbaksa ti je dao konkretniji primjer, pa da dalje ne pametujem... -pročitaj. To je dobronamjerno.

mbaksa sri 15.12.2010 00:26

Imam jos jedno rjesenje za proceduru. Brutalno rjesenje.  {#}

 

procedure KolikoDana(Mjesec: Integer; var BrojDana: Integer);
const
  Dani : array [1..12] of Integer = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
begin
  BrojDana := Dani[(Mjesec - 1) mod 12 + 1];
end;

 

To je poanta procedure - uzima parametar i nesto s njim napravi. Drugaciji algoritam, isti rezultat. Isti ulaz uvijek mora dati isti izlaz. Stoga je onu proceduru KolikoDana koju sam prije napisao jednostavno moguce zamijeniti ovom.

mbaksa sri 15.12.2010 21:05
emerik kaže...

Puno hvala @mbaksa,sad sam skužio.A ovu drugu proceduru baš ne mogu shvatiti jer pretpostavljam da su ovo stringovi,a mi još nismo učili.

Nisu stringovi. Stringovi su tekst, npr:

 

'Ovo je string'

 

var

  varijabla: String;

 

U ovom slucaju varijabla je tipa String.

 

 

U ovoj drugoj proceduri u pitanju je polje (array) - konkretno, polje od 12 cijelih brojeva (Integera) - kao sto lijepo i pise u deklaraciji: array [1..12] of Integer.

emerik pet 14.1.2011 22:29

Imam jedan problem.Program bi trebao upisati noz od n elemenata i onda napraviti novi niz koji sadrži samo proste brojeve iz prvog niza.Zašto ne radi dobro?

 

 

program deveti;
   var x,y:array[1..20] of integer;
      i,n,j:integer;
      prost:boolean;
begin
writeln('Upisi n');
readln(n);
writeln('Upisi niz');
for i:=1 to n do
   readln(x[i]);
prost:=true;

if x[i]=1 then prost:=false;
for i:=1 to n do
   begin
      for j:=2 to (x[i]-1) do
        begin
         if x[i] mod j= 0 then
            prost:=false;
        end;
        if prost=true then
           begin
              y[i]:=x[i];
               write(y[i]);
            end;
    end;
readln;
end.

Joco55 pet 14.1.2011 22:41

Ovdije gdje ti provjerava je li x[i] djeliv sa j, tu ispot prost:=false stavi Break;

 

I još jedna preporuka, za performanse: U for j petlji koristi da ti je j pola od x[i] jer samo dotle ima smisla djeliti, dakle da to izgleda ovako:
for j:=2 to (x[i] / 2) do        begin         if x[i] mod j= 0 then            prost:=false;        end;

mbaksa pet 14.1.2011 22:42

A kako ti program radi? Imas nule u drugom nizu? To je zato jer si za drugi niz koristio isti iterator kao i za prvi, odnosno iskopirao si iz prvog niza sve proste brojeve, a oni koji nisu prosti postali su 0. Za drugi niz (y[]), koristi posebni brojac/iterator, kojeg ces uvecavati kod kopiranja brojeva iz polja x[].

 

 

BTW nemoj pisati uvjet:

  if prost=true then

 

jer ti se to, ako je prost true prevodi u

  if true=true then

odnosno ako je prost false:

  if false=true then

 

A to nema smisla, jer true=true je isto kao i true, a false=true je isto kao i false.

 

Dakle, pravilno je pisati jednostavno:

if prost then

 

  Ako provjeravas je li vrijednost varijable prost false, onda pises

  if not prost then

emerik sub 15.1.2011 09:58

Je sad dobro?

btw. ne znam zašto opcija stilovi-kod ne radi dobro.

 

program deveti;
    var n,i,j,br:integer;
    prost:boolean;
    x,y:array[1..20] of integer;
begin
writeln('Upisi n');
readln(n);
writeln('Upisi niz');
for i:=1 to n do
readln(x[i]);
br:=1;
for i:=1 to n do
begin
    if x[i]=1 then
          prost:=false
    else
          prost:=true;
    for j:=2 to round(sqrt(x[i])) do
          if x[i] mod j = 0 then prost:=false;
    if prost then
    begin
          y[br]:=x[i];
          br:=br+1;
    end;

end;

write('Novi niz je :');
for i:=1 to br-1 do
    write(y[i]:4);
readln;
end.

mbaksa sub 15.1.2011 13:16
emerik kaže...

Je sad dobro?

Zar ga nisi testirao? Reci ti nama jel radi dobro.

 

BTW jesi siguran da je dovoljno provjeravati dijeljivost do korijena od broja za koji provjeravamo djeljivost?  for j:=2 to round(sqrt(x[i])) do

To ti je rekao netko? Naime, Joco ti je spominjao polovicu od x[i], a ti si otisao na korijen. I sad sam probao uvrstiti korijen u svom programcicu i do 100000 daje iste rezultate i kao polovica i kao cijeli niz (umanjen za jedan). Zanimljivo... Zanimljivo kako to nije opce poznato...

 

Program se cini OK. Samo napravi jos jednu stvar:

    begin
          y[br]:=x[i];
          br:=br+1;
    end;

 

 

To promijeni da izgleda ovako:

    begin
          y[br]:=x[i];
          br:=br+1;
          break;
    end;

 

 

Zasto? Zato jer ti se u suprotnom unutarnja petlja vrti sve do sqrt(x[i]), a recimo za parne brojeve ti znas da to nisu prim brojevi vec u trenutku kad ih pokusas podijeliti s dva. Naredba  break;  prekida izvodjenje trenutne petlje (u ovom slucaju unutrasnje petlje). Znaci, cim je broj paran - puf, prekida se unutarnja petlja i ide se na kopiranje broja u drugi niz.

 

Zapravo, to mozes izmijeniti i da izgleda ovako, pa da bude u duhu Pascala:

    begin
          y[br]:=x[i];
          Inc(br);
          break;
    end;

 

Funkcija Inc je isto sto i operator ++ u C++-u - inkrementira (uvecava) broj za jedan. Fora kod funkcije Inc je da se prevodi u strojni ekvivalent - u strojnom jeziku postoji identicna naredba (INC), koja uvecava broj za jedan, dok kod naredbe  br:=br+1;  nisi siguran kako ce se prevesti - ako program prevodilac (compiler) nema odgovarajucu optimizaciju, on ce to prevesti kao zbrajanje (ADD) - sto je sporije (ako zbog niceg drugog, onda zato sto koristi dva operanda).

 

BTW ne znam zbog cega tebi editor nije dopustio koristenje stila za kod - probaj s drugim browserom. Ja sam uredio tvoju poruku i, kao sto vidis, nije bilo problema.

 

mbaksa sub 15.1.2011 13:31
emerik kaže...

EDIT:Kad stavim break onda ne radi program.Ovo za kod,ja koristim Firefox.

Sorry, moja greska, nisam gledao kamo sam ga stavio - na krivo mjesto.

 

Znaci imas:

 

for j:=2 to round(sqrt(x[i])) do
    if x[i] mod j = 0 then prost:=false;

 

Umjesto toga treba ici:

 

for j:=2 to round(sqrt(x[i])) do

    if x[i] mod j = 0 then

      begin

        prost:=false;

        break;

      end;


Znaci, tu premjesti break i onda ce raditi.

patch123 uto 18.1.2011 21:13

Ajmo ljudi pomagajte

 

Radim program u Pascalu i odmah na početku sam našao naišao na proble,

Izbaci mi da mi fali ':' ,tj. dvotočka

 

ovo je program,ja stvarno ne vidim gdje sam je trebao staviti

 

 

PROGRAM trokut;

VAR O,P,RO,RU,S:INTEGER;

BEGIN

WRITE('A=');READLN(A);

WRITE('B=');READLN(B);

WRITE('C=');READLN(C);

WRITELN('O=',A+B+C);

END.

 

emerik uto 18.1.2011 21:29

Sve je dobro,ali kakve varijable koristiš gore u nabrajanju,a kakve u programu.Moraju se isto zvati.Dodaj na kraj programa još jedan   readln;

EDIT:PIši malim slovima

 

 

 

PROGRAM trokut;VAR O,a,b,c:INTEGER;BEGINWRITE('A=');READLN(A);WRITE('B=');READLN(B);WRITE('C=');READLN(C);WRITELN('O=',A+B+C);

readln;

 END.