PASCAL jako mały "pomocnik"
13.02.2012 16:50
Witajcie. Nie jestem programistą, żadnych zawodowcem czy ekspertem, staram się czegoś nauczyć, bo kto wie kiedy mi się to może przydać. Ale o czym będzie wpis?
Mianowicie ostatnio napisał do mnie kolega, ze jego syn dostał dość prostą, lecz żmudną prace domową. Mianowicie w zadaniu dane było kilkanaście ciągów i należało:
- policzyć sumę elementów ciągu i ich iloczyn
- posortować ciąg rosnąco i malejąco
- podać skrajne elementu ciągu
- obliczyć średnią arytmetyczną elementów ciągu
- podać ilość elementów ciągu
- podać największy element ciągu i jego położenie
Jako, że przykładów w zadaniu było sporo spytał mnie czy nie da się tego "uprościć" w arkuszu kalkulacyjnym czy w inny sposób. Pomyślałem o Pascalu. No więc mają założenia postanowiłem coś naskrobać. Oczywiście z pewnością nie jest to ekstra, bezbłędny i pozbawiony wad kod, ale nie był pisany na dłuższa metę. Co ważne działa, pomógł i po krotce powinien wyjaśnić co i jak – może się komuś przyda.
Co trzeba zrobić
Założyłem, że elementy ciągu będą umieszczone w tablicy jednowymiarowej. Jako, że nie są to zaawansowane rzeczy tablica ma maksymalnie 100 pozycji. No więc trzeba to zadeklarować: Nie zapominamy o słowie Program i nazwie programu na początku:
Program zadania; const max=100; type tablica=array[1..max]of longint;
No dobrze. Znając założenia wiem, ze będę potrzebował policzyć: sumę, iloczyn, ilość liczb, średnią arytmetyczną,posortować ciąg rosnąco i malejąco oraz znaleźć i podać miejsce i wartość elementu maksymalnego. Żeby się nie pogubić postanowiłem dla każdej z tych czynności napisać procedurę. No to pograj muzyko..
Ekhem.. zapomniałbym, przecież wpierw musimy naszej liczby wprowadzić.
procedure wypisz; begin for b:=1 to ilosc_liczb do write(t<b>,', '); writeln; end
Wprowadzenie danych
procedure wprowadz; begin for b:=1 to ilosc_liczb do begin write('a',b,' = '); readln(t<b>); end; end;
Jak widać zmienna sterująca pętla jest zmienna "b". Zmienna "ilosc_liczb" jest zmienną przechowująca ilość liczb w ciągu, wprowadza ją użytkownik.
Wypisanie wprowadzonych liczb
Aby sprawdzić czy dobrze wprowadziliśmy ciąg, warto go wyświetlić dla użytkownika
procedure wypisz; begin for b:=1 to ilosc_liczb do write(t<b>,', '); writeln; end;
Ponownie pętla for lecz tym razem wypisująca liczby podane przez uzytkownika, czyli nasz ciąg.
Suma elementów
Jako, że trzeba policzyć sume elementów..
procedure suma; var suma:longint; begin suma:=0; for b:=1 to ilosc_liczb do suma:=suma+t<b>; writeln('Suma elementów ciągu to: ',suma); end;
Na początku zakładamy, że nasza suma równa jest 0 (bo przecież tak jest). Sumę zapiszemy do zmiennej o tej samej nazwie, zmiennej "suma". Analizując fragment tego kodu widać, że jest to odwołanie do samej siebie i dodanie kolejnego elementu ciągu aż do elementu ostatniego "ilosc_liczb".
Średnia arytmetyczna
Skoro mamy już sumę, zajmijmy się średnią. Jest to odrobinę zmodyfikowana procedura sumy
procedure srednia; var suma:longint; srednia:real; begin suma:=0; for b:=1 to ilosc_liczb do suma:=suma+t<b>; srednia:=suma/ilosc_liczb; writeln('Średnia arytmetyczna wprowadzonych liczb to: ',srednia:3); end;
Nie jest to mocno skomplikowane, po prostu podzieliliśmy sumę przez ilość wprwadzonych liczb - odpowiednio zmienne "suma" i "ilosc_liczb".
Iloczyn elementów
procedure iloczyn; var iloczyn:longint; begin iloczyn:=1; for b:=1 to ilosc_liczb do iloczyn:=iloczyn*t<b>; writeln('Iloczyn elementów ciągu to: ',iloczyn); end;
Nasz iloczyn na początku nie może być rowny 0, gdyż wiadomo że cokolwiek pomnożone przez 0 daje 0, więc nasz pierwszy iloczyn jest liczbą równą 1. Nastepnie postępujemy analogicznie jak przy sumie, odwołując się do poprzedniego iloczynu.
Element największy
procedure najwiekszy_element; begin i_max:=1; max_el:=t[i_max]; for b:=1 to ilosc_liczb do if t<b>>max_el then begin i_max:=b; max_el:=t[i_max]; end; writeln('Element największy to: ',max_el,' a jego położenie to: a',i_max); end;
Na początku przyjmujemy, że naszym największym elementem jest element 1 – by mieć do czego sie odwołac. "i_max" oznacza maksymalne położenie (indeks) elementu maksymalnego a "max_el" oznacza wartość tego elementu. Instrukcja if zawarta w pętli for (tak by przejrzeć wszystkie elementy) sprawdza czy jakiś element jest większy od 1, jeżeli tak, podmienia zmienną "i_max" na połozenie nowego największego elementu czyniąc to samo z jego wartością, czyli zmienną "max_el"
Sortowanie
procedure sortowanie; begin zamiana:=true; while zamiana do begin zamiana:=false; for b:=1 to ilosc_liczb-1 do if t<b>>t[b+1] then begin pom:=t<b>; t<b>:=t[b+1]; t[b+1]:=pom; zamiana:=true; end; end; end;
W sortowaniu użylem algorytmu sortowania babelkowego, polegającego na porównywaniu kolejno par liczb. Zmienna "zamiana" sprawdza czy w ciągu została dokonana jakaś zamiana, bo przecież liczby mogły być ustawione w odpowiedniej kolejności – rosnąco. Dlaczego pierwsza zamiana ma wartośc true? Otóz dlatego, by dostać się do pętli while, po dostaniu się do pętli while uznajemy, ze ciąg jest ustawiony odpowiednio. iloscliczb-1, dlaczego mniej jeden? Otóż dlatego, iż par jest o 1 mniej od ilości liczb w ciągu. Mając na przykład ciąg 1, 2, 3, 4 mamy następujące pary: 12, 23, 34, czyli ilosc_liczb-1. Instrukcja warunkowa if sprawdza czy element i jest większy od elementu po nim nastepującym, jeżeli tak – zamienia je miejscami (do tego celu potrzebna jest zmienna "pom"). Jeżeli wystąpiła choć jedna zamiana zmienna zamiana przyjmuje wartość true i proces się powtarza, az ciąg będzie ustawiony w kolejności rosnącej.
No dobrze, a jak zrobić żeby było odwrotnie? Otóz nie musimy pisać oddzielnej procedury dla sortowania ciągu, Po prostu jeżli mamy ciąg w kolejności rosnącej, wypisany odwrotnie da kolejnośc malejącą, skorzystamy z tego pisząc procedurę wypisywania liczb w odwrotnej kolejności
procedure wypisz_odwrotnie; begin for b:=ilosc_liczb downto 1 do write(t<b>,', '); writeln; end;
Niech zabłysną gwiazdki
By tekst się nie zlewał po wyświetleniu postanowiłem upakować to w jakby to ująć "boxy" . Tytuły boxów maja wyglądać nastepująco:
****************************************************** TYTUŁ ******************************************************
procedure gwiazdki (znak:char;slowo:string;ile:byte); begin writeln; for b:=1 to ile do write(znak); writeln; writeln(slowo); for b:=1 to ile do write(znak); writeln; writeln; end;
znak:char;slowo:string;ile:byte to parametry formalne procedury. Pierwszy określa jaki znak będzie oddzielał zawartośc (w przykładzie "*"), drugi podaje tytuł boxu, natomiast trzeci długośc zmiennej znak.
Po zakończeniu psania procedur warto przejrzeć listę zmiennych, tutaj nie były jeszcze deklarowane. Zróbmy to:
var ilosc_liczb,b:integer; t:tablica; zamiana:boolean; pom,max_el,i_max:integer;
Co dalej?
Mając procedury zabierzmy się do napisania "ciała" programu. Rozpoczynamy od słowa begin
begin repeat Write('Podaj ilość liczb jaką chcesz wpisać '); readln(ilosc_liczb); until (ilosc_liczb>0);
Repeat sprawdza, czy nie podaliśmy przypadkiem jako ilości liczb w ciągu liczby ujemnej.
Wywołujemy zmienne:
wprowadz; writeln;
Po wprowadzeniu przez użytkownika liczb program wykona resztę pracy za nas:
gwiazdki('*','STATYSTYKA',45);
Pierwszy parater przy wywoływaniu procedur gwiazdki zostaje "podstawiony" za zmienną "znak", drugi za zmienną "slowo", a trzeci za zmienną "ile" w parametrach formalnych procedury "gwiazdki".
writeln('Twój ciąg liczb to: '); wypisz; writeln('Ilosc liczb w ciągu: ',ilosc_liczb); writeln('Elementy skarjne ciągu to: ',t[1],' oraz ',t[ilosc_liczb]); najwiekszy_element; sortowanie; writeln('Liczby jakie podałeś w kolejności rosnącej to: '); wypisz; writeln('Liczby jakie podałeś w kolejności malejącej to: '); wypisz_odwrotnie; gwiazdki('*','OBLICZENIA',45); srednia; suma; iloczyn; writeln; readln; end.
Cały kod programu wygląda tak:
Program zadania; const max=100; type tablica=array[1..max]of longint; var ilosc_liczb,b:integer; t:tablica; zamiana:boolean; pom,max_el,i_max:integer; procedure wprowadz; begin for b:=1 to ilosc_liczb do begin write('a',b,' = '); readln(t<b>); end; end; procedure wypisz; begin for b:=1 to ilosc_liczb do write(t<b>,', '); writeln; end; procedure wypisz_odwrotnie; begin for b:=ilosc_liczb downto 1 do write(t<b>,', '); writeln; end; procedure gwiazdki (znak:char;slowo:string;ile:byte); begin writeln; for b:=1 to ile do write(znak); writeln; writeln(slowo); for b:=1 to ile do write(znak); writeln; writeln; end; procedure najwiekszy_element; begin i_max:=1; max_el:=t[i_max]; for b:=1 to ilosc_liczb do if t<b>>max_el then begin i_max:=i; max_el:=t[i_max]; end; writeln('Element największy to: ',max_el,' a jego położenie to: a',i_max); end; procedure suma; var suma:longint; begin suma:=0; for b:=1 to ilosc_liczb do suma:=suma+t<b>; writeln('Suma elementów ciągu to: ',suma); end; procedure iloczyn; var iloczyn:longint; begin iloczyn:=1; for b:=1 to ilosc_liczb do iloczyn:=iloczyn*t<b>; writeln('Iloczyn elementów ciągu to: ',iloczyn); end; procedure srednia; var suma:real; srednia:real; begin suma:=0; for b:=1 to ilosc_liczb do suma:=suma+t<b>; srednia:=suma/ilosc_liczb; writeln('Średnia arytmetyczna wprowadzonych liczb to: ',srednia:3); end; procedure sortowanie; begin zamiana:=true; while zamiana do begin zamiana:=false; for b:=1 to ilosc_liczb-1 do if t<b>>t[b+1] then begin pom:=t<b>; t<b>:=t[b+1]; t[b+1]:=pom; zamiana:=true; end; end; end; begin repeat Write('Podaj ilość liczb jaka chcesz wpisać '); readln(ilosc_liczb); until (ilosc_liczb>0); wprowadz; writeln; gwiazdki('*','STATYSTYKA',45); writeln('Twój ciąg liczb to: '); wypisz; writeln('Ilosc liczb w ciągu: ',ilosc_liczb); writeln('Elementy skarjne ciągu to: ',t[1],' oraz ',t[ilosc_liczb]); najwiekszy_element; sortowanie; writeln('Liczby jakie podałeś w kolejności rosnącej to: '); wypisz; writeln('Liczby jakie podałeś w kolejności malejącej to: '); wypisz_odwrotnie; gwiazdki('*','OBLICZENIA',45); srednia; suma; iloczyn; writeln; readln; end.
Nie jest to bardzo skomplikowany program i zapewne nie jeden z czytelników napisałby lepszy itd. jednak nie o tym chciałem napisac. Chciałem pokazac jak w prosty sposób można sobie pomóc.
Oczywiście każdy ma własne zdanie dotyczące danych kwestii nie zamierzam go w żaden sposób podważać, czy obrażać kogokolwiek w jakikolwiek sposób. Przepraszam także za ewentualne błędy.