Download original in English  
as a DOS program  

mennonite's

całkiem zgrabne wprowadzenie do QB

Przekład: Damian Gawrych "Deger", marzec - kwiecień 2007
na licencji GNU GPL




Rozdział  1: Czym właściwie jest QBasic?
Rozdział  2: Uczymy się QBasic-a
      PRINT • LPRINT • CLS • COLOR
Rozdział  3: Zmienne
Rozdział  4: Kluczem są liczby...
      Obliczenia • ABS • INT • MOD • VAL • RND • SGN • SQR
Rozdział  5: Łańcuchy cz. 1: rzeczy niezastąpione
      UCASE$, LCASE$ • CHR$ • ASC • LEN
Rozdział  6: Więcej o ekranie tekstowym
      LOCATE • CSRLIN • POS • VIEW PRINT • SCREEN • WIDTH
Rozdział  7: Klawiatura i linie danych
      DATA • READ • RESTORE • INKEY$ • INPUT$ • INPUT • LINE INPUT
Rozdział  8: Łańcuchy cz. 2: wyszukiwanie i manipulacja
      INSTR • SPACE$ • LEFT$, RIGHT$ • MID$ • LTRIM$ • STR$
Rozdział  9: Praca z plikami binarnymi
      GET • PUT • FREEFILE • LOC • LOF • CLOSE • OPEN... FOR BINARY
Rozdział 10: Odgałęzienia w programie
      GOTO • GOSUB • RETURN • END • REM
Rozdział 11: Podejmowanie decyzji
      IF...THEN • SELECT CASE
Rozdział 12: Pętle w programie
      DO...LOOP, UNTIL, WHILE, EXIT DO • FOR...NEXT, STEP
Rozdział 13: Praca z plikami tekstowymi
      OPEN... FOR OUTPUT, APPEND, INPUT
Rozdział 14: Grafika
      SCREEN • PSET • CIRCLE • PCOPY • PAINT • LINE • POINT • PALETTE • DRAW
Rozdział 15: Błędy
      ON ERROR GOTO... • RESUME
Rozdział 16: Pomiar czasu
      TIMER • SLEEP • TIME$ • DATE$
Rozdział 17: Tablice
Rozdział 18: Wykorzystanie wewnętrznego głośnika
      PLAY • SOUND
Rozdział 19: Inne przydatne polecenia
      SHELL • COMMAND$ • SYSTEM
Rozdział 20: Zastrzeżenia
      PEEK, POKE • INP, OUT • CALL • INTERRUPTX • KILL • BSAVE, BLOAD
Rozdział 21: Pytania (i przyszłość Basic-a)



Od tłumacza:

      Oryginalny tekst "Wprowadzenia do QB" jest opublikowany w postaci wielu plików tekstowych powiązanych nawzajem odsyłaczami "IKI", pracującymi pod DOS-em, jak i pod Windows. IKI to napisany we FreeBasic prosty system hipertekstowy wzorowany na Wiki, ale działający off-line; "Wprowadzenie" jest przykładem jego zastosowania. Pod Windows można go przeglądać w oknie DOSa.

      Przekład w pewnym sensie odwzorowuje ten układ, wykorzystując w HTML tekst preformatowany o 80-znakowym wierszu; dlatego, podobnie jak z IKI, można go też oglądać w pomniejszonym oknie, mając w innym np. otwarty QBasic (dla ćwiczeń). Układ "stron" oryginału jest odtworzony przez podział poziomymi liniami. Od tłumacza pochodzi spis treści i nieco przypisów.


Rozdział 1: Czym właściwie jest QBasic?

QBasic jest interpretatorem programów Basica wydanym przez Microsoft. Był on przeznaczony dla systemu operacyjnego MS-DOS, aczkolwiek działa też z różnymi innymi odmianami DOS-a, w tym i Freedos. B.a.s.i.c. jest prostym językiem stworzonym w Dartmouth College do kodowania programów komputerowych. QuickBasic jest kompilatorem programów Basica... Główną różnicą pomiędzy nimi jest oczywiście to, że QuickBasic potrafi kompilować programy do kodu maszynowego i ma więcej dostępnych funkcji niż interpretator QBasic'a. Faktycznie QuickBasic zawiera interpretator prawie taki sam jak w QBasicu, ale pierwotnie był rozprowadzany jako samodzielny pakiet programów, podczas gdy QBasic był dołączany do wersji MS-DOS 5 i wyższych, a także do Windows 9x (może nie być zainstalowany, ale można go znaleźć na dysku instalacyjnym Windows95).
Zazwyczaj nie napotyka się różnicy między interpretatorem a kompilatorem, dopóki nie potrzeba robić własnych samodzielnych plików *.exe. Najogólniej, im bardziej złożone procedury używa program, tym bardziej prawdopodobne jest, że będzie potrzebował kompilatora i towarzyszacych mu bibliotek. Jednak, wg mojego osobistego doświadczenia, wiekszość programów będzie pracować pod interpretatorem. Oczywiście, gdy program zostanie skompilowany do samodzielnego pliku *.exe, nie trzeba już w ogóle żadnej wersji QBasic'a czy QuickBasic'a, aby go uruchomić.
B.a.s.i.c. został zaprojektowany, aby uczynić programowanie bardziej dostępnym dla nowicjuszy i jest prawdopodobnie najbardziej przyjaznym językiem programowania spośród wszystkich istniejących. Jeśli próbujesz szybko napisać mały program do wykonania prostego zadania na komputerze, B.a.s.i.c. pozwala zrobić to niewielkim nakładem czasu i wysiłku. Jest on znaczącą częścią dziesięciolecia trwającej tradycji programowania hobbystycznego; niezliczone książki i strony WWW zawierają kody źródłowe, które można wypróbować na swoim komputerze.
Programy B.a.s.i.c.'a zwykle wykonują się wolniej w porównaniu z napisanymi w innych językach i większość interpretatorów i kompilatorów B.a.s.i.c.'a ma poważne ograniczenia w tym, co i jak dobrze mogą one wykonać. Z tego powodu większość poważnych programistów (i wielu tych, którzy zamierzają programować dla zarobku) przerzuciło się na inne języki. Mimo to B.a.s.i.c. nie przestał być użyteczny i przyjemny, i jeśli jest nawet jednym z pomniejszych języków, trzyma się dzielnie również dzisiaj.

Rozdział 2: Uczymy się QBasic-a

Gdy uczymy się jakiegoś języka programowania, pierwszą rzeczą za którą się rozglądamy, jest dobry podręcznik, jeśli taki jest dostępny. Większość podręczników będzie zawierać różne odmiany programu "Hello World" lub program który spowoduje, że komputer wypisze na ekranie "Hello, World!". Drugą rzeczą, której szukamy ucząc się nowego języka, są przykłady programów; tu "Hello, World!" mógłby być najprostszym.
Zgodnie z nazwą, B.a.s.i.c. (odtąd będziemy go nazywać QBasic, ponieważ QBasic wykonuje świetną robotę interpretowania kodu B.a.s.i.c.'a i ponieważ jest to interpretator, z którym najprawdopodobnej będziesz rozpoczynać naukę) robi teraz całkiem łatwe zadanie:

    10 PRINT "hello, world!"
    20 END
 
  hello, world!


 To był dawniejszy sposób, gdy każda linia wymagała numerowania. W QBasic'u
 numery\ linii są opcjonalne (i prawie nigdy ich nie zobaczysz, poza książkami)
 i mogą zwykle być pominięte. Wyjątkiem jest, kiedy chcemy powrócić do miejsca,
 w którym byliśmy wcześniej, ale teraz nie martwmy się tym jeszcze...


Oto bardziej "współczesna" wersja kodu: PRINT "hello, world!" END Nie ma tu wielkiej różnicy; oczywiście nie musimy usuwać numerów linii z poprzedniego kodu, aby on zadziałał, są one po prostu rodzajem brzydkiej uciążliwości.
Polecenie PRINT, które prawdopodobnie powinno zwać się ECHO, jak to jest w DOS-ie, "drukuje" na ekran. Oczywiście, zanim wszyscy mieli monitory przyłączone do komputera, "ekranem" był dalekopis, albo zespół klawiatura - - drukarka elektryczna, dość podobna do maszyny do pisania, więc być może "print" nie jest taką znowu dziwną nazwą.
Nawiasem mówiąc, poleceniem drukowania na drukarce jest LPRINT, w gruncie rzeczy jest to część systemu DOS, nie tylko w Windows czasem powstają problemy gdy używamy LPRINT, ale bez Windows LPRINT nie będzie drukować na niektórych nowszych modelach drukarek (zauważyłem, że Lexmark pierwszy porzucił kompatybilność z "czystym" DOS-em, chociaż mógł być ktoś jeszcze) i oczywiście nie będzie drukować na drukarkach USB. (Jest możliwe uzyskać dostęp spod DOS-a do niektórych urządzeń USB bez uruchamiania Windows. Jest to bardzo, bardzo skomplikowane.)
Polecenie END zwyczajnie kończy program. Jeśli po tym poleceniu znajduje się jeszcze jakiś kod, nie zostanie on uruchomiony, chyba że specjalnie każemy w innej części programu iść do tego miejsca.
Jeżeli znowu każemy komputerowi drukować (PRINT), będzie on drukował w następnej linii... Zatem następujacy kod:
    PRINT "hello, world!"
    PRINT "jak sie masz?"
    END 
   
   tak się powinien zakończyć na ekranie:
 
  hello, world!
  Jak sie masz?


 Jeśli nie chcesz przejść do nowej linii, spróbuj wstawić średnik
 za cudzysłowem w linii, do której chcesz dopisać: 
    PRINT "hello, world!";
    PRINT "jak sie masz?"
    END 
   
   który zamiast tego wypisze tak:

   możesz dodać spacje, jeśli chcesz.
 
 
  hello, world!Jak sie masz?
 

 Możesz zakończyć z mnóstwem "hello" na ekranie, albo po prostu możesz chcieć
 zacząć od nowa. To polecenie:

 CLS

 oznacza "Clear Screen" - "wyczyść ekran" - i jest powszechnym sposobem
 rozpoczynania programu.

    CLS
    PRINT "hello!"

 Ale możesz chcieć jeszcze urozmaicić program. Dodajmy kolor.


Basic i QBasic nie są ograniczone do tekstu, lecz funkcje związane z tekstem sa omawiane jako pierwsze, ponieważ są zazwyczaj łatwiejsze do zakodowania i ponieważ naprawdę nie możesz od nich uciec, nawet jeżeli piszesz program graficzny. Zmienianie koloru jest naprawdę łatwe, jeżeli wiesz, jak. Wypróbuj to:

   CLS
   COLOR 1
   PRINT "NIEBIESKI!"
 
 
  NIEBIESKI!



 

 Kolory są reprezentowane przez liczby i w domyślnym, czysto tekstowym trybie
 jest ich szesnaście 1).

 Oto tabela:

    Paleta 16 podstawowych kolorów trybu tekstowego.


Można nawet zmieniać kolory przed przejściem do następnej litery:
    COLOR 2
    PRINT "h";
    COLOR 3
    PRINT "e";
    COLOR 5
    PRINT "l";
    COLOR 4
    PRINT "l";
    COLOR 1
    PRINT "o" 
 
  hello


 

 Abyś nie był zaskoczony - PRINT bez żadnej zmiennej łańcuchowej lub liczbowej
 po prostu drukuje pustą linię (albo zaprzestaje dodawania na końcu polecenia
 PRINT zakończonego średnikiem).






Rozdział 3: Zmienne

Zmienne są najłatwiejszym sposobem przechowywania danych w pamięci; oczywiście ta pamięć jest kasowana gdy program kończy się lub komputer zostaje wyłączony, ale zmienne są przydatne, gdy chcemy aby dane z jednej części programu były dostępne dla innej linii w programie. Są dwa główne typy zmiennych: łańcuchowe (tekstowe) i liczbowe (numeryczne). Nazwy zmiennych zaczynają się od litery i składają się z liter i liczb 2).
Oto przykład zmiennej tekstowej w działaniu:
    q$ = "hello, world!"
    PRINT q$
    PRINT q$
    PRINT q$
    PRINT q$
 
  hello, world!
  hello, world!
  hello, world!
  hello, world!

 
 Zawartość zmiennej łańcuchowej q$ jest drukowana 4 razy.


