Pascal: školski zadaci
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.
Da li postoji naradba da bi se npr izuzeo neki broj kod randomiziranja.
NPR:
x:=random(100);
Ali ne želim da IKAD generira recimo 50.
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)
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.
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.
OK.Hvala.
Posalji rjesenje kad zavrsis.
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.
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.
Ali program radi.
ali kojeg ti tu smisla ima koristenje procedure? onda si to mogao rijesiti i bez procedure. ajde prosiri program i za mjesec+2 - pa ce ti onda mozda biti jasnije u cemu je problem.
Razumijem ja tebe,ali nama je to u školi dovoljno.
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).
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.
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!
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.
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.
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.
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.
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.
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;
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
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.
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.
Hvala,nisam znao za naredbu INC.
A,ovo da se mora provjeravati do korijena smo učili iz matematike u 1. razredu srednje.
EDIT:Kad stavim break onda ne radi program.Ovo za kod,ja koristim Firefox.
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.
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.
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.
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.