Pereiti prie turinio

Pascal:nesuprantama problema


Rekomenduojami pranešimai

Sveiki!Visu pirmiausia visus su sventem! :) Taigi problema yra tokia, kad man vienoje eiluteje meta klaida "illegal qualifier" ir nezinau kaip ja istaisyti.As tiesiog laisvu metu biski paprogramuoju, uzduotis tokia:

Studentų matematikos pažymiai surašyti į tekstinį failą Duomenys.txt. Pirmoje failo eilutėje yra nurodyti: studentų skaičius ir balas reikalingas stipendijai gauti. Kitose eilutėse surašyti studentų vardai, pavardės bei gauti pažymiai. Parašykite programą, kuri rzeultato faile Rezultatas.txt:

a) Atspausdintų dar kartą visus studentus ir jų pažymius;

b) Suskaičiuotų ir atspausdintų studentų vardus ir pavardes, ir jų vidurkius

c) Suskaičiuotų kiek mokinių gaus stipendiją ir parodytų jų vardus bei pavardes

 

O mano kodas toks(ten kur klaida parasiau komentara):

program stipendija;

type klas=record
vard:string[12];
pavard:string[12];
paz,paz1,paz2,paz3,paz4:real;
end;

type masyvas=array[1..50] of klas;

type masyv=array[1..50] of real;

type mas=array[1..50] of real;

var skaic,bal:integer;
A:masyvas;
vid:masyv;
sum:mas;

Df,Rf:text;

procedure duomenys;
var i:integer;
begin
   Assign(Df,'duom.txt');
   Reset(Df);
   Readln(Df,skaic,bal);
   for i:=1 to skaic do
   Readln(Df,A[i].vard,A[i].pavard,A[i].paz,A[i].paz1,A[i].paz2,A[i].paz3,A[i].paz4);
   Close(Df);
end;

function vidurkis:real;
var i,n,a:integer;
begin
   a:=0;
   n:=0;
   for i:=1 to skaic do
   begin
       sum[a+1]:=A[(//sitoje vietoje klaida-illegal qualifier)i].paz+A[i].paz1+A[i].paz2+A[i].paz3+A[i].paz4;
       vid[n+1]:=sum[a]/5;
   end;
vidurkis:=vid[1];
end;

procedure stipendija;
var n:integer;
begin
   for n:=1 to skaic;
   begin
       if vid[n]>bal then writeln(Rf,A[n].vard,' ',A[n].pavard,' ',vid[n]);
   end;
end;

begin
Assign(Rf,'rez.txt');
Rewrite(Rf);
for i:=1 to skaic do
Writeln(Rf,A[i].vard,A[i].pavard,A[i].paz,A[i].paz1,A[i].paz2,A[i].paz3,A[i].paz4);
for i:=1 to skaic do
Writeln(Rf,A[i].vard,' ',A[i].pavard,' ',vid[i]);
Writeln(Rf,stipendija);
Close(Rf);
end.

 

Aciu kas pades! :)

Redagavo RealEfect
Nuoroda į pranešimą
Dalintis kituose puslapiuose

Cia paskalis, kuriam dzin yra ar didzioji, ar mazoji raide. Pas tave yra globalus masyvas "A", ir lokalus sveikas skaicius "a". Kadangi lokalus turi pirmenybe pries globalus, tai sveikam skaiciui negali taikyt masyvo lauztiniu skliaustu. Pradek kintamuosius vadinti zmoniskais vardais, ir tokiu problemu neliks.

 

EDIT: ir siaip globalus kintamieji yra didelis blogis, nebent kitaip neimanoma isspresti.

Redagavo dEVooX
Nuoroda į pranešimą
Dalintis kituose puslapiuose

Na šiaip programoje daug kas blogai. Tai pavardinkime kas:

1. string[12], 1..50 tose vietose, kur aprašinėjamas tipas. O jeigu staiga prireiks vardo ir pavardės ne 12 simbolių ilgio, o, pavyzdžiui, 20? Kas tada? Reikės keisti visą programą, kad būtų galima naudoti 20-ies simbolių vardus ir pavardes? Bet tokiu atveju juk galima pridaryti klaidų. Kur kas geriau būtų naudoti konstantą, kuria aprašomas tas ilgis, pavyzdžiui:

const max_ilgis = 12;

cons max_index = 50;

Tas pats taikytina ir failų pavadinimams. Taip pat keistas sprendimas man pasirodė pažymius saugoti real tipo kintamuosiuose. Kokia prasmė? Ar čia vertinimo sistema tokia, kad studentas gali vieną iš keturių pažymių gauti ir 8.5, 9.7 ir pan.? Na bet ne esmė - laikysiu, kad pažymiu gali būti tik sveikasis skaičius. Jei netiks, galėsi pasikeisti. :)

 