Łańcuchy, jak te używane przez polecenie PRINT, zaczynają się i kończą cudzysłowem "jak tutaj". Nie można wprowadzić łańcucha zawierającego wewnątrz cudzysłów: "jak to "robi ten" przykład," Później nauczymy się sposobu na to, przy użyciu funkcji CHR$. Zmienne łańcuchowe prawie zawsze kończą się znakiem dolara, gdy z drugiej strony zmienne liczbowe często kończą się bez żadnego specjalnego symbolu, mimo że istnieją inne przyrostki dla określonych typów (których zwykle nie potrzebujemy... ale możesz chcieć je użyć)3).
Wszystkie nazwy zmiennych mogą mieć jedną lub wiecej liter, muszą zaczynać się od litery i mogą po niej zawierać liczby (np. q2$ lub q2)4). Nie możesz również nadać zmiennej takiej samej nazwy jak polecenie lub funkcja jeżeli chcesz, aby program działał. Warto pokazać, że można drukować mieszaninę łańcuchów i liczb, jak w przykładzie poniżej:

    n=50
    PRINT 7; q$; n; "razy."
 
 
   7 hello, world! 50 razy.
 
 ... i można łączyć dwa łańcuchy w jeden, znakiem +, jak tutaj:

    q$="hello"
    q$="o, "+q$+" tutaj..."

 Teraz w zmiennej q$ jest przechowywany łańcuch "o, hello tutaj...".
 Łączenie łańcuchów w ten sposób, z użyciem lub bez użycia zmiennych, jest
 zwane "konkatenacją" i nie działa ze zmiennymi liczbowymi.

 
Jest jeszcze parę rzeczy, które mogłbyś chciec wiedzieć przed ruszeniem dalej: Często jest bardzo pożądane (dla oszczędności czasu i wysiłku) wpisywać znak zapytania: ? "hello" zamiast wpisywania PRINT; QBasic (jak wiele innych interpretatorów i kompilartorów) zamienia go na PRINT. Nie należy jednak przestać używać znaku zapytania tam, gdzie jest on potrzebny w tekście: ? "czy chcesz zakończyć?" będzie zamienione na: PRINT "czy chcesz zakończyć?"
Poza tym, zamiast pisać każde polecenie w oddzielnej linii, często możesz chcieć łączyć linie kodu, używając dwukropka: CLS: PRINT "do wszystkich zainteresowanych"; : PRINT ":" wyczyści ekran i wypisze:
 
  do wszystkich zainteresowanych:
 

COLOR 10: PRINT "Drogi Janie"; : PRINT ","
  wypisze
 

  Drogi Janie,

 
 Gratulacje! Jeśli jeszcze tego nie zrobiłeś, możesz teraz napisać swój
 pierwszy program w QBasic'u. Będziesz mógł zrobić znacznie więcej
 po przeczytaniu następnego rozdziału.





Rozdział 4: Kluczem są liczby...

Nieeee! Tylko nie matematyka! Na poważnie, wszystko co robi komputer, to odliczanie i wyliczanie, matematyki nie da się uniknąć, ale przez większość czasu nie będzie ona bolesna. W programowaniu kolory są liczbami, dźwięki są liczbami, litery są liczbami i liczbami są różnice między programem który coś robi i takim, który nie robi nic; jest tu więc parę sposobów na pracę z nimi...
Przede wszystkim - operacje: użycie x+y dodaje je do siebie, x-y odejmuje y od x, x*y daje iloczyn, a zwykły ukośnik, "/", będzie dzielił. Potegowanie stosuje zapis x^y, gdzie x jest podnoszone do potęgi y. Obliczenia dobrze pracują ze zmiennymi:
    x = 7
    y = x * 5
    PRINT "7 razy 5 =";
    PRINT y
 
 
  7 razy 5 = 35
 

W QBasic-u można stosować nawiasy w taki sam sposób, jak używamy ich w obliczeniach na papierze (z tą oczywiscie różnicą, że chcemy je wprowadzać z klawiatury, a nie ołówkiem). Idąc dalej, ABS(x) automatycznie zamienia każdą wartość poniżej zera na taką samą wartość powyżej zera. Tak, ono po prostu usuwa "minus" z liczby ujemnej.
    q = ABS((5 / 7) * -1)
    PRINT q
  
  .7142857

 

INT Jest podobne w swej prostocie do ABS, lecz przypuszczalnie częściej się przydaje. INT(x) z liczbami całkowitymi nie robi w ogóle nic. Jednak kiedy x nie jest liczbą całkowitą, INT zmusi ją, aby taką była, obcinając ułamek (część dziesiętną). Wszystko wskazuje na to, że gdy pozostaniesz przy QBasic-u, będziesz używać tej funkcji, zapoznaj się więc z nią.
    PRINT INT(7 / 3); INT(-4.9); INT(4.9)
  
  2 -5  4

 

MOD Jest to dziwaczna funkcja o dziwnej nazwie (nazwa pochodzi od "modulus"). Zmusza ona długi zestaw liczb do stania się mniejszym: powiedzmy że mamy liczbę... 42 (a czemu by nie?), ale potrzebujemy liczbę z zakresu 0 — 15, bo przypuszczamy, że liczba ta reprezentuje kolor. Możemy oczywiście odrzucić każdą liczbę powyżej 15 i ustawić ją na 15, albo zamiast tego wykonać 42 MOD 16 (znacznie bardziej przydatne w przypadku zmiennych, a nawet pętli i liczników), które zawsze da nam liczbę z zakresu 0 do 15. Zilustrujmy to na małych liczbach i zobaczmy, czy jest zrozumiałe:

    PRINT 0 MOD 7
    PRINT 1 MOD 7
    PRINT 2 MOD 7
    PRINT 3 MOD 7
    PRINT 4 MOD 7
    PRINT 5 MOD 7
    PRINT 6 MOD 7
    PRINT 7 MOD 7
    PRINT 8 MOD 7
 
  0
  1
  2
  3
  4
  5
  6
  0
  1 








 znowu!

 Najwięcej uciechy z dzielenia modulo można mieć w procedurach graficznych,
 gdzie jego najlepszym celem może być obsługa (naprawdę) długich dzieleń.
 Jeżeli nigdy go nie użyjesz, to OK, o jedną rzecz mniej...

*) przyp. tłum. - modulo daje jako wynik resztę z dzielenia.


Przejdziemy teraz do pewnej funkcji liczbowej, której użycie jest trudne do uniknięcia... VAL n = VAL(q$) przekształca łańcuch q$ na warość n, tak że łańcuch " 0.557" staje się dla programu po prostu .557: czymś, co może być dodawane, odejmowane lub w inny sposób użyte jako liczba, czego z łańcuchem (w przeciwnym razie) zrobić nie można. Jest to bezcenne, gdy pracujemy z danymi z plików i z klawiatury.
    q$ = "27a"
    PRINT VAL("tutaj"); VAL(q$); VAL("4.91")
  
  0  27  4.91

 

Jeśli potrzebujemy dostatecznie "losową" liczbę, do rzutu kostką lub po prostu do zgrabnego wyświetlenia na ekranie, użycie funkcji RND z INT oraz liczbą potrzebnych "scianek": n = INT(RND * 6) zwróci nam liczbę z zakresu 0 — 5 i możemy otrzymać każdą liczbę reprezentującą "oczka", lub cokolwiek chcemy.
Potrzebne 1 do 6? Czemu nie? n = INT(RND * 6 + 1) zwróci liczby bardziej przydatne dla kości. (Możesz pomyśleć "dlaczego nie 'RND * 7'?" i najprostsza odpowiedź jest "ponieważ jest to błąd!" Przydatna odpowiedź to, że RND * 6 + 1 wytwarza 6 możliwych liczb z jedynką dodaną do takiej liczby, a RND * 7 w rzeczywistości tworzy siedmiostronną kostkę, coś, czego nigdy w życiu nie widziałem.)
Zauważysz, że kiedy wylosujesz 100 liczb, to przy każdym uruchomieniu programu będa to te same liczby. Aby to obejść, kod RANDOMIZE TIMER będzie "zasiewał" funkcję RND. Wówczas taki sam rzut kostką trafi się dwa razy, kiedy odbędzie się o tej samej porze dnia co poprzednio, z dokładnością do milisekundy; biorąc jeszcze pod uwagę, że zegar systemowy w twoim komputerze nie pokazuje dokładnie takiego samego czasu, jak twój cyfrowy zegarek na rękę, nawet jeśli ustawiłeś go według zegara atomowego: możesz sobie próbować... RANDOMIZE TIMER ? "ta liczba będzie wystarczająco losowa:"; INT(RND * 10)
q = SGN(n) ustawia q na -1 gdy n jest mniejsze niż 0, ustawia q na 0 gdy n = 0, i ustawia n na 1 gdy n jest wieksze niż 0. Używam tej funkcji, chociaż niezbyt często. SQR(n) daje pierwiastek kwadratowy z n i jest prawie zawsze łatwiejsze w użyciu, niż papier i ołówek.
Używam tego do robienia zgrabnych rzeczy w grafice; możliwe, że znajdziesz parę innych zastosowań dla trygonometrii. Oto parę funkcji trygonometrycznych: cosinus: COS(n) sinus: SIN(n) tangens: aż się boję użyć go w programie... przepraszam, chciałem powiedzieć TAN(n) n jest kątem w radianach. Radiany to stopnie * pi / 180.

Rozdział 5: Łańcuchy cz. 1: rzeczy niezastąpione

Chociaż potrzebujesz rozmawiać z komputerem aby napisać program i zwykle do tej rozmowy używasz matematyki, zazwyczaj też potrzebujesz łańcuchów (które mogą zawierać "ludzki" język), aby mówić do ludzi używających tego komputera. Z tego i innych powodów łańcuchy są generalnie równie ważne dla programu, jak liczby. Oto parę poleceń do pracy z łańcuchami: UCASE$ q$=UCASE$(q$) zamieni q$ na jego kopię napisaną samymi dużymi literami. Wersja dla małych liter to: LCASE$ q$=LCASE$(q$) — gdy napiszesz "Naciśnij q aby wyjść", będzie to różnica miedzy osobą potrafiącą wyjść z programu kiedy zechce, i taką, która potrafi to nieco później (gdy ktoś zwróci uwagę, że świeci mu się wskaźnik Caps Lock). Jest możliwe wyłączyć komuś Caps Lock przy użyciu kodu w programie, lecz przetwarzanie łańcucha przez LCASE$ jest łatwiejsze i bardziej eleganckie.

    q$="NAZWA@QB.Com": PRINT LCASE$(q$)
  
  nazwa@qb.com

 

CHR$ jest niezastąpione: istnieje 256 różnych znaków ASCII (np. mała litera "a" ma kod ASCII 97, a spacja - kod 32). W tym - litery, cyfry, znaki interpunkcyjne i inne pocieszne symbole (ASCII 01 to uśmiechnieta buźka). W większości jedynym sposobem uzyskania niektórych z nich jest użycie CHR$. Np. jeśli chcesz otrzymać cudzysłów na ekranie lub umieścić go wewnątrz łańcucha, możesz zastosować następujący kod: (umieść to wszystko oczywiście w tej samej linii...) ? "Uczyłem się o qbasic-u z "+CHR$(34)+mennonite's pretty good intro to qbasic"+CHR$(34)+" i jest to całkiem dobre." ...ponieważ ASCII 34 to ten sam cudzysłów, który można dostać z klawiatury.
  CHR$ pozwala także "drukować" cienie i linie ze znaków tekstowych...
Odwrotność CHR$, funkcja ASC daje nam liczbę będącą kodem pierwszego bajtu łańcucha:
     ? ASC("a") -3
     wydrukuje:
  
  94

 
 ponieważ ASCII 97, kodowane w QBasicu jako CHR$(97) to "a", a 97-3 jest 94.


