background image

Data i czas 

 

Moduł 'Dos' Turbo Pascal'a udostępnia funkcje, za pomocą których możesz uzyskać 
wiadomości o bieżącej godzinie a także dacie. Pascal umożliwia również sprawdzenie ile 
milisekund jest włączony komputer bez użycia dodatkowych modułów. 

 

Ponieważ część operacji opisanych w tym rozdziale będzie operawała na module Dos, 
musimy go zadeklarować, czyli wpisać na początku programu: 

 

uses Dos; 
 

Badanie czasu 

 

procedure GetTime(var Hour, Minute, Second, Sec100 : Word); 
 

procedura GetTime zwraca aktualny czas komputerowy. Zapisuje go do Twoich zmiennych, 
które wstawisz do procedury. 
 
Hour przyjmuje wartości 0..23, 
Minute 0..59 
Second 0..59 
Sec100 0..99 

 

Można uzyskać czas choćby w taki sposób: 

 
uses Dos; 
var h, m, s, ss : Word; 
 
begin 
 GetTime(h, m, s, ss); 
 WriteLn('Jest godzina: ', h, ':', m); 
end. 
 

Można korzystać ze zmiennych o dowolnej nazwie, ale zadeklarowanych jako Word. 

 

background image

Badanie daty 

 
procedure GetDate(var Year, Month, Day, DayOfWeek : Word); 
 

procedura GetDate zwraca aktualną datę. Zapisuje ją także do Twoich zmiennych, które 
wstawisz do procedury. 
 
Year przyjmuje wartości 1980..2099, 
Month 1..12 
Day 1..31 
DayOfWeek 0..6 

 

Jeśli chodzi o dni tygodnia, gdy program zwróci 0 będzie to niedziela 

 

Można uzyskać datę choćby w taki sposób: 

 
uses Dos; 
var y, m, d, dw : Word; 
 
begin 
 GetDate(y, m, d, dw); 
 WriteLn('Dzisiaj jest: ', y, '-', m, '-', d); 
end. 
 

W trybie graficznym 

 

Zadanie wyświetlania godziny i daty w trybie graficznym jest nieco trudniejsze, ale także 
proste. Jeśli pierwszy raz próbujesz w grafice wyświetlić czas lub datę, pewnie spotka Cię 
niemiłe zaskoczenie i błąd: „Type Mismatch”. 

 

Najprawdopodobniej będziesz chciał tak samo jak to robiłeś we WriteLn, użyć OutText, lub 
OutTextXY. To normalne dla człowieka, niestety nie dla komputera. 

 

Niestety nie wolno napisać tak: 
OutTextXY(100, 100, 'Jest godzina', g, ':', m); 

 

background image

Dlaczego? 
OutText różni się od WriteLn. WriteLn mógł przyjmować jako treść do wyświetlania 
praktycznie wszystko. Nie ważne było dla niego czy wyświetlasz zmienną tekstową, liczbową 
czy jeszcze inną. OutText przyjmuje tylko tekst i w dodatku tylko jeden napis ciągły! 

 

Twoje zadanie polega więc na zbudowaniu jednej zmiennej tekstowej, która będzie zawierała 
całą informację łącznie z godziną -czyli zmienną liczbową. 

 

Kolejna trudność powstaje z tym, że nie wolno łączyć zmiennej tekstowej z liczbową. Są one 
całkiem inaczej zapisywane w pamięci komputera. Dzięki temu liczby zajmują mniej miejsca 
w pamięci i komputerowi jest znacznie łatwiej robić na nich operacje matematyczne. 

 
 
Zamiana zmiennej liczbowej na tekstową 
Str(Liczba : LongInt; var Tekst : string); 
 

Służy do tego procedura Str 
Przykład użycia 

 
var i : Integer; 
   s : string; 
begin 
 i := 10; 
 Str(i, s); 
 WriteLn(s); 
end; 
 

Przygotowanie zmiennej tekstowej zawierającej aktualną datę: 

 

uses Dos; 
var y, m, d, dw : Word; 
   temp, s : string; 
 
begin 
 GetDate(y, m, d, dw); 
 Str(y, temp); 
 s := 'Dzisiaj jest: ' + temp; 
 Str(m, temp); 
 s := s + '-' + temp; 
 Str(d, temp); 