Toliau pažiūrėkime į tavo pačios programos klaidą:

sum[a+1]:=A.paz + A.paz1 + A.paz2 + A.paz3 + A.paz4;

Na iš šios eilutės galima suprasti tai, kad naudojami kintamieji a ir A, kurie pagal Pascal leksiką yra iš esmės vienodi. Tai išeitų toks paradoksas: A yra globalus masyvas, a - lokalus sveikasis skaičius. Kurį tipą rinktis kompiliatoriui, jeigu jis neranda skirtumo tarp a ir A? Neaišku... Tai pakeiskime a į b, pavyzdžiui. Toliau bus dar viena klaida:

program stipendija;

<...>

procedure stipendija;

Argi taip galima?

Dar toliau: for n:=1 to skaic; - irgi "gražu". Tada dar bus klaida, jog "Identifier not found I", jei naudosi Free Pascal, arba kitoks tekstas, kuris išreikš tą pačią klaidą - kintamojo panaudojimą prieš apibrėžimą. Na gerai, apibrėžiame klaidą. Po to išeina paradoksas, kad kintamasis stipendija naudojamas įrašyme. Neaišku, kam skirtas, iš kur jis atsirado. Aišku nebent tai, kad net ir, jei apibrėžtume tokį, jo naudoti nebūtų galima, nes jau programos pavadinimas toks. Na pamėginau ir tai pataisyti - programa dėl neaiškių priežasčių vis tiek neveikė. Geriau pasinagrinėk veikiančios programos pavyzdį. :)

 

program stipendija;

const max_ilgis = 12;
const max_indeksas = 50;
const duom_file = 'duom.txt';
const rez_file = 'rez.txt';

type stud = record
                     vard: string[max_ilgis];
                   pavard: string[max_ilgis];
           P1, P2, P3, P4: integer;
end;

type stud2 = record
                     vard: string[max_ilgis];
                   pavard: string[max_ilgis];
                 vidurkis: real;
end;

type stud_mas = array [1..max_indeksas] of stud;
type stud_mas2 = array [1..max_indeksas] of stud2;

procedure SkaitytiDuomenis (var S: stud_mas; var masyvo_ilgis, studentai: integer; var reikalingas_vidurkis: real);
var
   failas: text;
   indeksas: integer;
   duomenys: stud;
begin
   Assign(failas,duom_file);
   {$I-}
   Reset(failas);
   {$I+}
   if IOResult <> 0 then WriteLn('Klaida nuskaitant duomenis. Failas ',duom_file,' neegzistuoja arba negalima jo atidaryti')
   else
   begin
       indeksas := 1;
       ReadLn(failas,studentai,reikalingas_vidurkis);
       while not eof(failas) do
       begin
           ReadLn(failas,duomenys.vard,duomenys.pavard,duomenys.P1,duomenys.P2,duomenys.P3,duomenys.P4);
           S[indeksas] := duomenys;
           Inc(indeksas);
       end;
   end;
   masyvo_ilgis := indeksas-1;
   Close(failas);
end;

procedure AnalizuotiDuomenis (S: stud_mas; masyvo_ilgis: integer; reikalingas_vidurkis: real; var S_return: stud_mas2; var masyvo_ilgis_return: integer);
var
   indeksas, i: integer;
   duomenys: stud2;
   vid: real;