LEN... n = LEN(q$) przypisze n liczbę równą liczbie bajtów w łańcuchu - - przykłady: LEN("hello") jest równe 5, LEN("jak sie masz?" jest równe 13. Spacje i znaki interpunkcyjne liczą się też. Na koniec, tak jak można przekształcić łańcuch na liczbę przy pomocy VAL, można też przekształcić liczbę na łańcuch przy pomocy STR$, więc: sp = 5 q$ = "Nacisnąłeś spację" + STR$(sp-1) + "razy." przechowa w q$ łańcuch: "Nacisnąłeś spację 4 razy."
Jesteś już daleko na drodze nauki języka QBasic, ze znajomością, jakiej przypuszczalnie wiekszość ludzi nie ma nigdy. Najlepsza rzecz, jaką możesz zrobić z tym podręcznikiem, to czytać go powoli, myśleć nad każdą stroną i jaki rodzaj programu mógłbyś napisać przy użyciu każdego z poleceń, oraz eksperymentować z kodem w QBasicu (wpisuj kod, uczy się szybciej w ten sposób, choćbyś nawet tylko "wycinał i wklejał") aby poczuć, jak się naprawdę programuje. I nigdy nie zapominaj o dobrej zabawie.

Rozdział 6: Więcej o ekranie tekstowym

Po przerobieniu PRINT, COLOR i CLS - oto nieco więcej sposobów na pracę w trybie tekstowym: LOCATE y nakazuje QBasic-owi rozpocząć drukowanie od wiersza y na ekranie. albo LOCATE y, x nakazuje drukować w wierszu y, w kolumnie x. x jest zwykle 1 - 80.
Wygląda to na pierwszy rzut oka na układ współrzędnych Kartezjusza 5) i jest dość sensowne to adresowanie tekstu jako "wiersz, kolumna". Polecenie LOCATE pozwala nam to robić, ale nie będziemy w stanie zrobić niczego w najniższym wierszu (zwykle jest to wiersz 25), chyba że w poleceniu PRINT użyjemy średnika; LOCATE 25, 1 PRINT "PRINT ze średnikiem na końcu, aby drukować w najniższym wierszu.";


 
 PRINT ze średnikiem na końcu, aby drukować w najniższym wierszu.

Również latanie kursora tam i z powrotem może być irytujące, więc: LOCATE y, x, 0 ...ukrywa go i (gdy chcemy go znowu pokazać, np. w miejscu, gdzie ktoś zamierza coś wpisać) - LOCATE y, x, 1 przywraca kursor. Jest to także jedno z tych poleceń QBasic'a, które działa nawet gdy pominiemy jedną wartość: LOCATE y, , 0 ...umiejscawia się w wierszu y i czyni kursor niewidocznym; w tym przypadku nie zmienia ono kolumny.
Pomyślmy teraz o współrzędnych, CSRLIN reprezentuje wiersz, w którym jest kursor, a POS(0) reprezentuje kolumnę. Gdy drukujemy coś na ekranie, niech a = CSRLIN i b = POS(0), zlokalizujmy (LOCATE) jakiś punkt na ekranie (powiedzmy - jego lewy górny narożnik), wydrukujemy (PRINT) coś w tym miejscu i następnie wykonamy LOCATE a, b, wówczas wskażemy miejsce, które poprzednio opuściliśmy. To może być przydatne do tworzenia pasków stanu.
VIEW PRINT jest dziwny, ale uważam go za użyteczny: gdy ekran tekstowy zwykle ma 25 wierszy, można wymusić mniejsze zakresy. VIEV PRINT 10 TO 17 zachowuje tekst obecnie wyświetlany we wszystkich 25 liniach, ale gdy drukować wewnątrz linii 10 do 17, przewija on ekran (i zmienia tekst) tylko wewnątrz linii 10 do 17. q = SCREEN (y, x) nada zmiennej q wartość ASCII znaku znajdującego się na pozycji y, x, a więc możemy nie tylko pisać na ekranie, lecz równie dobrze odczytywać z niego.
WIDTH kolumny, wiersze może byc użyteczne, ale to, co można wprowadzić jako dopuszczalne wartości dla kolumn i wierszy, zależy od używanego trybu ekranowego. W trybie tekstowym WIDTH , 50 da nam dwa razy tyle miejsca do pracy od góry do dołu ekranu (wypróbuj też 43), ale WIDTH 40 (poziomo) nie będzie zbyt dobre. Jest to omawiane dalej, przy poleceniu SHELL.

Rozdział 7: Klawiatura i linie danych

Pozostawiałem polecenia DATA na uboczu, ponieważ są irytujące, chociaż będziesz chciał wiedzieć jak one działają, gdy je zobaczysz w czyimś kodzie. Polecenia DATA (chociaż, jak powiedziałem, nie lubię ich), są dosyć łatwe w użyciu. Gdziekolwiek w głównym module programu (nawet nie martw się tym, co to jest) wstaw polecenie DATA z łańcuchami lub liczbami które mają zostać odczytane, oddzielonymi przecinkami: DATA ugh., data, statements-, that takes, me back.
    READ q$: ? q$;
    READ q$: ? q$;
    READ q$: ? q$;
    READ q$: ? q$;
    READ q$: ? q$;
 
 ugh.datastatements-that takesme back.
 Istnieją lepsze sposoby, ale to działa. Gdy używasz polecenia DATA, możesz
 zauważyć, że chcesz wstawić coś niepowtarzalnego jako ostatni łańcuch lub
 liczbę, aby procedura "wiedziała" kiedy odczyt jest zakończony, ale będziesz
 potrzebować petlę i podejmowanie decyzji (omówione dalej), aby to móc wykonać.


Jeżeli wykonujesz odczyt (READ) wiecej razy niż liczba wprowadzonych do DATA danych otrzymujesz komunikat o błędzie i program zatrzymuje się. Aby tego uniknąć, nie odczytuj więcej razy, niż jest danych (Ha!) Przy unikatowym ostatnim wpisie można powtórnie czytać od początku poleceń DATA. (QBasic szuka ich wszystkich razem, od początku do końca programu, traktując je jako jedno długie polecenie DATA.) Wstawienie staroświeckiego numeru linii (np. 20) przed pierwszym poleceniem DATA pozwoli nam zastosować polecenie: RESTORE 20 gdy tylko zechcemy wykonać powtórny odczyt. MoŻna też skierować się do innego miejsca (w naszej pojedynczej wirtualnie ciągłej linii danych), ale trzeba umieścić numery linii pomiędzy poleceniami DATA: RESTORE 70: READ b$: PRINT b$ + ",";: READ b$: PRINT b$; "."
    50
    DATA 5,6,7,8,9
    70
    DATA ok, that's enough
 
 ok,that's enough.

Sądzę, że najbardziej wszechstronnym sposobem odczytu klawiatury jest funkcja INKEY$, ale ona nie czeka na wciśnięcie klawisza, po prostu woła "Hej, klawiatura, co się dzieje?" i o ile klawisz właśnie nie zostanie naciśnięty, klawiatura mówi "...", a INKEY$ zwraca pusty, o zerowej długości łańcuch... nawet nie spację, po prostu nic pomiedzy dwoma cudzysłowami jeden przy drugim: "". Nie ma w tym niczego złego, po prostu INKEY$ pracuje tylko w pętli, tak więc zademontruję INKEY$ po pokazaniu, jak działają pętle. Tymczasem INPUT$(n) jest podobny, a nie tak podły. Pokażę to za chwilę. Żeby docenić proste piękno INPUT$(n) musimy zobaczyć jego alternatywy:
INPUT "", q$ Można wstawić coś miedzy cudzysłowy i wtedy jest to jak polecenie PRINT, ale ja wolę używać PRINT do pisania, a INPUT jako wejście. Zaletą oddzielania tych dwóch poleceń jest to, że można wstawić instrukcje i widoczny koniec wprowadzania z klawiatury w oddzielnych liniach lub różnych miejscach na ekranie. Naprawdę próbuję dać tu dobry przykład przez pokazanie INPUT użytego z przecinkiem - mógłbyś zastosować średnik: INPUT ""; q$
 ale INPUT "Wpisz swoje nazwisko - "; q$
 pokaże to na ekranie tak:
 
 Wpisz swoje nazwisko - ?  
 ponieważ, jak wszyscy wiemy, JEDYNY sposób uzyskania informacji od użytkownika
 to forma pełnego zdania zakończonego znakiem zapytania :)

 No tak. To dlatego stosowanie przecinka jest lepsze.

 Oczywiście, właściwie nie polecam stosowania polecenia INPUT zawsze.
 LINE INPUT jest stosowane w ten sam, właśnie opisany sposób (a więc
 to nie było na próżno), a jest bardziej niezawodne. Wyjaśnię:

 Powiedzmy na przykład, że zastosujemy taki kod:
 INPUT "Wpisz swoje nazwisko - ", n$
 i np. użytkownik wpisze:

 Powinien on zobaczyć taki komunikat:
 
 Wpisz swoje nazwisko - smith, john q.

 REDO FROM START?  
 Dobre, nie? 6


Jest tak, ponieważ on wpisał przecinek. Polecenie INPUT jest zaprojektowane, aby można było pobrać więcej niż jedną daną w jednym poleceniu, oddzielane są one przecinkami, jak tutaj: INPUT "Proszę wprowadzić trzy liczby, wstawić przecinki między pierwszą a drugą i także między drugą a trzecią i nie zapomnieć o tym, i nie wstawiać ich za dużo, bo moja procedura wejściowa będzie wrzeszczeć na ciebie. Dziekuję. ", a, b, c Zakładając, że twój odważny użytkownik zrozumie wszystko dokładnie, sprytne polecenie INPUT zaoszczędzi dodatkową linię kodu. Kiepski projekt!
A więc nigdy nie używam polecenia INPUT. Zamiast tego, kiedy nie chcę zamieszania, stosuję "dwuliniową" metodę uzyskiwania danych z klawiatury (są lepsze sposoby, przy użyciu INKEY$, pamiętasz?) PRINT "Proszę, wpisz swoje nazwisko. Jak długo nazwisko ma mniej niż 250 znaków i nie zawiera Enter, nie powinno być żadnych problemów:": ? LINE INPUT n$ Wszystko to jest dobre do wpisania linii danych i naciśnięcia Enter. Z drugiej strony - jeżeli mamy menu: 1. robi coś 2. robi coś jeszcze 3. robi coś całkiem innego 4. wyjście wówczas taka zachęta mogłaby wyglądać sensownie: ? "Wprowadź swój wybór - ";: LINE INPUT q$ Ale myślę, że to jest lepsze: 1. robi coś 2. robi coś jeszcze 3. robi coś całkiem innego ? "Wybierz opcję (1-3) lub naciśnij [Esc] aby wyjść :)": q$=INPUT$(1) Teraz q$ będzie mieć dokładnie jeden bajt długości i będzie to 1, albo 2, albo 3, albo Esc (Esc ma kod ASCII=27). Może to byc coś jeszcze, ale można sprawdzić czy jest to jedna z akceptowanych opcji i powtarzać to, dopóki nie pojawi się oczekiwany klawisz. Tak, znowu potrzebna pętla. Można także zamienić "1" w INPUT(1) na inną liczbę, np. 5, jeżeli chcemy dokładnie 5 klawiszy wczytać do programu. To także jest kiepski projekt, bo ludzie nie mogą zobaczyć, co wpisują, i nie mogą cofnąć się gdy nacisną niewłaściwy klawisz. Zazwyczaj będę używał INKEY$. W pętli INKEY$ może działać całkiem jak INPUT$(n), a równie dobrze może wykrywać klawisze kursora i funkcyjne.

Rozdział 8: Łańcuchy cz. 2: wyszukiwanie i manipulacja