background image

 s := s + '-' + temp; 
 
 WriteLn(s); 
end. 
 

Zegar wskazówkowy* 

 

Do stworzenia zegara wskazówkowego będzie potrzebna lekka umiejętność matematyki. 
Naszym zadaniem będzie obliczenie kątów jakie wskazówka pokonała od godziny 0:00. 
Będziemy zamieniali liczbę minut, które minęły od początku godziny na stopnie, a stopnie na 
radiany. Podobna operacja czeka nas z godziną i sekundami. 

 

Kolejna uwaga, Twoja karta grafiki musi być zgodna ze standardem VESA. Niestety, coraz 
więcej firm produkujących karty graficzne, zrezygnowało z podtrzymywania tego standardu. 
Być może będziesz musiał programować na VirtualPC -program, na którym można emulować 
inny komputer. 

 

Niżej opisany jest ogólny schemat budowy i rozwoju programu. Pomoże Ci ustalić jak w 
rzeczywistości powstaje bardziej skomplikowany kod. W rzeczywistości trzeba go podzielić 
na mniejsze punkty, co chwilę je testować i dodawać kolejne. Warto regularnie zapisywać 
program (F2) – przed każdym jego uruchomieniem, a nawet co napisanie kilku linii 
programu. 

 

Uruchomienie grafiki 
 
Wyłączenie grafiki 
 

Najpierw zajmujemy się najprostszymi operacjami, w dodatku tymi, bez których dalszy kod 
programu nie ruszy. W tym wypadku włączeniem grafiki. 

 
 

Uruchomienie grafiki 

Narysowanie tarczy zegara

 

Wyłączenie grafiki 
 

Później warto narysować tarczę, czyli zobaczyć pierwsze efekty swojej pracy. Tarcza będzie 
jeszcze bez wskazówek, ale da Tobie dużo satysfakcji... w końcu coś zaczyna się dziać. 

background image

 

Następnie dobrze narysować krótkie linie, ułatwiające odczytanie z tarczy minuty. Będzie ich 
60, najlepiej zrobić to w pętli i pierwszy raz skorzystać w poważnej matematyki (Sinus, 
Cosinus). Jest 360 stopni w pełnym kole, więc co 6 stopni powinna być kolejna linia. 

 

Ale jak za pomocą stopni ustalić pozycje 60 linii? Będziemy potrzebowali wyliczyć 
współrzędne x i y dla każdego punktu. Każda linia potrzebuje 2 punktów. Trzeba 
przypomnieć więc kilka informacji z matematyki: 

 

 

Długość odcinka "a", czyli oddalenie wyliczanego punktu od środka liczymy ze wzoru: a = r 
cos ?. Długość odcinka c = r sin ?. Teraz do środka współrzędnych tarczy musimy dodać: w 
poziomie odcinek a, a w pionie odjąć odcinek c. Manipulując promieniem -dodając jeden 
odrobinę dłuższy od drugiego otrzymamy dwie współrzędne dla dwóch punktów. Możemy 
połączyć już je linią. 

 

W Pascalu funkcje sinus i cosinus potrzebują wartości w radianach by wyliczyć żądaną 
wartość. W pełnym kole jest 360 stopni co odpowiada wartości 2? (w radianach). Z tego 
wynika, że 

 

360° =  2? (rad), 
1° =  2? / 360 (rad), 
1° =  ? / 180 (rad), 
x° odpowiada  x * (? / 180) (rad), 
 

Aby więc wyliczyć sin 30° wpiszemy: 

WriteLn Sin(30 * (PI / 180)); 
 

background image

Co piąta minuta powinna być grubsza. 
 
 
        

FOR i:=1 TO 60 DO 
       BEGIN 
         IF (i MOD 5<>0) THEN SetLineStyle(0, $FF, 1) ELSE SetLineStyle(0, $FF, 3); 
         SetColor(7); 
         Line(Sx+Round(Sin((540-i*6)*(PI/180))*(DlM+12)), 
              Sy+Round(Cos((540-i*6)*(PI/180))*(DlM+12)), 
              Sx+Round(Sin((540-i*6)*(PI/180))*(DlM+18)), 
              Sy+Round(Cos((540-i*6)*(PI/180))*(DlM+18))); 
 
       END; 
 