begin
   indeksas := 1;
   for i := 1 to masyvo_ilgis do
   begin
       with S[i] do
           vid := (P1+P2+P3+P4)/4;
       if vid >= reikalingas_vidurkis then
       begin
           with S_return[indeksas] do
           begin
               vard := S[i].vard;
               pavard := S[i].pavard;
               vidurkis := vid;
           end;
           Inc(indeksas);
       end;
   end;
   masyvo_ilgis_return := indeksas-1;
   for i := 1 to masyvo_ilgis do
   begin
       with S[i] do
       vid := (P1+P2+P3+P4)/4;
       with S_return[indeksas] do
       begin
           vard := S[i].vard;
           pavard := S[i].pavard;
           vidurkis := vid;
       end;
       Inc(indeksas);
   end;
end;

procedure SaugotiDuomenis (S: stud_mas; S2: stud_mas2; nuo, iki: integer);
var
   failas: text;
   indeksas, i: integer;
   duomenys: stud;
begin
   Assign(failas,rez_file);
   {$I-}
   Rewrite(failas);
   {$I+}
   if IOResult <> 0 then WriteLn('Klaida irasant duomenis. Failas ',rez_file,' neegzistuoja arba negalima jo atidaryti')
   else
   begin
       for i := 1 to iki do
       begin
           with S[i] do
               Write(failas,vard,pavard,P1,' ',P2,' ',P3,' ',P4);
           WriteLn(failas);
       end;
       for i := nuo+1 to iki+nuo do
       begin
           with S2[i] do
               Write(failas,vard,pavard,vidurkis:0:2);
           WriteLn(failas);
       end;
       WriteLn(failas);
       WriteLn(failas,'Stipendija gaus tiek studentu: ',nuo);
       WriteLn(failas);
       WriteLn(failas,'Stipendija gausiantys studentai');
       for i := 1 to nuo do
       begin
           with S2[i] do
               Write(failas,vard,pavard,vidurkis:0:2);
           WriteLn(failas);
       end;
   end;
   Close(failas);
end;

var S: stud_mas;
   S2: stud_mas2;
   ilgis, ilgis2, i, studentai: integer;
   reikalingas_vidurkis: real;

begin
   SkaitytiDuomenis(S,ilgis,studentai,reikalingas_vidurkis);
   AnalizuotiDuomenis(S,ilgis,reikalingas_vidurkis,S2,ilgis2);
   SaugotiDuomenis(S,S2,ilgis2,ilgis);
end.

 

Pavyzdinis failas duom.txt programai:

5 6.5
Antanas     Pranaitis   9 8 7 4
Antanas     Jonaitis    10 10 10 10
Jonas       Pranaitis   7 7 7 7
Antanas     Antanaitis  7 6 5 4
Jokubas     Sudaitis    8 8 8 9

 

Po įvykdytos programos gautum tokį rezultatą:

Antanas     Pranaitis   9 8 7 4
Antanas     Jonaitis    10 10 10 10
Jonas       Pranaitis   7 7 7 7
Antanas     Antanaitis  7 6 5 4
Jokubas     Sudaitis    8 8 8 9
Antanas     Pranaitis   7.00
Antanas     Jonaitis    10.00
Jonas       Pranaitis   7.00
Antanas     Antanaitis  5.50
Jokubas     Sudaitis    8.25

Stipendija gaus tiek studentu: 4

Stipendija gausiantys studentai
Antanas     Pranaitis   7.00
Antanas     Jonaitis    10.00
Jonas       Pranaitis   7.00
Jokubas     Sudaitis    8.25

Redagavo topsas
Nuoroda į pranešimą
Dalintis kituose puslapiuose

Na šiaip programoje daug kas blogai. Tai pavardinkime kas:

1. string[12], 1..50 tose vietose, kur aprašinėjamas tipas. O jeigu staiga prireiks vardo ir pavardės ne 12 simbolių ilgio, o, pavyzdžiui, 20? Kas tada? Reikės keisti visą programą, kad būtų galima naudoti 20-ies simbolių vardus ir pavardes? Bet tokiu atveju juk galima pridaryti klaidų. Kur kas geriau būtų naudoti konstantą, kuria aprašomas tas ilgis, pavyzdžiui:

const max_ilgis = 12;

cons max_index = 50;

Tas pats taikytina ir failų pavadinimams. Taip pat keistas sprendimas man pasirodė pažymius saugoti real tipo kintamuosiuose. Kokia prasmė? Ar čia vertinimo sistema tokia, kad studentas gali vieną iš keturių pažymių gauti ir 8.5, 9.7 ir pan.? Na bet ne esmė - laikysiu, kad pažymiu gali būti tik sveikasis skaičius. Jei netiks, galėsi pasikeisti. :)

 

Toliau pažiūrėkime į tavo pačios programos klaidą:

sum[a+1]:=A.paz + A.paz1 + A.paz2 + A.paz3 + A.paz4;

Na iš šios eilutės galima suprasti tai, kad naudojami kintamieji a ir A, kurie pagal Pascal leksiką yra iš esmės vienodi. Tai išeitų toks paradoksas: A yra globalus masyvas, a - lokalus sveikasis skaičius. Kurį tipą rinktis kompiliatoriui, jeigu jis neranda skirtumo tarp a ir A? Neaišku... Tai pakeiskime a į b, pavyzdžiui. Toliau bus dar viena klaida:

program stipendija;

<...>

procedure stipendija;

Argi taip galima?

Dar toliau: for n:=1 to skaic; - irgi "gražu". Tada dar bus klaida, jog "Identifier not found I", jei naudosi Free Pascal, arba kitoks tekstas, kuris išreikš tą pačią klaidą - kintamojo panaudojimą prieš apibrėžimą. Na gerai, apibrėžiame klaidą. Po to išeina paradoksas, kad kintamasis stipendija naudojamas įrašyme. Neaišku, kam skirtas, iš kur jis atsirado. Aišku nebent tai, kad net ir, jei apibrėžtume tokį, jo naudoti nebūtų galima, nes jau programos pavadinimas toks. Na pamėginau ir tai pataisyti - programa dėl neaiškių priežasčių vis tiek neveikė. Geriau pasinagrinėk veikiančios programos pavyzdį. :)

 

program stipendija;

const max_ilgis = 12;
const max_indeksas = 50;
const duom_file = 'duom.txt';
const rez_file = 'rez.txt';

type stud = record
                     vard: string[max_ilgis];
                   pavard: string[max_ilgis];
           P1, P2, P3, P4: integer;
end;

type stud2 = record
                     vard: string[max_ilgis];
                   pavard: string[max_ilgis];
                 vidurkis: real;
end;

type stud_mas = array [1..max_indeksas] of stud;
type stud_mas2 = array [1..max_indeksas] of stud2;

procedure SkaitytiDuomenis (var S: stud_mas; var masyvo_ilgis, studentai: integer; var reikalingas_vidurkis: real);
var
   failas: text;
   indeksas: integer;
   duomenys: stud;
begin
   Assign(failas,duom_file);
   {$I-}
   Reset(failas);
   {$I+}
   if IOResult <> 0 then WriteLn('Klaida nuskaitant duomenis. Failas ',duom_file,' neegzistuoja arba negalima jo atidaryti')
   else
   begin
       indeksas := 1;
       ReadLn(failas,studentai,reikalingas_vidurkis);
       while not eof(failas) do
       begin
           ReadLn(failas,duomenys.vard,duomenys.pavard,duomenys.P1,duomenys.P2,duomenys.P3,duomenys.P4);
           S[indeksas] := duomenys;
           Inc(indeksas);
       end;
   end;
   masyvo_ilgis := indeksas-1;
   Close(failas);
end;