Chociaż możnaby znaleźć lepszą procedurę wykonującą tą samą rzecz, INSTR jest bardzo szybkim i prostym sposobem sprawdzenia, czy i kiedy dany łańcuch istnieje jako część większego łańcucha: np.: Przypuścmy, że q$ przechowuje łańcuch: "the quick brown fox jumped, and stuff." i chcemy się dowiedzieć, czy łańcuch (udajemy, że nie wiemy, czym jest q$; może on pochodzić z pliku lub z klawiatury) zawiera słowo "fox", zatem kodujemy: n = INSTR(q$, "fox") n będzie się równać liczbie liter, cyfr i znaków przestankowych, które zostaną przeczytane, zanim zaczniemy czytać "fox"... W tym przypadku "f" w słowie "fox" jest 17. bajtem w q$, więc INSTR ustawi n na 17. Jeżeli łańcuch "fox" nie zostanie znaleziony w łańcuchu przechowywanym w q$, n będzie ustawione na 0. 1 123456789012345 7 90123456789012345678 "the quick brown fox jumped, and stuff."
SPACE$ jest naprawdę bardzo łatwe w użyciu. SPACE$(n) jest to łańcuch ASCII 32 (spacji), który jest n bajtów długi. q$=q$+SPACE$(10) doda 10 spacji na końcu q$. LEFT$ i RIGHT$ nie są tak potężne i kompletne jak MID$, ale odrobinę łatwiejsze w użyciu. Przechodząc wprost do przykładów, LEFT$("Seventy",5) to "Seven", a RIGHT$("elephant",3) to "ant". MID$ jest podobne:
Składnia funkcji MID$ to: MID$(q$, od_którego_bajtu_zacząć, ile_bajtów) Zatem n$=MID$("hello", 2, 4) ustawiłoby n$ na "ello", a n$=MID$("yeah, or... something", 14, 2) ustawiłoby n$ na "om". Jest również polecenie MID$, które działa w ten sam sposób, z tym wyjątkiem, że zamiast czytać łańcuch, nadpisuje go: y$="yeah, or... something" n$=SPACE$(2)+"no" MID$(y$, 13, 4)=n$ będzie zawierać "yeah, or... nothing" w y$. 4-bajtowe "some" zostało zastąpione przez 2 spacje i "no", zamieniając "something" w " nothing". Jeśli nie lubisz polecenia MID$ do nadpisywania, to jest całkowicie możliwe pominąć go zupełnie, używajac tylko "czytającą" funkcję MID$ i konkatenację łańcuchów.
Są przypadki (zwłaszcza w kodzie, jak w procedurze pierwszego menu, wcześniej) gdy nasze zmienne będą zawierały wiodące lub końcowe spacje, których nie chcemy. Gdy używamy np. STR$(n) do przekształcenia zmiennej liczbowej na łańcuch, będzie on zawierał wiodąca spację (jeśli to jest przynajmniej zero) rezerwowaną dla znaku "plus", mimo że tego znaku nigdy nie widać. Gdy liczba wypada poniżej zera, pokaże się znak "minus", ale w przeciwnym razie możemy utknąć na spacji, której nie chcemy, jak tutaj: " 55". LTRIM$(STR$(n)) usunie wiodące spacje z liczby, a LTRIM$(RTRIM$(q$)) usunie spacje z obu końców każdego łańcucha. Jest to przydatne nie tylko gdy zamieniamy liczby na łańcuchy, ale także gdy przyjmujemy dane z klawiatury lub z plików.

Rozdział 9: Praca z plikami binarnymi

Byłoby dobrze w tym miejscu nauczyć się, jak zapisywać dane do pliku i załadować je z pliku, ale będzie to znacznie bardziej użyteczne gdy nauczymy się o podejmowaniu decyzji i o pętlach. Tymczasem o tym, jak pracować z plikami binarnymi: Przede wszystkim trzeba umieścić takie polecenie na początku programu: DIM bt AS STRING * 1 W ten sposób mamy do pracy jednobajtowy łańcuch. Można deklarować dłuższe łańcuchy, ale ten będzie działał w każdym przypadku.
Zawsze otwieraj plik :) OPEN "filename.txt" FOR BINARY AS #1 Jeśli zamierzamy tylko odczytać plik, to, ściśle biorąc, nie potrzebujemy zmiennej bt, zatem nie trzeba też DIM na początku programu. Po prostu odczytujemy bajt: b$=INPUT$(1, #1) i to już wszystko. Tak, to JEST podobne do odczytu z klawiatury.
Zrób to jeszcze raz, aby odczytać następny bajt. Zwykle zapewne będziesz chciał stosować tą metodę zamiast: GET #1, q, bt gdzie q jest bajtem pliku, który chcesz odczytać... Gdy q = 57, to będzie czytany 57. bajt pliku. Do zapisu stosuje się: PUT #1, q, bt gdzie bt jest łańcuchem, który ma tylko jeden bajt (lub literę) długości. Jest to zupełnie ten sam pomysł. Parę użytecznych funkcji do pracy z plikami to: q = FREEFILE Ustawia q na numer następnego pliku, który jest wolny... Jeżeli masz otwarty plik jako #1 i drugi plik jako #2, to FREEFILE będzie równe 3. LOC(n) jest to bajt, który ustawiliśmy do czytania lub zapisu. Jeżeli już użyliśmy INPUT$(1, #1) 50 razy, LOC(1) będzie równe 51. LOF(n) warte jest zapamiętania; LOF(n) jest równe długości pliku #n (w bajtach), Jeżeli otworzyłeś plik jako #1 i LOF(1) jest 0, to plik jest pusty. Zawsze zamykaj plik, z którym zakończyłeś pracę, przez: CLOSE #1 Jeśli pracujesz tylko z jednym plikiem lub gdy nie ma żadnych innych plików, które trzeba pozostawić otwarte, użycie CLOSE bez numerów plików: CLOSE zamknie wszystkie pliki.

Rozdział 10: Odgałęzienia w programie

GOTO jest dość łatwe w użyciu; najpierw potrzebny jest numer linii: 90 lub zamiast niego - etykieta linii: hej: stosując do nazywania etykiet zasady podobne do nazywania zmiennych.
Następnie można nakazać programowi zatrzymać wykonywanie dokładnie tem, gdzie jest (zwykle program wykonuje pierwszą linię, następnie drugą linię, następnie trzecią... nie inaczej!) i kontynuować wykonywanie od tego numeru linii: GOTO 90 lub od tej etykiety linii: GOTO hej
a najłatwiejszym sposobem wykorzystania tego jest nakazać programowi wykonywanie tego samego raz po raz: 10 PRINT "not again! "; GOTO 10 A dlaczego numery linii to wielokrotność 10? Hm, dzisiaj to już nie ma żadnego uzasadnienia. Około 100 lat temu (właściwie 20 d0 30) Basic nie miał takiego edytora tekstu, w jaki został wyposażony QBasic. Był program, który po prostu oczekiwał na wpisanie linii i gdy zaczynała się ona od numeru, dodawał ją do reszty programu... Widziałeś tylko linie, które wpisywałeś, a gdy wpisałeś LIST i nacisnąłeś Enter, pokazywał się listing programu. Cała sztuka polegała na wylistowaniu programu, który miał długość większą niż około 20 linii :) Można było ułatwić dopisywanie linii, "nazywając" je wielokrotnościami 10. W ten sposób, jeśli np. potrzebowałeś linię między 10 i 20, mogłeś po prostu nazwać ją 15. Mogłeś przekopiować linię pod inny numer przez wyświetlenie jej i nadpisanie nowym numerem, ale jeżeli miałeś program o 50 liniach i wszystkie linie przyrastały o 1, a nie o 10, to wstawienie nowej linii było niemożliwe! Masz tu więc kawałek historii Basic'a. Wy, młodzi, nawet nie wiecie, jak jesteście rozpieszczani!
Czasami będziesz chciał wiedzieć, dokąd rzeczywiście trafisz, używając GOTO: kiedy utkniesz w pętli, możesz zatrzymać program, przytrzymując CTRL i naciskając klawisz C... jeśli to nie pomoże, wypróbuj CTRL + BREAK. Jest to lepsze niż CTRL + ALT + DEL, które zakończyłoby QBasic (pod Windows) albo zrestartowało komputer (pod DOS-em i prawdopodobnie też pod Linux-em).
GOSUB powinno się stosować do zastąpienia GOTO wszędzie, gdzie to możliwe. Według współczesnych standardów stałe używanie GOTO nie jest uważane za dobre programowanie. GOSUB jest nieco bardziej skomplikowane, ale znacznie bardziej przydatne. Pierwszą rzeczą do zrobienia jest wstawienie punktu zatrzymania pomiędzy głównym programem i podprogramami. W celu wprowadzenia: podprogram jest częścią programu, do której prowadzi odgałęzienie przy pomocy GOSUB i która jest opuszczana przez RETURN. Podprogramy same są jak miniaturowe programy.
W tym celu wstawiamy: END na końcu głównego programu, aby go w tym miejscu zatrzymać. PONIŻEJ polecenia END wstawiamy wszystkie nasze podprogramy. Np. tu mamy podprogram czyszczacy ekran, witający użytkownika i zmieniający kolorz powrotem na biały: start: CLS: COLOR 10 ? " ** program, który nic nie robi, lecz startuje **" ? " 2005 by mennonite" COLOR 7 ? RETURN Wewnątrz głównego programu, to jest przed poleceniem END, stosujemy: GOSUB start i to uruchomi kod z podprogramu, a następnie powróci do programu głównego tuż za poleceniem GOSUB! Pojąłeś to wszystko? Jeszce raz: GOSUB start END CLS: COLOR 10 ? " ** program, który nic nie robi, lecz startuje **" ? " 2005 by mennonite" COLOR 7 ? RETURN
Jest to jedna z najważniejszych cech programowania w językach takich jak Basic i QBasic. Poczuj się w tym swobodnie; gdy pisze się dłuższy program, jest prawie niemożliwe obejść się bez takich podprogramów. Dlaczego wstawiliśmy punkt zatrzymania programu, zanim uruchomił się podprogram? Bo gdy program dojdzie do tego miejsca, zacznie znowu uruchamiać znajdujący się tu podprogram - napotka polecenie RETURN (wróć), nie mając żadnego GOSUB wywołującego ten podprogram... Program będzie myślał (oto, jak w rzeczywistości głupie są komputery...) "WRÓĆ? Wróć dokąd?!", wpadnie w szał i odmówi dalszej roboty. Nie jest to zazwyczaj niebezpieczne, ale wygląda nieudolnie.
REM - to nie będzie robić niczego. Jest to stary sposób dodawania komentarzy do kodu programu. I ciagle działa... Ale łatwiej jest stosować apostrof: ' - to równiez nie będzie robić niczego. ' Komentarze warto stosować, bo kiedy ktoś inny zajrzy do twojego kodu, będzie ' mógł łatwiej wyobrazić sobie, co to wszystko robi. (A czasami, kiedy zajrzysz do programu, który napisałeś dawno temu, będziesz też chciał mieć do niego komentarz.) Naprawdę dobrą zasadą byłoby: ZAWSZE wstawiać komentarz na początku programu, który przynajmniej mówi, co ten program robi. W ten sposób daleko zajdziesz.

Rozdział 11: Podejmowanie decyzji

Hej, teraz uczynimy program sprytniejszym. Obecnie twój kod robi to: [rób to] ale możemy go zrobić tak inteligentnym, że będzie wiedział Tak czy Nie! [rób to... ale nie, kiedy nie chcę.] Musisz rzecywiście dobrze wiedzieć, czego chcesz :D Oto przykład IF...THEN, używający bardzo nieprzyzwoitego polecenia GOTO :O
x=0 etykieta:
 x=x+1
 IF x > 5 THEN ? x            ' > znaczy "większy niż"
 IF x < 10 THEN GOTO etykieta ' < znaczy "mniejszy niż"

 który będzie to drukował na ekranie      ->


  6
  7
  8
  9
  10