Potrzebny jest nam promień tarczy zegara a także kąt jaki pokonała wskazówka. W 
matematyce kąty liczymy od poziomu w górę, w zegarze interesują nas kąty od godziny 
dwunastej w dół. Przy rysowaniu poruszającej się wskazówki trzeba więc uwzględnić, że ruch 
wskazówek zegara jest przeciwny do zwiększającego się kąta w matematyce a w dodatku nie 
zaczyna się od tego samego miejsca. 

 

To jednak nie jest dla nas problemem. Wskazówka minutowa matematycznie pokonuje drogę 
od kąta 90 stopni, potem 84, 78, 72 aż do 0 a następnie 354, 348 itd.. aż do 90 stopni. Zamiast 
zwiększać kąty, będziemy je odejmować od 90. (Wskazówka minutowa porusza się kątowo 
wg wzoru: ? = 90 – m * 6, gdzie zmienna m to kolejna minuta od 0 do 59) 

 

Godzina dwunasta ma kąt 90 stopni, trzecia ma kąt 0 stopni, szósta 270 a dziewiąta 180. Czyli 
wskazówka godzinowa występuje co 30 stopni. Z tego wzór na obliczenie kąta godziny to: ? 
= 90 – g * 30, gdzie g to numer godziny (od 0 do 11) 

 

Z wartościami kątów nie będzie problemów, bo przecież rysujemy 60 razy linię co 6 stopni. 
Korzystając z pętli ze zmienną i od 1 do 60, będziemy po prostu mnożyli zmienną "i" przez 6. 
Orzymamy w wyniku 6, 12, 18, 24... 354, 360 

 

Narysowanie tarczy zmobiluzuje Cię do dalszej pracy. Trzeba pamiętać, by dodać pętlę 
czekającą na naciśnięcie klawisza, żeby wogóle cokolwiek zauważyć. 

 
 

background image

Uruchomienie grafiki 

Dodanie pętli aż do momentu naciśnięcia klawisza

 

 Narysowanie tarczy zegara 

Koniec pętli

 

Wyłączenie grafiki 
 

Pętla spowoduje, że program będzie się wykonywał w kółko. Zacznie od początku, dojdzie do 
końca i znowu zacznie od początku. 

 

while (PORT[$60]<>1) do 
   begin 
     {...} 
   end 
 

Tarczę zegara i wskazówki rysujemy tylko wtedy, gdy jest to potrzebne, czyli co sekundę -
gdy pozycja wskazówek ulegnie zmianie. Nie ma potrzeby, żeby tarcza się cały czas 
rysowała, bo będzie to obciążało procesor komputera a poza tym będzie bardzo mocno 
migało. Dlatego właśnie w programie jest warunek: 

 

GetTime(h, m, s, ss); 
     if (s<>sse) then 
   begin 
     {...} 
     sse := s; 
   end; 
 

W tym wypadku zmienna sse przechowuje starą wartość sekund a zmienna 's' aktualną. Jeśli 
aktualna ilość sekund jest różna od starej, wtedy... rysujemy cały zegar. Oczywiście trzeba po 
sprawdzeniu warunku do zmiennej 'sse' przypisać wartość 's', bo teraz starą sekundą będzie ta, 
właśnie narysowana. 

 

A jak narysować wskazówki? To jest znacznie prostsze od narysowania tarczy. Jeden koniec 
wskazówki będzie w środku koła, drugi koniec będzie ruchomy, będzie przesuwał się dookoła 
tarczy. 

 

Uruchomienie grafiki 
Dodanie pętli aż do momentu naciśnięcia klawisza 
 

Dodanie warunku -jeśli zmieniła się sekunda

 

 Narysowanie tarczy zegara 
 

Narysowanie wskazówek

 

background image

Koniec pętli 
Wyłączenie grafiki 
 

Już wiemy jak obliczyć współrzędne X i Y punktu znajdującego się na okręgu o podanym 
promieniu, dla dowolnego kąta. Teraz wystarczy zamienić ilość minut, sekund i godzin na 
odpowiedni kąt i wszystko gotowe. Rysujemy trzy linie, każdą o jej własnym stylu 
graficznym. 

 