procedure AnalizuotiDuomenis (S: stud_mas; masyvo_ilgis: integer; reikalingas_vidurkis: real; var S_return: stud_mas2; var masyvo_ilgis_return: integer);
var
   indeksas, i: integer;
   duomenys: stud2;
   vid: real;
begin
   indeksas := 1;
   for i := 1 to masyvo_ilgis do
   begin
       with S[i] do
           vid := (P1+P2+P3+P4)/4;
       if vid >= reikalingas_vidurkis then
       begin
           with S_return[indeksas] do
           begin
               vard := S[i].vard;
               pavard := S[i].pavard;
               vidurkis := vid;
           end;
           Inc(indeksas);
       end;
   end;
   masyvo_ilgis_return := indeksas-1;
   for i := 1 to masyvo_ilgis do
   begin
       with S[i] do
       vid := (P1+P2+P3+P4)/4;
       with S_return[indeksas] do
       begin
           vard := S[i].vard;
           pavard := S[i].pavard;
           vidurkis := vid;
       end;
       Inc(indeksas);
   end;
end;

procedure SaugotiDuomenis (S: stud_mas; S2: stud_mas2; nuo, iki: integer);
var
   failas: text;
   indeksas, i: integer;
   duomenys: stud;
begin
   Assign(failas,rez_file);
   {$I-}
   Rewrite(failas);
   {$I+}
   if IOResult <> 0 then WriteLn('Klaida irasant duomenis. Failas ',rez_file,' neegzistuoja arba negalima jo atidaryti')
   else
   begin
       for i := 1 to iki do
       begin
           with S[i] do
               Write(failas,vard,pavard,P1,' ',P2,' ',P3,' ',P4);
           WriteLn(failas);
       end;
       for i := nuo+1 to iki+nuo do
       begin
           with S2[i] do
               Write(failas,vard,pavard,vidurkis:0:2);
           WriteLn(failas);
       end;
       WriteLn(failas);
       WriteLn(failas,'Stipendija gaus tiek studentu: ',nuo);
       WriteLn(failas);
       WriteLn(failas,'Stipendija gausiantys studentai');
       for i := 1 to nuo do
       begin
           with S2[i] do
               Write(failas,vard,pavard,vidurkis:0:2);
           WriteLn(failas);
       end;
   end;
   Close(failas);
end;

var S: stud_mas;
   S2: stud_mas2;
   ilgis, ilgis2, i, studentai: integer;
   reikalingas_vidurkis: real;

begin
   SkaitytiDuomenis(S,ilgis,studentai,reikalingas_vidurkis);
   AnalizuotiDuomenis(S,ilgis,reikalingas_vidurkis,S2,ilgis2);
   SaugotiDuomenis(S,S2,ilgis2,ilgis);
end.

 

Pavyzdinis failas duom.txt programai:

5 6.5
Antanas     Pranaitis   9 8 7 4
Antanas     Jonaitis    10 10 10 10
Jonas       Pranaitis   7 7 7 7
Antanas     Antanaitis  7 6 5 4
Jokubas     Sudaitis    8 8 8 9

 

Po įvykdytos programos gautum tokį rezultatą:

Antanas     Pranaitis   9 8 7 4
Antanas     Jonaitis    10 10 10 10
Jonas       Pranaitis   7 7 7 7
Antanas     Antanaitis  7 6 5 4
Jokubas     Sudaitis    8 8 8 9
Antanas     Pranaitis   7.00
Antanas     Jonaitis    10.00
Jonas       Pranaitis   7.00
Antanas     Antanaitis  5.50
Jokubas     Sudaitis    8.25

Stipendija gaus tiek studentu: 4

Stipendija gausiantys studentai
Antanas     Pranaitis   7.00
Antanas     Jonaitis    10.00
Jonas       Pranaitis   7.00
Jokubas     Sudaitis    8.25

 