dopóki x nie jest wieksze niż 5, nie będzie drukować, a gdy x = 10, nie powróci do 'etykieta'.
W tych przykładach używam ciagle GOTO, ponieważ jest ono łatwe do nauczenia. Czasem, gdy coś jest łatwiejsze do nauczania, jest też łatwiejsze do nauczenia się... ale bez względu na to, niedługo poznasz parę poleceń, które pomogą wyeliminować stosowanie GOTO, a są doskonałe do pokazanych już przykładów; są DWIE pary doskonale pasujących komend, które można stosować podobnie łatwo.
A teraz inny przykład: PRINT "jak się nazywasz? - " LINE INPUT q$: q$=LTRIM$(RTRIM$(q$)) 'usuwa spacje 'standardowa odpowiedź jim$ = "I am James T. Kirk... (Captain... of) " jim$ = jim$ + "the Starship... Enterprise..." ?:? "czy jesteś Obcym płci żeńskiej? (t/n)" Widzisz? Nie trzeba wiele, aby zrobić program myślący całkiem jak Obcy płci żeńskiej, zwłaszcza taki z lat 60.!
Ten przykład używa AND, spróbujmy takiego który używa OR i dorzućmy jeszcze ELSE... 7) PRINT "jak się nazywasz? - " LINE INPUT q$: q$=LTRIM$(RTRIM$(q$)) 'usuwa spacje o$=LCASE$(q$) IF INSTR(o$,"bones")>0 OR INSTR(o$,"mccoy")>0 THEN ? "i need mr. sulu in sickbay, he thinks we"; ? " really need a pilot to fly this thing!" ELSE ? "damnit, " + q$ +", you're not a doctor!" END IF
To jest blok IF... THEN 8) Działa on jak jedna długa linia, która nie mieści się na ekranie: IF INSTR(o$,"bones")>0 OR INSTR(o$,"mccoy")>0 THEN ? "i need mr. sulu in sickbay, he thinks we";: ? " actually need a pilot to fly this thing!" ELSE ? "damnit, " + q$ +", you're not a doctor!"
A oto sposób na sprawdzanie wielu warunków przy użyciu SELECT... CASE: ? "wpisz liczbę "; : LINE INPUT q$ SELECT CASE VAL(q$) CASE 1 TO 5: ? "twoja liczba to co najmniej jeden i najwyżej pięć." CASE 6 TO 10 ? "twoja liczba to co najmniej sześć i najwyżej dziesięć." CASE IS = 15 ? "piętnaście? jak to dostałeś?" CASE IS > 20 ? "więcej niż 20? nie bawię się!" ' bez szczególnego powodu... CASE ELSE: ? "nie rozumiem tej odpowiedzi." END SELECT
"CASE ELSE", oczywiście, wykonuje kod następujacy po tej linii, jeżeli wcześniej program nie napotkał żadnego innego przypadku (case) zgodnego warunku. CASE jest też naprawdę wygodne gdy używa się wiele wartości: SELECT CASE LTRIM$(RTRIM$(LCASE$(q$))) CASE "susie", "janie", "jamie", "josie", "connie", "carrie", "mary" ? "czy już z wami chodziłem?" CASE ELSE ? "co robisz we wtorek?" END SELECT

Rozdział 12: Pętle w programie

Jak obiecałem, oto dwa sposoby na usunięcie GOTO z wcześniejszego przykładu: x=0 etykieta: x=x+1 IF x > 5 THEN ? x ' > znaczy "większe niż" IF x < 10 THEN GOTO etykieta ' < znaczy "mniejsze niż" Jednym sposobem jest DOO... LOOP. Działa tak, jak to: etykieta: GOTO etykieta jeżeli nie napotkano warunku
Ale lepiej jest tak: DO: 'nie trzeba etykiety linii! LOOP UNTIL warunek=1 9) I przykład: x=0 DO x=x+1 IF x > 5 THEN ? x LOOP UNTIL x >= 10 ' >= znaczy "większy niż, lub równy"
Gdybyś miał bardzo długą (bardzo długo powtarzającą się) pętlę: x = 0 DO x = x + 1: IF INKEY$ = CHR$(27) THEN EXIT DO ' zatrzymuje pętlę gdy Esc ^^^^ zostanie naciśnięty... IF x > 5 THEN PRINT x LOOP UNTIL x >= 2 ^ 17 mógłbyś zatrzymać ją "ze środka" przez INKEY$! (2^17 to oczywiście 2 do potęgi 17, 131072 - dużo!)
Jak wspomniano już wyżej, INKEY$ nie czeka na naciśnięcie klawisza. Jeżeli nacisnąłeś klawisz (w tej pętli INKEY$ sprawdza to wiele razy na sekundę), to INKEY$ wykryje to (jest parę wyjątków, jak np. klawisz CTRL...), ale program będzie biegł, czy klawisz będzie naciskany, czy też nie. Jest też możliwe wychwycić przy pomocy INKEY$ ostatnie naciśnięcie klawisza, ponieważ istnieje bufor śledzący ostatnio naciśnięte klawisze. Może on przepełnić się, szczególnie gdy trzymamy klawisz nacisnięty cały czas, i można użyć INKEY$ do wyczyszczenia tego bufora, aby komputer nie piszczał.
EXIT DO, użyte jak wyżej, zatrzymuje pętlę DO... LOOP i przenosi wykonywanie programu do tej jego części, która znajduje się poniżej pętli. Innym sposobem jest uzyskanie tego przy użyciu OR: x = 0 DO x = x + 1 IF x > 5 THEN PRINT x LOOP UNTIL x >= 2 ^ 17 OR INKEY$ = CHR$(32) 'klawisz spacji wysyła kod ASCII = 32.
FOR... NEXT jest sposobem na pętle o określonej ilości powtórzeń. 'to jest pętla krótsza niż poprzednio, uzyskana przez FOR... NEXT FOR x=1 TO 10 IF x>5 THEN ? x NEXT x lub nawet: FOR x=5 TO 10 ? x NEXT x
Aby otrzymać przyrosty mniejsze niż 1, wypróbuj STEP: FOR x=5 TO 10 STEP .5 ? x ' wypisze 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10 NEXT x Tu dodajemy 0.5 zamiast 1. Można też równocześnie odliczać wstecz i po więcej niż 1: FOR x=10 TO 1 STEP -2 ? x ' wypisze 10, 8, 6, 4, 2... ale nie 1, bo weźmie 2 i wykona znowu ' KROK -2, co da 0, czyli mniej niż zakres 10 do 1... NEXT x
Aby odtworzyć funkcjonalność INPUT$(1) przy użyciu INKEY$, zastosujemy zapis: DO: q$=INKEY$: LOOP UNTIL q$ <> "" ' <> znaczy "różny od" Nawiasem mówiąc, możesz zechcieć poznać inny rodzaj petli DO... LOOP: DO WHILE warunek = prawda LOOP ( WYKONUJ, DOPÓKI warunek = prawda ZAPĘTLIJ )

Rozdział 13: Praca z plikami tekstowymi

Praca z plikami tekstowymi różni się nieco od plików binarnych... po pierwsze, sposób otwarcia pliku zależy od tego, czy będziemy plik zapisywać, czy odczytywać. Z tego i paru innych powodów wolę obsługiwać pliki tekstowe tak, jakby były binarne i otwierać je w trybie dostępu binarnego. Sam uznasz, zaczynając, czy to jest łatwiejsze, czy też nie. Często bywam nazbyt leniwy i otwieram pliki tekstowe jako tekstowe. Aby zapistać następujące linie do pliku: To jest linia. Opuść następną: OK, to jest inna linia... I to także linia.
zawsze OTWIERAJ plik: OPEN "nazwa.txt" FOR OUTPUT AS #1 Jeśli zrobisz to w ten sposób, będziesz startować od zera... to znaczy - plik "nazwa.txt" zostanie wyczyszczony i będzie pusty, jeśli przedtem taki nie był. Z tego powodu będziemy teraz używać APPEND (DOŁĄCZ). APPEND, zamiast wymazywać zawartość pliku, dopisuje na jego końcu. Jeżeli zapisujesz do logu, to jest dokładnie to, czego potrzebujesz. Może to być problematyczne gdy przechowujesz dane dla zapisanej gry. W takim przypadku możesz preferować OPEN... FOR OUTPUT Mimo to: OPEN "filename.txt" FOR APPEND AS #1 Teraz zastosujemy polecenie PRINT do zapisania naszych linii do pliku. Otwarty właśnie plik ma nr 1, więc użyjemy PRINT #1, q$ PRINT #1, "To jest linia. Opuść następną:" PRINT #1, "" PRINT #1, "OK, to jest inna linia..." q$ = "I to także linia." PRINT #1, q$
Ostatnia linia została zapisana odmiennie, aby jeszcze raz zademonstrować, że łańcuch jest przede wszystkim łańcuchem i dlatego można równie dobrze użyć PRINT #1, q$ jak i wyrażenie w cudzysłowach; oba są przykładami prawidłowych łańcuchów. Zawsze ZAMYKAJ (CLOSE) plik po zakończniu z nim pracy: CLOSE #1 Jeśli pracujesz tylko z jednym plikiem, albo jeśli nie masz innych plików które potrzebujesz mieć otwarte, użycie CLOSE bez numeru pliku: CLOSE zamknie wszystkie pliki, które otworzył program.
Teraz aby odczytać plik, otworzymy go znowu, tym razem do odczytu: OPEN "filename.txt" FOR INPUT AS #1 Plik tekstowy jest odczytywany po jednej linii na raz. Jednym z najbardziej niezawodnych sposobów jest zastosowanie LINE INPUT wewnątrz pętli: DO: LINE INPUT #1, q$ PRINT q$ ' drukuje linię na ekranie Program powinien wiedzieć, kiedy zakończyć zapętlanie. EOF(1) jest warunkiem który stanie się prawdziwy gdy zostanie osiągnięty koniec pliku. Może on kończyć pętlę LOOP w ten sposób: LOOP UNTIL EOF(1) Możesz przekonać się, że taka pętla będzie lepsza do odczytu plików tekstowych: DO WHILE EOF(1) = 0: LINE INPUT #1, q$: LOOP ' obsługuje też pliki ' o zerowej długości
Oczywiście, jeżeli chcemy odczytać tylko pierwszą linię z pliku, to pętla nie będzie potrzebna, wystarczy LINE INPUT #1, q$. Zamknijmy plik, kiedy skończymy pracę z nim. Nie ma otwartych żadnych plików, które powinny pozostać otwarte, więc wystarczy użyć ogólnie CLOSE

Rozdział 14: Grafika