Line(Sx, Sy, Sx+Round(Sin((540-m*6)*(PI/180))*DlM), 
            Sy+Round(Cos((540-m*6)*(PI/180))*DlM)); 
 

Zmienna Sx, Sy oznacza tu środek tarczy zegara. 'm' to ilość minut. (540-m*6) to zamieniona 
ilość minut na kąt. (540-m*6)*(PI/180) to obliczenie wartości radianowej z kątowej -bo tego 
właśnie wymaga funkcja Sin(). Na koniec mnożymy otrzymany wynik przez DlM, czyli 
długość wskazówki minutowej. Jeśli zmienisz wartość DlM na mniejszą, wskazówka będzie 
krótsza, jeśli ułożysz nieprawidłowo obliczanie kąta, wskazówka będzie się cofać, albo 
zaczynać nie od minuty :00 tylko od innego miejsca. 

 

Poniżej znajduje się całkowity kod źródłowy zegara wskazówkowego w Turbo Pascalu. 
Poeksperymentuj trochę z zegarem a dużo się z tego nauczysz. Będziesz wtedy dobrze 
wiedzieć co odpowiada za jakie właściwości i przede wszystkim łatwiej Ci będzie zrozumieć 
ideę tworzenia podobnych kodów. 

 

uses Graph, Dos; 
 
const 
    Sx : Integer = 320; 
    Sy : Integer = 240; 
 
    DlM = 100; 
    DlH = 80; 
    DlS = 90; 
 
    GM = 1; 
    GH = 3; 
    GS = 1; 
 
 
 
var 
  h, m, s, ss : Word; 
  sse         : Word; 

background image

  i           : Integer; 
 
 
  grDriver: Integer; 
  grMode: Integer; 
  ErrCode: Integer; 
 
function IntToStr(i:Integer):string; 
var s:string; 
begin 
 Str(i, s); 
 if (i<10) then s:='0'+s; 
 IntToStr:=s; 
end; 
 
 
begin 
 
 grDriver :=Detect; 
 InitGraph(grDriver, grMode,' '); 
 ErrCode := GraphResult; 
 if ErrCode = grOk then 
 begin  { Do graphics } 
 
   while (PORT[$60]<>1) do 
   begin 
 
     GetTime(h, m, s, ss); 
     if (s<>sse) then 
     begin 
       ClearDevice; 
       SetColor(10); 
       OutTextXY(560, 460, IntToStr(h)+':'+IntToStr(m)+':'+IntToStr(s)); 
       SetColor(7); 
       SetFillStyle(1, 8); 
       FillEllipse(Sx, Sy, DlM+20, DlM+20); 
 
       for i:=1 to 60 do 
       begin 
         if (i mod 5<>0) then SetLineStyle(0, $FF, 1) else SetLineStyle(0, $FF, 3); 
         SetColor(7); 
         Line(Sx+Round(Sin((540-i*6)*(PI/180))*(DlM+12)), 
              Sy+Round(Cos((540-i*6)*(PI/180))*(DlM+12)), 
              Sx+Round(Sin((540-i*6)*(PI/180))*(DlM+18)), 
              Sy+Round(Cos((540-i*6)*(PI/180))*(DlM+18))); 
 
       end; 
 
 
       sse := s; 

background image

 
       SetColor(15); 
       SetLineStyle(0, $FF, GH); 
       Line(Sx, Sy, Sx+Round(Sin((540-h*30)*(PI/180))*DlH), 
            Sy+Round(Cos((540-h*30)*(PI/180))*DlH)); 
 
       SetColor(9); 
       SetLineStyle(0, $FF, GM); 
       Line(Sx, Sy, Sx+Round(Sin((540-m*6)*(PI/180))*DlM), 
            Sy+Round(Cos((540-m*6)*(PI/180))*DlM)); 
 
       SetColor(12); 
       SetLineStyle(0, $FF, GS); 
       Line(Sx, Sy, Sx+Round(Sin((540-s*6)*(PI/180))*DlS), 
                    Sy+Round(Cos((540-s*6)*(PI/180))*DlS)); 
 
 
     end; 
 
   end; 
 
   CloseGraph; 
 end 
 else 
   Writeln('Graphics error:', GraphErrorMsg(ErrCode)); 
 
 
end. 
 


Document Outline