Sveikas, is tavo kodo daug kas neaisku, man butu geriau, kad veiktu pagal mano varianta, nes pas tave paprasciausiai daug neaiskiu komandu, kuriu as nemoku, nors mokykloje pascal mokausi jau ~2 metai...Pavyzdziui tokie kaip "{$I-}" arba "IOResult <> 0" arba "for i := 1 to iki do"(kaip galima rasyti iki, jeigu pascaliui neaisku, kas tas iki? :D), arba " while not eof","Inc(indeksas)","masyvo_ilgis_return := indeksas-1;","with S2 do".Zodziu visos sios komandos man yra neaiskios, bet as pataisiau savo ankstesni, paprastesni varianta ir dabar meta klaida,kad blogas skaiciaus formatas, tik nezinia kur:

program uzduotele;

type klas=record
vard:string[12];
pavard:string[12];
paz,paz1,paz2,paz3,paz4:real;
end;

type masyvas=array[1..50] of klas;

type masyv=array[1..50] of real;

type mas=array[1..50] of real;

var skaic,bal:integer;
A:masyvas;
vid:masyv;
sum:mas;
n,i:integer;

Df,Rf:text;

procedure duomenys;
begin
   Assign(Df,'duom.txt');
   Reset(Df);
   Readln(Df,skaic,bal);
   for i:=1 to skaic do
   Readln(Df,A[i].vard,A[i].pavard,A[i].paz,A[i].paz1,A[i].paz2,A[i].paz3,A[i].paz4);
   Close(Df);
end;

function vidurkis:real;
var i,n,b:integer;
begin
   b:=0;
   n:=0;
   for i:=1 to skaic do
   begin
       sum[b+1]:=A[i].paz+A[i].paz1+A[i].paz2+A[i].paz3+A[i].paz4;
       vid[n+1]:=sum[b]/5;
   end;
vidurkis:=vid[1];
end;

procedure stipendija1;
var n:integer;
begin
   for n:=1 to skaic do
   begin
       if vid[n]>bal then writeln(Rf,A[n].vard,' ',A[n].pavard,' ',vid[n]);
   end;
end;

begin
duomenys;
vidurkis;
Assign(Rf,'rez.txt');
Rewrite(Rf);
for i:=1 to skaic do
Writeln(Rf,A[i].vard,A[i].pavard,A[i].paz,A[i].paz1,A[i].paz2,A[i].paz3,A[i].paz4);
for i:=1 to skaic do
Writeln(Rf,A[i].vard,' ',A[i].pavard,' ',vid[i]);
stipendija1;
Close(Rf);
end.

Gal zinai, zinote kas galetu buti negerai, labai buciau dekingas, kas paaiskintu. :)

Redagavo RealEfect
Nuoroda į pranešimą
Dalintis kituose puslapiuose

http://wiki.mifsa.lt/Informatika_%28program%C5%B3_sistemos%29/Byl%C5%B3_skaitymas_ir_ra%C5%A1ymas_su_IO_tikrinimu

 

Kaip tai neaišku kas tas 'iki'? 'procedure SaugotiDuomenis (S: stud_mas; S2: stud_mas2; nuo, iki: integer);'

http://www.taoyue.com/tutorials/pascal/pas2e.html

http://www.gnu-pascal.de/gpc/Inc.html

 

Nejaugi taip sunku pasigooglinti?

Nuoroda į pranešimą
Dalintis kituose puslapiuose

Prisijunkite prie diskusijos

Jūs galite rašyti dabar, o registruotis vėliau. Jeigu turite paskyrą, prisijunkite dabar, kad rašytumėte iš savo paskyros.

Svečias
Parašykite atsakymą...

×   Įdėta kaip raiškusis tekstas.   Atkurti formatavimą

  Only 75 emoji are allowed.

×   Nuorodos turinys įdėtas automatiškai.   Rodyti kaip įprastą nuorodą

×   Jūsų anksčiau įrašytas turinys buvo atkurtas.   Išvalyti redaktorių

×   You cannot paste images directly. Upload or insert images from URL.

Įkraunama...
  • Dabar naršo   0 narių

    Nei vienas registruotas narys šiuo metu nežiūri šio puslapio.

×
×
  • Pasirinkite naujai kuriamo turinio tipą...