Do tej pory skupialiśmy uwagę na poleceniu komputerowi, aby umieszczał na ekranie litery lub liczby, w wyszczególnionym kolorze. Jednak większość osób uczących się, jak programować, będzie chciało znać sposób kontrolowania każdego punktu na ekranie, czyli każdego piksela. Nie jest nieprawdopodobne, że twój komputer uruchamia Windows w rozdzielczości 1024 lub więcej pikseli w poziomie na 768 lub więcej piseli w pionie. W QBasic jest możliwe osiągnięcie takiej rozdzielczości, ale nie bez specjalnego kodu lub bibliotek, które rozszerzają zwykłe możliwości QBasic-a.
Domyślnie, nasz wybór będzie nieco bardziej ograniczony. Aby pracować z grafiką, trzeba najpierw zmienić bieżący tryb pracy ekranu... Najbardziej przydatne (i często używane) tryby ekranowe to 0, 9, 12 i 13. Pozostałe, ogólnie biorąc, są dedykowane starszym komputerom i mają większe piksele (i mają ich mniej) oraz mniej kolorów. SCREEN 0 jest trybem wyłącznie tekstowym. Jest możliwe w SCREEN 0 pracować w rozdzielczości nawet 80 x 100, jeśli jesteś sprytny, lecz nawet wtedy będziesz ograniczony do maksymalnie 8 zwykle używanych kolorów (czasem 16, ale nie zawsze) i twoje "piksele" będą ogromne i prostokątne.
Pierwszym faktycznym trybem "graficznym" jest SCREEN 1, ale pozwala on tylko na rozdzielczość 320 x 200 i 4 kolory. Zapoznamy się również z wyższymi trybami graficznymi, ale najpierw zobaczmy, jak działają PSET i CIRCLE. SCREEN 1 zmienia tryb ekranowy na 1; jest to proste. Teraz przerzućmy się z powrotem do polecenia LOCATE y, x i współrzędnych kartezjańskich... prawie... Powiedzmy że: x = 20: y = 4 Też proste. Aby postawić kropkę w punkcie o tych współrzędnych, wstawiamy: PSET (x, y) a jedyną różnicą od Kartezjusza jest, że 0,0 znajduje się w lewym górnym rogu ekranu. Wszystkie punkty na ekranie w QBasic-u biegną od 0 do największej dostępnej liczby, w tym przypadku od 0 do 319 wszerz i od 0 do 199 w dół, daje to oczywiście całkowitą rozdzielczość 320 x 200. x, y (lub, w tym przypadku, 20, 4) oznaczają 20 pikseli od lewej i 4 od góry.
A teraz, dla okregu, zastosujemy prawie taki sam sposób: CIRCLE (x, y), 10 Tym razem narysowaliśmy trochę poza ekranem. Okrąg narysowany został ze współrzędnymi x=20 i y=4, ale ma promień (szerokość podzielona przez 2) = 10. Żeby rzecz całą zmieścić na ekranie, ustawmy y gdzieś powyżej 9. Punkt x,y oznacza środek okręgu.
Pokażemy też sposób na zmianę kolorów, ale przejrzyjmy najpierw najbardziej przydatne tryby ekranowe: Zaczynając z drugiego końca, SCREEN 13 pozwala zastosować do 256 kolorów równocześnie i można określić każdy element tej 256-kolorowej palety, uzyskując zakres barw zbliżony jakością do plików fotograficznych. Z drugiej strony SCREEN 13 pozwala tylko na rozdzielczość 320 x 200. Niezliczone profesjonalne i dobrze znane gry pod DOS zostały stworzone przy użyciu tego trybu, a QBasic jest (w końcu) językiem programowania dla DOS-a.
Wiekszą ilość pikseli (ale mniej kolorów) oferuje SCREEN 12. Ten tryb wygląda bardziej "profesjonalnie", nawet jeśli pozwala na te same 16 domyślnych kolorów, których używa tryb tekstowy. Na szczęście kolory mogą być przełączane na inne poleceniem PALETTE. Ten tryb daje rozdzielczość 640 x 480. Nie jest to wiele, ale może być to najlepsze, co można uzyskać (albo co potrzeba) przez długi czas używania QBasic-a.
SCREEN 9 jest nieco inny, niż SCREEN 12. Ma również 16 kolorów, ale zamiast rozdzielczości 640 x 480 - tylko 640 x 350. Na wyświetlaczach LCD obraz może być nieco mniejszy (rozciąganie obrazu na LCD może nie działać dobrze, SCREEN 9 jest najlepszy na monitorach lampowych) oraz jeżeli nie zmienimy parametru "aspect", nasze "okręgi" i "kwadraty" mogą być nieco bliższe elipsom i prostokątom - ale SCREEN 9 ma dwie graficzne zalety, które niekiedy czynią go lepszym niż SCREEN 12: jedno - to że, podobnie jak w SCREEN 0, można zmieniać kolor tła (nawet kiedy drukujemy tekst) w SCREEN 9, oraz że jest to tryb o najwyższej rozdzielczości który jeszcze ma zapasową "stronę" do stosowania z PCOPY.
PCOPY jest fantastycznym poleceniem, które pozwala za jednym zamachem skopiować cały ekran i potem go odtworzyć. Np. jeżeli chcemy narysować skomplikowane tło i na nim u góry ruchomy obiekt, można zapisać kopię naszego ekranu przy pomocy PCOPY 0,1 - narysowac coś, a następnie przywrócić nasz poporzedni ekran (minus to, co właśnie narysowane) przez PCOPY 1,0. Możemy preferować pracę z "duszkami" (sprites), ale PCOPY ma swoje zastosowania, a nie działa w trybach 12 i 13.
Oto zestawienie trybów ekranowych, z którymi będziemy pracować w tym podręczniku: tryb rozdziel. kolory, kolory tła działa z PCOPY? 0 tylko txt 16, plus 8 kolorów tła (8 na raz) t 1 320 x 200 4 na raz z 8, 1 na raz z 16 (tryb 13 jest lepszy) t 13 320 x 200 256 n 12 640 x 480 16 n 9 640 x 350 16, plus 16 kolorów tła (1 na raz) t
Mając te tryby dostatecznie omówione, zmieńmy teraz tryb na: SCREEN 12 Nie zawsze będzie to potrzebne, szczególnie po zmienie trybów, ale w innym przypadku zastosujmy także: CLS Działa to w trybach graficznych równie dobrze jak w trybie tekstowym. Oto parę sposobów, jak zmienić kolor tła. Na razie - pomalujmy go. Aby pomalować tło na niebiesko, użyjemy PAINT (0, 0), 1 I mamy teraz ekran pełen niebieskich pikseli. A co z innymi sposobami? OK, najpierw narysujmy kilka linii.
Aby narysować linię, zaznaczamy pierwszy punkt (x, y) i drugi punkt (x2, y2) i łączymy je razem, jak tutaj: x = 370 y = 45 x2 = 40 y2 = 112 LINE(x,y)-(x2,y2), c To rysuje czarną linię, bo nic nie ustawia c na inną wartość niż 0, a zero to kolor czarny.
Oto para linii, zielony to kolor 2: LINE (451, 85)-(491, 300), 2 LINE (104, 290)-(421, 290), 2 A co z prostokątami? Aby utworzyć prostokąt, wyobraźmy sobie, że jeden koniec linii oznacza narożnik prostokąta, a drugi koniec oznacza przeciwległy narożnik, po przekątnej.
Aby narysować purpurowe prostokąty przy użyciu powyższych współrzednych (purpura to kolor 5), dodajemy na końcu ,B: LINE (451, 85)-(491, 300), 5, B LINE (104, 290)-(421, 290), 5, B Oczywiście drugi "prostokąt" ma niezmieniony y i dlatego nie ma wysokości. Poprawmy to: LINE (104, 290)-(421, 294), 5, B
Zróbmy prostokąty o połowę mniejsze: LINE (451, 85)-(471, 193), 5, B LINE (104, 290)-(263, 292), 5, B i wypełnijmy je kolorem, przez zamianę B na BF: (znacznie szybsze niż PAINT!) LINE (451, 85)-(471, 193), 5, BF LINE (104, 290)-(263, 292), 5, BF (i, niestety, nie da się tak zrobić wypełnionego okręgu - CIRCLE.)
Oto szybszy sposób na zmianę koloru ekranu niż PAINT: c = 7 'biały LINE (0,0)-(639)-(479), c, BF 'rysuje biały prostokat tak duży jak cały 'ekran To działa również w SCREEN 13. Przełączmy się na ten tryb: m = 13 SCREEN m i narysujmy okrąg (CIRCLE) na środku ekranu, z promieniem 20: CIRCLE (160,100), 20 i wypełnijmy okrąg przy pomocy PAINT: PAINT (160, 100), 15
Jeżeli zamierzamy określić kolor czegokolwiek, możemy przyjrzeć się pikselom, z których to jest zrobione. Popatrzmy na jeden piksel: c = POINT(150, 90) ? c 15 Kolor 15, jaskrawobiały! Ten punkt (x 150, y 90) znajduje się wewnątrz okregu. A co ze 140, 120? ? POINT (140, 120) 0 Czarny - ten punkt jest na zewnątrz okręgu.
Zmieńmy również kolor. Możemy zmienić paletę (PALETTE), więc nie będzie potrzebne powtórne rysowanie. Aby zmienić jaskrawobiały na kolor bardziej jędrny, wyjdziemy z wartości kolorów RGB (czerwony-zielony-niebieski): red = 225: green = 129: blue = 112 Ale QBasic używa liczb od 0 do 63, a większość wartości RGB leży w zakresie 0 do 255. Żaden problem: red = INT(red / 4) green = INT(green / 4) blue = INT(blue / 4)
Aby zmienić paletę, zastosujemy polecenie PALETTE z następującym wzorem" PALETTE 15, 256 ^ 0 * red + 256 ^ 1 * green + 256 ^ 2 * blue I teraz sprawdźmy znowu kolor okręgu: PRINT POINT(150, 90) 15 Ciągle jest jaskrawobiały? POINT zwraca wartość atrybutu, a nie rzeczywiste wartości RGB. Kolor 15 jest domyślnie jaskrawobiały, ale teraz został zmieniony na cielisty przez PALETTE. Jest to jednak wciąż kolor 15.
Zanim pożegnamy grafikę, jeszcze parę rzeczy... To spowoduje błąd w trybie SCREEN 13: COLOR 5, 15 Utknęliśmy z kolorem 5 na czarnym tle. Powinniśmy zmienić paletę: PALETTE 0, 256 ^ 0 * 63 + 256 ^ 1 * 63 + 256 ^ 2 * 63 'jaskrawobiały
Za to w SCREEN 9 można rownież: COLOR 5, 15 Każdy z nich będzie zmieniał kolor tła, lecz jeżeli nie będzie to tryb pełnoekranowy (zamiast w oknie), PALETTE może nie działać. Oczywiście jest to w każdym razie dość rzadkie - uruchamianie trybów graficznych w oknie. (W Windows 98 polecenie SCREEN inne niż SCREEN 0 powoduje automatyczne przejście QBasica z pracy w oknie do trybu pełnoekranowego - przyp. tłum.)
I na koniec, DRAW. Działa ono szczególnie dobrze w: SCREEN 12 DRAW umiescza na ekranie grafikę przy pomocy zestawu instrukcji łańcuchowych, bardzo podobnie jak "LOGO". Polecenie do zmiany koloru na zielony to: "c2" gdzie 2 jest liczbą reprezentującą kolor zielony, podobnie jak to jest w innych poleceniach graficznych oraz przy tekście w trybie tekstowym. Cztery pierwsze instrukcje kierunkowe są proste, L przesuwa w lewo, R w prawo (Right), D przesuwa w dół, a U w górę (Up). Jest możliwe użyć kilka instrukcji równocześnie: DRAW "c14r5u7" będzie rysować (draw) żółtą linię przesuwając się 5 pikseli w prawo i następnie 7 pikseli w górę.
Pozostałe kierunki, wliczając w to przekątne, są kodowane literami zgodnie z następującym diagramem: h u e ^ l <- -> r v g d f Aby przesunąć niewidoczny "kursor graficzny" bez rysowania (jak "pu" lub "pen up" w LOGO), zaczynamy każdą instrukcję od b: DRAW "u5 bu2 l5 bd7" będzie rysować linię 5 pikseli w górę, przesunie się w górę o 2 bez rysowania, narysuje 5 w lewo i przesunie się o 7 pikseli w dół bez rysowania.
Najlepszą rzeczą w poleceniu DRAW jest jego zdolność do przerysowywania pod jednym z 360 różnych kątów. Ten program: DRAW "ta " + STR$(INT(360 / 3)) + "u50" DRAW "ta " + STR$(INT(360 / 3 * 2)) + "u50" DRAW "ta " + STR$(INT(360 / 3 * 3)) + "u50" będzie rysował trójkąt równoboczny o bokach po 50 pikseli. Jego krótsza wersja to: DRAW "ta120 u50 ta240 u50 ta360 u50" A ta wersja będzie rysować pięciokąt: DRAW "ta " + STR$(INT(360 / 5)) + "l20" 'uwaga: przed 20 jest l a nie jedynka DRAW "ta " + STR$(INT(360 / 5 * 2)) + "l20" DRAW "ta " + STR$(INT(360 / 5 * 3)) + "l20" DRAW "ta " + STR$(INT(360 / 5 * 4)) + "l20" DRAW "ta " + STR$(INT(360 / 5 * 5)) + "l20"

Rozdział 15: Błędy

Zrobiłbyś dobrze, zawsze wyłapując i obsługując błędy... Prawie nigdy nie zawracam sobie tym głowy. Jeżeli dobrze napiszesz swój program, możesz poradzić sobie, aby ich uniknąć. Już mniej to się stosuje do dużych programów. Oczywiście, czasami wyłapywanie błędów jest całkiem użyteczne. Czy stosujesz obsługę błędów, czy nie, program, napotkawszy błąd, może przekazać użytkownikowi nazwę błędu. Jeżeli nie wychwytujesz błędów, program na dodatek zakończy się. Jeżeli stosujesz obsługę błędu, masz okazję przekazania użytkownikowi bardziej przyjaznej interpretacji problemu: "Przepraszam, plik o takiej nazwie nie istnieje w tym folderze." lub nawet naprawić to tak, że program może biec dalej: "Taki plik nie istnieje. Utworzyć go? (T/N)"
Możesz nawet wyłapywać błędy, aby wykryć, które tryby ekranowe nie działają. Jak wspomniano w rozdziale o grafice, w QBasicu jest kilka trybów graficznych, a zaczynają się od SCREEN 0 czyli trybu tylko-tekst aż po SCREEN 13. A więc można nakazać programowi przejść przez wszystkie możliwe tryby: okscreen$ = SPACE$(14) ON ERROR GOTO oops FOR q = 0 TO 13 SCREEN q NEXT q: nomorec = 1 i wtedy, gdy program spróbuje wykonać SCREEN [w którymś z niedostępnych trybów], to spowoduje błąd nr 5 i przejście do podprogramu "oops": oops: IF nomorec = 0 THEN IF ERR = 5 THEN MID$(okscreen$, q + 1) = "x" END IF RESUME NEXT który dodaje "x" pod częścią zmiennej okscreen$ dotyczącą tego trybu.
Polecenie RESUME NEXT mówi programowi "nie przejmuj się tym ostatnim błędem..." i wtedy program wykonuje następną linię, którą jest "NEXT q" albo pętla FOR... NEXT. Gdy już wypróbujemy wszystkie tryby ekranowe, możemy wrócić do SCREEN 0, który jest trybem domyślnym i powinien działać zawsze: SCREEN 0: WIDTH 80 'WIDTH 80 powinno działać zawsze; gdy nie - usuń go aby wydrukować skalę dla liczb od 0 do 13: PRINT " 1111" PRINT "01234567890123" a poniżej: PRINT: PRINT okscreen$ END 'pamiętaj o wstawieniu END między programem i podprogramami I teraz program będzie wstawiał małe "x" pod numerani trybów, które nie działają na twoim komputerze!
Na wypadek, gdybyśmy przelecieli przez ten dział zbyt szybko: oto przegląd: ON ERROR... GOTO etykietalinii mówi programowi, do jakiego podprogramu przejść, gdy przytrafi się błąd. Nie istnieje "ON ERROR... GOSUB". IF ERR=n THEN będzie wykonywać coś w odpowiedzi na określony błąd... (do obsługi tej części można także użyć SELECT CASE ERR). RESUME NEXT powraca do tej części programu, w której wystąpił błąd, ale do linii NASTĘPNEJ po tej, która spowodowała błąd.
Uwaga: Lista kodów błędów znajduje się w Pomocy do QBasic 1.1... Błąd nr 5 to "Illegal function call" (Niedozwolone wywołanie funkcji) - otrzymujemy ten błąd gdy próbujemy przejść do niedostępnego trybu ekranowego, chociaż istnieją też inne możliwe powody. Listy takiej nie ma w QB 4.5 (dostarczano go z prawdziwym papierowym podręcznikiem w czasach, gdy jeszcze istniały papierowe podręczniki), jednak lista ta powinna być dość łatwa do znalezienia on-line, (np. http://deger.republika.pl/QBhelpPL/contents/codes.htm#errors) a QBasic 1.1 jest dostępny za darmo na stronie Microsoftu. Jest jeszcze co najmniej parę innych poleceń do obsługi błędów, ale przypuszczalnie nie będziesz ich nigdy potrzebował.

Rozdział 16: Pomiar czasu

Istotne dla grafiki i gier, a przydatne do wielu innych rzeczy, które możemy zechcieć zrobić, oto są popularne funkcje dające dostęp do wewnętrznego zegara w komputerze i pomiaru czasu: TIMER (wspominana wcześniej - do użycia z RANDOMIZE) jest funkcją numeryczną, która zwraca liczbę sekund, jaka upłynęła od północy. W ten sposób przy użyciu TIMER można kodować opóźnienie: delay = .5 'delay = opóźnienie w sekundach, tutaj - pół sekundy t = TIMER + delay: DO: LOOP UNTIL TIMER > t albo TIMER < t - delay * 1.2
Jest również możliwe wytwarzać krótkie opóźnienia stosując FOR q=1 TO d: NEXT q gdzie d jest dużą liczbą, ale im szybsze są komputery, tym bardziej staje się to nieprzydatne. Jest to zawodne także z tego powodu, że opóźnienie jest dłuższe na wolniejszych maszynach i nie może być ustalone dokładnie dla dowolnego komputera, a tylko dla tego, na którym zostało wypróbowane.
SLEEP powoduje, że program siedzi cicho i nie robi zupełnie nic, dopóki nie naciśnie się klawisza, a użyte z liczbą: SLEEP 5 działa w ten sam sposób, tylko przestaje oczekiwać na klawisz po upływie tej liczby sekund. Jeśli jest użyte w programie znaczną liczbę razy (szcególnie w pętli), bufor klawiatury przepełnia się i komputer wydaje irytujący terkot. Można wyczyścić ten bufor stosując INKEY$, ale myślę że lepiej uważać SLEEP za substytut q$=INPUT$(1) albo za odmianę przykładu kodu zliczania czasu (wsadzoną do funcji INKEY$), a ja zazwyczaj stosuję SLEEP tylko gdy jestem na tyle zajęty innymi rzeczami, że unikam wpisywania nawiasów: (przykład: SLEEP jest bardzo przydatne podczas debuggingu.)
TIME$ ma podwójne zastosowanie - do sprawdzania i do do ustawiania czasu. Aby sprawdzić (bieżący) czas, niech q$=TIME$, co wpisze do q$ ośmiobajtowy łańcuch składający się z "hh:mm:ss", gdzie hh będzie parą cyfr oznaczających godzinę, mm - minuty, a ss - sekundy. Aby ustawić czas, tworzymy łańcuch o tym samym ośmiobajtowym formacie "hh:mm:ss" i TIME$=q$ DATE$ działa tak jak TIME$, sprawdza i ustawia datę systemową w formacie miesiąc-dzień-rok jako "mm-dd-rrrr". Uwaga: Jeśli komputer znajduje się poza USA, jest możliwe, że jego system operacyjny, a zatem i QBasic będzie używał innego formatu wyświetlania daty. (QB w polskiej wersji Windows 98 wyświetla jednak format amerykański: 04-15-2007; przyp. tłum.)

Rozdział 17: Tablice

Tablice czynią zmienne bardziej użytecznymi i oferują potężny sposób na zarządzanie danymi. Np. następujący kod: READ a READ b READ c READ d READ e: PRINT a;b;c;d;e; DATA 52,21,19,45,73 można zamienić na: FOR q=1 TO 5 READ ab(q) NEXT q FOR q=1 TO 5 ? ab(q); NEXT q ... co nie wygląda zbyt spektakularnie, dopóki nie mamy nieco więcej niż pięć zmiennych do nazwania.
Inna zaleta tablic to to, że nie potrzebujemy wiedzieć dokładnie, jak dużo elementów będzie przechowywane. Np.: DIM q$(1 to 100) OPEN "plik" FOR INPUT AS #1 DO: c=c+1 LINE INPUT #1, q$(c) LOOP UNTIL EOF(1) or c => 99 q$(c+1) = CHR$(26): c=0: close otworzy "plik" i przechowa każdą wczytaną linię w q$(c); c oznacza, która linia jest tutaj przechowywana. Ten przykład ogranicza mozliwą liczbę linii do 99 i ustawia ostatnią linię na ASCII 26 (eof), aby zaznaczyć która linia jest tą ostatnią.
Zauważ użycie DIM(1 to 100), które jest wymagane dla tablic o rozmiarze większym niż 10 jednostek. Użycie DIM jest także niezbędne dla tablic wielowymiarowych: DIM twod(1 to 5, 1 to 5) AS INTEGER 'integers - liczby całkowite - 'pozwalają stosować większe tablice przydzieli pamięć dla tablicy o 5 jednostkach, a każda jednostka będzie także miała 5 podjednostek: twod(1,1) twod(2,1) twod(3,1) twod(4,1) twod(5,1) twod(1,2) twod(2,2) twod(3,2) twod(4,2) twod(5,2) twod(1,3) twod(2,3) twod(3,3) twod(4,3) twod(5,3) twod(1,4) twod(2,4) twod(3,4) twod(4,4) twod(5,4) twod(1,5) twod(2,5) twod(3,5) twod(4,5) twod(5,5)
Można zauważyć, ze chociaż 3-wymiarowe tablice są możliwe (a także jeszcze większe - QB Help określa maksymalną liczbę wymiarów na 60! - przyp. tłum.), ograniczenia QBasic-a nie pozwalają, aby trójwymiarowa tablica była wystarczająco duża, aby być zbyt czesto przydatna. (Znam kogoś, kto stosuje taką tablicę do gry w karty, i można ją użyć we własnym programie rozwiązującym kostkę Rubika... chociaż taki program już istnieje.)

Rozdział 18: Wykorzystanie wewnętrznego głośnika

PLAY wygrywa tony (wymienione w zmiennej łańcuchowej), które mogą być nutami muzycznymi. Np. PLAY "cdefgab" odgrywa oktawę w ćwierćnutach. Można użyć liczb oraz "o" do zmiany oktawy i długości nuty, a szczegóły sa dostępne w systemie Pomocy dostarczanym z QBasic-iem. PLAY może działać w tle naszego programu, ale ja bardziej lubię SOUND. SOUND wytwarza ton o określonej częstotliwości. Stosuje się go tak: SOUND 100, 1 'wyemituje bardzo niski ton. SOUND 5000, 2 'wyemituje ton bardzo wysoki, dwa razy tak długi. DO: FOR q=100 TO 500 STEP 2: SOUND q-50, .5: NEXT q LOOP UNTIL INKEY$=chr$(27) 'wytworzy dżwięk syreny do czasu naciśnięcia Esc SOUND 32767, n '(gdzie n jest wystarczająco dużą liczbą) nie będzie 'wytwarzać dźwięku przez czas ustawiony w n. (n=1 = ok. 1/18 sek. - przyp. 'tłum.)

Rozdział 19: Inne przydatne polecenia

SHELL wywołuje polecenia DOS-a. DOS oczywiście jest w stanie nie tylko zawiadywać operacjami na plikach i folderach, może on też uruchamiać inne elementy oprogramowania. Uruchamianie dużych programów spod SHELL może powodować błąd DOS-a "Za mało pamięci" (zazwyczaj nie występuje). Oto zgrabny przykład na SHELL: SHELL "dir *.* /a /b > dirfile.txt" Tworzy on plik o nazwie "dirfile.txt" zawierający listę wszystkich plików z bieżącego folderu. Następnie taką listę można załadować poleceniem OPEN.
mode co40 jest następna przydatną komendą DOS-a, ale nie zawsze (jeżeli w ogóle) działa pod Windows XP. (Z jakiegoś powodu, ilekroć Windows dostaje nowy emulator DOS-a, robi on nawet mniej rzeczy niż DOS albo poprzednie emulatory DOS-a.) Lepiej jest ciągle używać mode con cols=40, które działa pod XP i może być użyte z QBasic-a w ten sposób: SHELL "mode con cols=40" Jest to lepsze niż WIDTH 40, ponieważ bardziej prawdopodobnie działa. Wiem o pewnym projekcie, w którym nie działało WIDTH 40, zanim najpierw nie uruchomiono tej komendy DOS-a przez SHELL, po czym WIDTH 40 działało już normalnie.
COMMAND$ Tylko w QuickBasic (kompilator). Odczytuje argumenty wpisane po nazwie samodzielnego pliku *.exe, spod DOS-a albo Windows, tak że gdy skompilujemy program o nazwie appli01.exe i wpiszemy: c:\winnt\>appli01 Nowy.txt /fs po znaku zachęty DOS-a (np.) i na poczatku tego programu wstawimy: q$=COMMAND$ 'wtedy łańcuch q$ będzie zawierał: "Nowy.txt /fs"
SYSTEM Używaj go zamiast END; jest on przydatny tylko, gdy używamy interpretatora (QBasic lub QuickBasic). Kończy on program, ale gdy działa interpretator, wychodzi także z interpretatora (opuszcza QBasic lub QuickBasic). Działa tylko gdy uruchamiamy program stosując qbasic /run [plik].bas lub qb /run plik... itd. (np. z pliku wsadowego). Przykład: SYSTEM END 'END nie jest tutaj potrzebne, ale niczemu nie przeszkadza, a jest łatwe 'do zauważenia, gdy inni ludzie będą czytać twój kod.

Rozdział 20: Zastrzeżenia

Basic jest fantastycznym językiem do uczenia się jak pisać programy. Zdaj sobie w pełni sprawę, że nawet jeśli jest powolny lub ma mniej funkcji niż niektóre inne języki, będziesz naprawdę pisać programy i możesz rzeczywiście tworzyć w ten sposób małe fragmenty software'u.
Ponieważ oprogramowanie może robić prawie wszystko, co potrafi komputer, może to także Basic. W żaden sposób nie moge brać odpowiedzialności za to, jak używasz lub nadużywasz Basic oraz jego pochodne; nie mogę nawet wziąć odpowiedzialności za to, co zrobisz z zamieszczoną tutaj informacją, i nie biorę jej. Co z nią z robisz, jest to tylko twoja sprawa i twoja odpowiedzialność. Chociaż dołożyłem dużej staranności, aby dać ci dokładną informację, opartą o wiele lat doświadczenia, nie mogę uczynić żadnego rodzaju gwarancji, włącznie z tym że informacja jest użyteczna, dokładna lub bezpieczna. Jeżeli uczysz się - ucz się. Jeśli coś robisz - rób. Ale weź jakąś odpowiedzialność za to, co robisz. Będziesz jedyną osobą odpowiedzialną za to, co zrobisz z tym podręcznikiem i informacją, którą oferuje...
Lecz przy zastrzeżeniach już poczynionych... po prostu bądź rozważny. Ludzie, którzy zbliżają się do bardziej złożonych funkcji ich komputera (a czasami nawet prostych funkcji) nieraz martwią się, że coś zniszczą albo skasują wszystko. Nie jest to prawdopodobne, kiedy pracujesz z QBasic-iem. Więc dołóż nieco staranności w tym, co robisz, miej pomysł na to, co robisz. Gdy będziesz już bardziej oswojony z językiem, oto najpotężniejsze polecenia, przy których trzeba być szczególnie starannym i nie używać ich, dopóki się ich nie zrozumie:
PEEK prawdopodobnie nie spowoduje żadnych problemów, ale czyta z tych samych miejsc w pamięci, co POKE. POKE To nie jest zabawka :) przenoszeniem informacji przy użyciu POKE twój komputer może zrobić prawie wszystko, włącznie z "zawieszeniem się" lub prawdopodobnym uszkodzeniem plików. Nie używaj POKE dopóki nie zrozumiesz dokładnie, po co je używać.
INP, OUT Nie dokładnie jak PEEK i POKE, ale podobne w praktycznym zastosowaniu. Stosuj z taka samą ostrożnością, jak PEEK i POKE. (Jedyny wyjątek, o który przypuszczalnie nie trzeba się martwić: INP(96) - czyta z klawiatury.) CALL pozwala pracować z kodem w asemblerze. W tym kodzie można napisać WSZYSTKO, nawet program do formatowania twardego dysku. Nie używaj CALL lub kodu asemblera, jeżeli nie wiesz, do czego służą. Z drugiej strony - tym sposobem możesz uzyskać dostęp do myszy. Podsumowując: bądź ostrożny i wiedz, jak bardzo potężne są te polecenia.
INTERRUPTX (lub coś podobnego do tego?) spokrewniony w funkcjach z CALL. Nie używaj, chyba że rozumiesz, co chesz zrobić. SHELL Całkiem bezpieczne polecenie, jeżeli rozumiesz komendy DOS-a, ale ponieważ może ono wywoływac te komendy, to może zrobić wszystko, co potrafi DOS. (DOS zarządza plikami i może usuwać je , tworzyć, przenosić lub zmieniać im nazwy, formatować dyski i uruchamiać wiele różnuch rodzajów innych programów, a więc nie używaj SHELL, jeśli nie rozumiesz polecenia DOS-a, które ono ma wywołać.
KILL Nie aż tak złowrogie, jak brzmi, ale może skasować plik lub pliki i tak naprawdę jest to wszystko, co potrafi. Nie używaj KILL, chyba że chcesz kasować pliki.
Poza tym możesz zechcieć wiedzieć, co poszczególne polecenia robią, zanim wypróbujesz program, który ich używa: OPEN "..." FOR INPUT Tu nie ma problemu. Program chce czytać dane z pliku. Powinieneś sprawdzić, czy program zamyka (CLOSE) plik, kiedy odczyt się skończy. OPEN "..." for RANDOM OPEN "..." FOR BINARY A tutaj program może chcieć rzeczywiscie wpisywać dane do pliku. Jeżeli nie chcesz, aby program wpisywał (lub zmieniał) dane w otwieranym pliku, upewnij się, że program nie używa tych poleceń.
OPEN "..." FOR APPEND Tu jest mniej zmartwienia o pliki z danymi, ponieważ ono jedynie dopisuje na końcu pliku. Jeżeli napisałes list, a program otworzy go FOR APPEND, będzie on wpisywał dane POZA końcem tego listu, więc niczego nie utracisz. Oczywiście problem może powstać, jeżeli plik jest bardzo duży, albo komputer "zawiesi się" lub straci zasilanie gdy plik jest otwarty i zapisywany. Dopisywanie do plików binarnych (jak .exe lub nawet pliki obrazu jak .jpg) może także powodowac problemy, wiec upewnij się że wiesz, jaki plik jest "dopisywany".
OPEN "..." FOR OUTPUT Spośród wszystkich trybów otwierania plików ten naprawdę wymaga uwagi. Chociaż jest bardzo przydatne, otwarcie pliku FOR OUTPUT wymazuje zawartość pliku w momencie użycia tego polecenia. Jest to zamierzone, a czasami pożądane. Jeżeli nie chcesz opróżnić pliku przed zapisywaniem do niego, używaj zamiast tego OPEN "..." FOR APPEND (zob. wyżej).
OPEN [urządzenie] FOR [...] czyta z lub zapisuje do urzadzenia. Łatwo zrozumieć, ze jest to używane do sterowania sprzetem przyłączonym do komputera, więc bądź pewny że chcesz, aby program sterował tym urzadzeniem, jeśli program, który uruchamiasz, otwiera je. BSAVE, BLOAD Oba te polecenia obsługują pliki na dysku, a więc bądź ostrożny.
Czerp przyjemność z nauki jak pisać programy. Główna rzecz do zapamiętania to ta, że bierzesz odpowiedzialność za instrukcje, które odbiera twój komputer, i to, że z tymi umiejętnościami wiąże się potrzeba zwracania uwagi na to, co każesz komputerowi robić. Więc nie obawiaj się, ale bądź rozważny. Zawsze próbuj zrozumieć, co robi kod ZANIM go uruchomisz. Nawet w Basic-u twój kod może zrobić bardzo wiele.

Rozdział 21: Pytania (i przyszłość Basic-a)

Jeżeli masz pytania dotyczące QBasic-a, pierwszą rzeczą jest poszukanie odpowiedzi w pliku Pomocy. QBasic ma bardzo dobry system pomocy i jeżeli wyskakuje ci błąd, idź do polecenia które sprawia kłopoty i naciśnij klawisz [F1]; to wywoła Pomoc na temat polecenia, na którym własnie stoi kursor. Jeśli to nie zadziała, spróbuj załadować Pomoc QBasic-a przytrzymując [Shift] i wtedy maciskając [F1], co da ci dostęp do indeksu albo spisu treści, i będzie można stamtąd poszukać odpowiedzi na twój problem. Czytaj Helpy!
Jeżeli masz pytanie nie omówione w systemie Pomocy, wypróbuj forum on-line, np. QBasic Forum: http://www.network54.com/Forum/13959 Zanim tam zadasz pytanie, zajrzyj do sekcji FAQ. Została ona tam wstawiona, aby pomagać ludziom w pospolitych kwestiach i błędach... alternatywą byłoby dawanie wciąż tych samych odpowiedzi jeszcze raz i jeszcze, i jeszcze :( (Jeżeli bawisz się w grafikę ascii, odwiedź także http://www.ascii-world.com).
Co do przyszłości Basic-a, to nieczęsto ktoś pisze o przyszłości bez uśmieszków czy śmiechu z ludzkich przewidywań, a szczególnie przewidywań dotyczących technologii. Jednakże, tak jak są ludzie którzy przypuszczalnie są zaskoczeni, że Basic wciąż jeszcze istnieje, tak będą i tacy którzy będą zaskoczeni, że będzie on nadal istniał w przyszłości. Czy ludzie wciąż będą używać Basic? Pawdopodobnie tak. I będą emulatory DOS-a, jak np. dosbox, aby móc go uruchamiać, gdy Basic przestanie już działać pod wirtualną maszyną DOS-a w Windows.
I jest także FreeBasic, ambitny (i pasjonujący) projekt, który oferuje darmowy szybki i obszerny 32-bitowy kompilator Basic-a z kodem open-source dla DOS-a, Linuxa i Windows. W przyszłości może nawet będzie wersja na Mac-a. Przy odrobinie szcęścia przyszłość będzie pełna hobbystów FreeBasic-a i wyśmienitych programów. FreeBasic można znaleźć pod adresem: http://freebasic.net -= Bawcie się dobrze! -- tak się kończy mennonite's pretty good qb tutorial =-

Przypisy tłumacza

1) 16 kolorów jest w trybie testowym dostępnych równocześnie, a tablica poniżej pokazuje ich domyślne przypisania. Przy czym kolor 0 jest zawsze przypisany do tła, a kolor 7 - do znaku. Poleceniem PALETTE można zmienić przypisania kolorów do ich numerów, wybierając kolor z palety 64 kolorów. Wróć 2,4) QBasic dopuszcza także użycie kropki w nazwie zmiennej, jak tutaj: nazwa.zmiennej Jest to przydatne przy uczytelnianiu nazw wielowyrazowych, jeżeli takie używamy. Rzadko jednak spotyka się programistów, którzy z tego korzystają. Maksymalna długość nazwy zmiennej to 40 znaków. Wróć2 Wróć4 3) Można zadeklarować typ zmiennej na początku programu i wtedy nie potrzebuje ona już przyrostka. Spotyka się np. deklarację DEFINT A-Z, która czyni wszystkie zmienne numerycznymi całkowitoliczbowymi (integer, przyspiesza to obliczenia i angażuje mniej pamięci). Przyrostki wydają się mieć pierwszeństwo przed taką deklaracją, bo później zmienne ze znakiem $ nadal są zmiennymi tekstowymi. Przyrostki dla zmiennych liczbowych - zob. Pomoc QB, zestaw znaków Wróć 5) Ściśle biorąc, układ współrzędnych ekranowych jest odbiciem lustrzanym pierwszej cwiartki układu kartezjańskiego względem jego osi X: punkt 0,0 znajduje się w lewym górnym rogu, a wszystkie współrzędne są dodatnie i rosną w dół i w prawo. Uwaga: pozycja 0,0 istnieje tylko w trybach graficznych, w trybie tekstowym współrzędne zaczynają się od 1,1; LOCATE 0,0 powoduje błąd! Wróć 6) REDO FROM START? = Jeszcze raz od poczatku. INPUT powtarza ten komunikat w kółko, dopóki nie otrzyma akceptowalnej wartości. Jednakże odpowiedź "pustym" [Enter] przy pytaniu o liczbę nie jest traktowana jako błąd, liczba wtedy otrzymuje wartość 0! Wróć 7) AND, OR, ELSE, oczywiste dla anglojęzycznego czytelnika, w polskim przekładzie wymagają komentarza. AND = "i", zachodzi gdy obydwa warunki są prawdziwe. Np. gdy a=5 i b też =5, mamy do czynienia z 'a AND b'. Dla OR wystarczy, gdy jeden ALBO drugi (albo obydwa razem) warunki są prawdziwe. ELSE = "w przeciwnym razie"; w bloku IF...THEN wykona się gdy żaden z poprzednio sprawdzanych warunków "nie pasował". Wróć 8) IF... THEN... = jeżeli... to... Wróć 9) UNTIL = "dopóki nie". W przykładzie LOOP UNTIL x >=10 oznacza "wykonuj pętlę, dopóki x nie przyjmie wartości 10 lub większej". Kiedy x osiagnie wartość 10, wtedy pętla już nie wykona się. Przykładowy zapis "LOOP UNTIL warunek=1, gdzie "1" ma oznaczać "prawdę", jest dla PC mylący. Komputery PC pracują w tzw. logice ujemnej, gdzie "prawdę" oznacza "-1", a nie "1". W związku z tym można napisać "IF warunek = -1 THEN...", lub po prostu "IF warunek THEN...". Wróć

(c) copyleft 2007
na licencji GNU GPL