This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Ali rights reserved. No part ofthis book may be reproduced or transmitted in any form or by any
means, electronic or mechanical, including photocopying, recording or by any information storage
retrieval system, without permission from the Publisher.
Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej
publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną,
fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje
naruszenie praw autorskich niniejszej publikacji .
Wszystkie znaki ich właścicieli.
występujące
w
tekście są zastrzeżonymi
znakami firmowymi
bądź
towarowymi
The Wrox Brand trade dres s is a trademark ofWiley Publishing, Inc. in the United States and/or other
countries. Used by permission.
Visual C++ is registered trademark of Microsoft Corporation in the United States and/or other
countries. Ali other trademarks are the property of their respective owners.
The Wrox Brand jest zastrzeżonym znakiem towarowym Wiley Publishing, Inc . na terenie Stanów
Zjednoczonych i innych krajów. Wykorzystano za zgodą właściciela .
Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje
były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialnościani za ich wykorzystanie,
ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz
Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody
wynikłe z wykorzystania informacji zawartych w książce .
Wydawnictwo HELION
ul. Kościuszki lc , 44-100 GLIWICE
tel. 032 231 22 19, 032 230 98 63
e-mail : he/ion@he/ion.p/
WWW : http://he/ion.p/(księgarnia internetowa, kata
Drogi Czytelniku!
chcesz ocenić tę książkę, zajrzyj pod adres
http://he/ion.p//user/opinie?vcpppo Możesz tam wpisać swoje uwagi, spostrzeżenia , rec Jeżeli
Printed in Poland .
Ks iążkę dedykuję A/exandrowi Gi/bey owi.
Z n iecierpli woś cią oczekuję na jego komentarze,
a/e pewnie będę musial j eszcze troch ę p oczekać.
Podziękowania Za włożony wysiłek i wsparcie chciałbym podziękować wydawnictwu John Wiley & Sons oraz zespołowi edytorskiemu i produkcyjnemu wydawnictwa Wrox . W szczególności chciał bym tutaj wyróżnić redaktora naczelnego ds. rozwoju - Kevina Kenta, który wspierał mnie od samego początku do końca pisania tej książki. Chciałbym również podziękować edytorowi technicznemu - Johnowi Muellerowi za dokładne przeczytanie mojego tekstu i poprawienie, mam nadzieję, większości popełnionych przeze mnie błędów, wypróbowanie wszystkich fragmentów kodu oraz konstruktywne komentarze, które uczyniły tę książkę o wiele lepszą. Na koniec chciałbym podziękować mojej żonie , Eve, za jej cierpliwość , pogodę ducha oraz wspieranie mnie podczas długiego okresu przelewania moich myśli na karty tej książki. Jak już wielokrotnie wspominałem wcześniej - bez niej książka ta nie mogłaby powstać.
Spis treści oautorze
19
Wstęp
21
Rozdział
1. Programowanie przy użyciu Visual C++ 2005
Środow is ko programistyczne .NET
Common Łanguage Runtime (CLR) Pisanie programów w C++ Nauka programowania dla systemu Windows Nauka C++ Standardy C++ Aplikacje działające w trybie konsoli Koncepcje programowania w systemie Windows Czym jest zintegrowane środow isko programistyczne Składn iki systemu Używanie IDE Opcje paska narzędz i Dokowalne paski narzędzi Dokumentacja Projekty i rozwiązania Ustawianie opcji w Visual C++ 2005 Tworzenie i uruchamianie programów dla Windowsa Tworzenie aplikacji Windows Forms Podsumowan ie Rozdział 2.Dane. zmienne i dZiałania
arytmetyczne
Struktura programu w C++ Funkcja mainO Instrukcje programu Białe znaki Bloki instrukcj i Programy konsolowe generowane automatyczn ie Definiowanie zmiennych Zasady nadawania nazw zmiennym Deklarowanie zmiennych Wartość początkowa zmiennej Podstawowe typy danych Zmienne całkowite Znakowe typy danych Modyfikatory typu integer Typ logiczny
27
27
28
29
30
31
32
32
33
35
35
37
3 8
39
39
40
54
55
58
61
63
64
71
72
74
75
75
76
77
78
79
80
80
81
82
83
6
Visual C++ 2005. Od podstaw Typy zmienno pozycyjne Literały
Definiowanie synonimów typów danych Zmienne o okre ś lonych zbiorach wartości Określanie typu st-ałych wyliczeniowych Podstawowe operacj e wejś c ia -wyj śc ia Wprowadzanie danych z klawiatury Wysyłanie danych do wiersza poleceń Formatowan ie wysyłanych danych Kodowanie znaków specjalnych Wykonywanie obliczeń w C++ Instrukcja przypisania Działania arytmetyczne Obliczanie reszty Modyfikowanie zmiennej Operatory inkrem entacji i dekrementacji Kolejność wykonywania obliczeń Typy zmiennych i rzutowanie Zasady rzutowania operandów Rzutowanie w instrukcjach przypisania Rzutowanie jawne Rzutowanie w starym stylu Operatory bitowe Czas życi a i zas ięg zmiennych Zmienne automatyczne Pozycjonowanie deklaracj i zmiennych Zmienne globalne Zmienne statyczne Przestrzenie nazw Deklarowanie przest rzeni nazw Wielokrotne deklar acje przestrzeni nazw Programowanie w C++jCLI Fundamentalne typy danych w C++jCLI Wysyłan ie danych do wiersza poleceń w C++jCLI C++jCLI - formatowanie danych wyjściowych C++jCLI - wprowadzanie danych z klawiatury Bezpieczne rzutowanie Wyliczenia w C++jCLI Podsumowanie Ćwiczenia Rozdział 3.Decyzje i pętle
Porównywanie wartości Instrukcja warunkowa if Zagnieżdżanie inst rukcji warunkowych if Rozszerzona instrukcja warunkowa if Zagnieżdżanie instru kcji warunkowych lf-else Operatory logiczne i wyrażen ia Operator warunkowy Instrukcja switch Przejśc ie bezwarunkowe
:
84
85
86
87
88
89
89
90
91
92
94
9 4
95
100
101
102
104
106
106
107
108
109
109
116
116
119
119
123
123
125
126
128
128
133
133
136
137
138
141
142
145
145
147
148
150
152
154
158
159
162
Spis Ireści Powtarzanie bloków instrukcji Czym jest pętla Różne sposoby użycia pętli for Pętla while Pętla do-while Zagnieżdżanie pętli
Programowanie w C++jCLI Pętla for each Podsumowan ie Ćwiczenia
Rozdział 4. Tablice, łańcuchy
znaków i wskaźniki
Obsługa
wielu wartości danych tego samego typu Tablice Deklarowanie tablic Inicjalizacja tablic Tablice znakowe oraz obsługa łańcuchów Tablice wielowymiarowe Pośredni dostęp do danych Czym jest wskaźnik Deklarowanie wskaźników Używanie wskaźników , Inicjalizowanie wskaźników Operator sizeof Stałe wskaźniki oraz wskaźniki do stałych Wskaźniki i tablice Dynamiczne przydzielanie pamięci Pam ięć wolna, czyli sterta : Operatory new i delete Dynamiczne przydzielanie pamięc i tablicom Dynamiczne przydzielanie pamięci tablicom wielowymiarowym Używanie referencji Czym jest referencja Deklarowanie i inicjalizowanie referencji Programowanie w C++JCLI Uchwyty śledzące Tablice CLR Łańcuchy
Referencje
śledzące
Wskaźniki wewnętrzne
Podsumowan ie Ćwiczenia
Rozdział5. Wprowadzanie struktury do programu Zrozumieć
funkcje Do czego potrzebne są funkcje Struktura funkcji Używanie funkcji Przekazywanie argumentów do funkcji Mechanizm przekazywania przez wartość Wskaźniki jako argumenty funkcji
7 163
163
165
174
176
177
180
184
187
187
189
190
190
191
194
196
200
203
203
204
205
207
213
215
217
224
224
224
225
228
229
229
229
230
231
233
248
258
258
261
263
265
266
267
267
269
273
274
275
8
Visual C++ 2005. Od podstaw Przekazywa nie tabl ic do funkcji Referencje jako argumenty funkcj i Zastosowanie modyfikatora const Argumenty funkcji malm) Akceptowanie zmiennej liczby argumentów funkcji Zwracanie wartości przez funkcję Zwracanie wskaźnika Zwracanie referencji Zmienna statyczna w funkcji Wywołania funkcj i rekurencyjnej Stosowanie rekurencji Programowanie w C++/CLI Funkcje przyjmujące zmienną liczbę argumentów Argumenty funkcji maint) Podsumowan ie
277
281
283
285
287
289
289
292
295
297
300
300
301
302
303
304
Ćwiczenia
Rozdział 6. Ostrukturze programu -
ciąg
dalszJ
305
Wskaźniki
do funkcji Deklarowan ie wskaźników do funkcji Wskaźnik do funkcji jako argument Tablice wskaźników do funkcj i Inicjalizowan ie parametrów funkcji
Wyjątki Wywoływanie wyjątków
Przechwytywanie wyjątków MFC Obsługa błędów przydzielania pamięci Przeładowywaniefunkcji Czym jest przeładowywaniefunkcji Kiedy stosować przeładowywanie funkcji Szablony funkcji Stosowanie szablonu funkcji Przykład używania funkcji Implementacja kalkulatora Usuwanie spacji z łańcucha Obliczanie wartości wyrażen ia Obliczanie wartości składn ika Analizowanie liczby Składanie całego programu Rozszerzanie programu Wydobywanie podłańcucha Uruchamianie zmodyfikowanego programu Programowanie w C++/CLI Funkcje generyczne Kalkulator CLR Podsumowanie Obsługa wyjątków w
Ćwiczenia
:
306
306
309
311
312
314
316
316
318
318
320
321
323
323
324
326
326
330
330
333
334
337
339
340
343
343
345
351
357
358
Spis treści Rozdział 7. Deliniowanie własnych
Iypów danych
Struktury w języku C++ Czym jest struktura Definiowanie struktury Inicjali zowanie struktury Uzyskiwanie dostępu do pól struktury Pomoc mechanizmu Intellisense w pracy ze strukturami Struktura RECT Używanie wskaźników ze strukturam i Typy danych , obiekty, klasy i egzemplarze Zrozumieć klasy Definiowanie klasy Deklarowanie obiektów klasy Uzyskiwanie dostępu do zmiennych składowych klasy Funkcje składowe klasy Umiejscowienie definicji funkcji składowej Funkcje inline Konstruktory klas Czym jest konstruktor Konstruktor domyślny Przypisywanie domyślnych wartośc i parametrom umieszczonym w klasach Używanie listy inicjalizacyjnej w konstruktorze Prywatne składowe klasy Uzyskiwanie dostępu do prywatnych zmiennych składowych klasy Przyjaciele klasy Domyślny konstruktor kopiujący Wskaźnik th is Stałe obiekty klasy Stałe funkcje składowe klasy Definiowan ie funkcji składowej poza klasą Tablice obiektów klasy Składowe statyczne klasy Statyczne zmienne składowe klasy Statyczne funkcje składowe klasy Wskaźniki i referencje do obiektów klasy Wskaźn ik i do obiektów Referencje do obiektów Programowanie w C++/CLI Definiowanie typów klas wartości Definiowanie typów referencyjnych Właściwości klasy , Pola initonly Konstruktor statyczny Podsumowanie Ćwiczenia
9 359
360
360
360
361
361
365
366
367
369
372
373
373
374
376
378
379
380
380
382
385
387
387
390
391
394
395
398
399
.400
401
402
403
405
406
406
409
411
:
412
417
420
433
434
435
436
10
Visual C++ 2005. Od podslaw Rozdziala. Więcej na lemat klas Destruk tory klas Czym jest destruktor Destruktor domyślny Destruktory i dynamiczne przydzielani e pam ięci Implementacja konstruktora kopiującego Dzielenie pamięci pomiędzy zmiennymi Definiowanie unii Unie anonimowe Unie w klasach i strukturach Przeładowywanie operatorów Implementacja przeładowanego operatora Implementacja pełnej obsługi operatora Przeładowywanie operatora przypisania Przeładowywanie operatora dodawania Przeładowywanie operatorów inkrement acj i i dekrementacji Szablony klas Definiowanie szablonu klasy Tworzenie obiektów klasy szablonu Szablony klas z wieloma parametrami Używanie klas Interfejs klasy Definiowan ie problemu Implementacja klasy Definiowanie klasy CBox Zastosowanie klasy CBox Organizowanie kodu programu Nazewnictwo plików programu Programowanie w C++jCLI Przeładowywanie operatorów w klasach wartości Przeładowywanie operatorów inkrement acj i i dekrementacji Przeładowywanie operatorów w klasach referencyjnych Podsumowanie Ćwiczenia
Rozdzial9. Dziedziczenie i funkcje wirlualne Podstawy programowan ia zorientowanego obiektowo (OOP) Dziedziczenie w klasach Czym jest klasa bazowa Tworzenie klas pochodnych Kontrola dostępu do dziedziczonych składowych Działanie konstruktora w klasie pochodnej Deklarowan ie chronionych składowych klasy Poziom dostępu do dziedziczonych składowych klasy Konstruktor kopiujący w klasie pochodnej Składowe klasy jako przyjaciele Klasy zaprzyjaźnione Ograniczenia klas zaprzyjaźnionych Funkcje wirtualne Czym jest funkcja wirtualna Używanie wskaźników do obiektów klas Używanie referencji z funkcjami wirtualnymi
439
439
440
440
442
445
448
448
450
450
450
451
454
458
464
468
468
469
472
475
477
477
477
478
486
497
500
500
502
503
508
509
511
512
515
515
517
517
518
521
524
528
531
532
537
538
538
539
541
544
545
Spis treści Funkcje czysto wirtualne Klasy abstrakcyjne Pośrednie klasy bazowe Wirtualne destruktory Rzutowanie pomiędzy typam i klasowym i Klasy zagnieżdżone Programowanie w C++ /CLI Dziedziczenie w C++/CLI Klasy interfejsowe Definiowanie klas interfejsowych Klasy i asemblacje Definiowanie nowych funkcji Delegaty i zdarzenia Finalizatory i destruktory w klasach referencyjnych Klasy generyczne Podsumowanie Ćwiczenia
_
547
548
551
553
559
559
563
563
569
570
574
579
579
592
594
605
607
,
:
Rozdzial10. Debugowanie
611
Co znaczy debugowanie Błędyoprogramowania
Najczęściej spotykane błędy Podstawowe operacje debugowania Ustawianie punktów wstrzymania Ustawianie punktów śledzenia Rozpoczynanie debugowania Zmien ianie wartości zmiennej Dodawanie kodu debugującego Asercje Dodawanie własnego kodu debugowanła Debugowanie programu Stos wywołań Szukanie błędu krok po kroku Testowanie rozszerzonej klasy Odnajdywanie następnego błędu Debugowanie pamięci dynamicznej Funkcje sprawdzające obszar wolnej pamięci Sterowanie operacjami debugowanla obszaru wolnej Dane wyjściowe debuggera obszaru wolnej pamięci Debugowanie programów w C++/CLI Używanie klas Debug i Trace Podsumowanie
_
pam i ęci
Rozdzial11. Założenia programowania dla systemu Windows Podstawy programowania dla systemu Windows Elementy okna Programy dla Windowsa i system operacyjny Programy st erowane zdarzeniami Komunikaty Windowsa Windows API Typy danych w systemie Windows Notacj a w programach dla systemu Windows
11
611
613
614
615
617
619
620
625
625
626
627
633
633
635
638
641
641
642
643
644
650
650
659
661
:
662
663
664
665
665
666
666
667
12
Visual C++ 2005. Od podslaw Struktura programu dla systemu Windows Funkcja WinMalnt) Funkcje przetwarzania komunikatów Prosty program dla systemu Windows Organizacja programu dla systemu Windows Microsoft Foundation Classes Notacja MFC Jak jest ustrukturyzowany program MFC Korzystani e z formularzy systemu Windows Podsumowanie
668
669
681
686
686
689
689
690
693
695
Rozdzial12. PrOgramowanie dla systemu Windows
zwykorzystaniem Microsoft Foundation C1asses
699
Architektura dokument-widok w MFC Czym jest dokument Interfejsy dokumentu Czym jest wido k lączenie dokumentu i jego widoków Aplikacja a MFC Tworzenie aplikacji MFC Tworzenie apl ikacji SDI Wynik działania MFC Application Wizard Tworzenie aplikacji MDI Podsumowanie Ćwiczenia
700
700
700
70'1
702
702
705
707
710
721
724
724
Rozdzial13. Praca zmenu i paskami narzędzi Komun ikacja z systemem Windows Zrozumieć mapy komunikatów Kategorie komunikatów Obsługa komun ikatów w programie Rozwijanie programu Sketcher Elementy menu Tworzenie i edycja zasobów menu Dodawanie procedur obsługi dla komunikatów menu Wybieranie klasy obsługującej komunikaty menu Tworzenie funkcj i komunikatu menu Tworzenie kodu dla funkcji komunikatów menu Dodawanie procedur obsługi komunikatów uaktualniających interfejs Dodawanie przycisków paska narzędzi Edycja właściwośc i przycisku paska narzędzi Testowanie przycisków narzędzi Dodawanie wskazówek Podsumowanie Ćwiczenia
Rozdzial14. Rysowanie woknie Podstawy rysowania w oknie Obszar klienta okna Graphical Device Interface
727
użytkownika
727
728
731
732
733
734
734
739
740
741
743
747
752
753
754
755
756
757
759
759
760
761
SpiS treści Mechanizm rysowania w Visual C++ Klasa widoku w aplikacji Klasa CDC Rysowanie grafiki w praktyce Programowanie myszy Komunikaty z myszy Procedury obsługi komunikatów myszy Rysowanie za pomocą myszy Testowanie szkicownika Uruchamianie przykładu Przechwytywanie komunikatów myszy Podsumowanie Ćwiczenia Rozdział 15. Tworzenie dokumentu ipoprawianie
:
widoku
Czym są klasy kolekcji Typy kolekcji Klasy kolekcji z kontrolą typów Kolekcje obiektów Kolekcje wska źników z kontrolą typów Korzystanie z szablonu klasy CList Rysowanie krzywej Definiowanie klasy CCurve Implementacja klasy CCurve Sprawdzanie klasy CCurve Tworzenie dokumentu Używanie wzorca CTypedPtrList Poprawianie widoku Uaktualnianie wielokrotnych widoków Przewijanie widoków Korzystanie z trybu mapowania MM_LOENGLlSH Usuwanie i przesuwanie kształtów Implementacja menu kontekstowego Łączenie menu z klasą Wybieranie menu kontekstowego Podświetlanie elementów Obsługa komunikatów menu Rozwiązywanie problemu nakładających się elementów Podsumowanie Ćwiczenia Rozdział 16. Praca z oknami
dialogowymi ikontrolkami
Poznaj okna dialogowe Poznaj kontrolki Wspólne kontrolki Tworzenie zasobu okna dialogowego Dodawanie kontrolek do okna dialogowego Programowanie okna dialogowego Dodawanie klasy dialogu Modalne i niemodalne okna dialogowe Wyświetlanie okna dialogowego
13 763
763
765
774
776
777
779
781
805
806
807
808
809
811
811
812
813
813
823
825
826
827
829
830
831
831
837
837
840
844
846
847
848
850
855
860
867
869
870
871
871
872
874
874
875
877
877
878
878
14
Visual C++ 2005. Od podstaw Obs ł u ga
kont rolek okna dialogowego Inicjalizowanie kontrolek O b s ł u ga komunikatów przycisku opcj i Ko ń czenie operacj i okna dialogowego Dodawanie szerokośc i pióra do dokument u Dodawanie szerok ości pióra do elementów Tworzenie elementów w widoku Testowanie okna dialogowego U żywani e p okrętł a
Dodawanie element u menu Scale oraz przycisku paska Tworzenie po k rętła Generowanie klasy okna dialogowego Scale Wyśw i e tl an i e po k rętła
Korzystanie ze w spółc zynni ka skali Skalowalne tryby mapowania Ustawianie rozmiaru dokumentu Ust awianie t rybu mapowania Impleme ntowanie przewijania ze skalowaniem Praca z paskami stanu Dodawanie paska stanu do ramki U żyw ani e pól list Usuwanie okna dialogowego Scale Tworzenie kontro lki pola list Korzystan ie z kont rolki pola tekstowego Tworzenie zasobu pola tekst owego Tworzenie klasy okna dialogowego Dodawanie element u menu Text Definiowanie elementu Text Impleme ntacja klasy CText Tworzenie element u Text Podsumowanie Ćwiczeni a
Rozdział 17. Przechowywanie i drukowanie dokumenlów Poznaj seri al i z acj ę Serializowanie dokumentu Serializacja w definicji klasy dokumentu Serializacj a w implement acji klasy dokumentu Zestaw fun kcj i klas opartych na CObject Jak d zi ał a serializacj a Jak za im p l em entowa ć se r ia l izację klasy Stosowanie seri alizacji Rejest rowanie zmian dokumentu Serializowanie dokumentu Serializowanie klas elementów Testowani e seriali zacji Przenoszenie tekst u Drukowanie dokument u Proces drukowania Implement acja wielostron icowych wydruków Uzyskiwanie c ał kowitego rozmiaru dokum entu Przechowywanie danych drukowania
Spis treści Przygotowania do wydruku Porządkowanie po drukowaniu Przygotowywanie kont ekstu urządzenia Drukowanie dokumentu Drukowanie dokum entu Podsumowanie
945 947 947 948 952 95 3 954
Ćwiczenia
Rozdzial18. Tworzenie własnych plików DLL
955
Poznaj DLL Jak działają DLL Zawartość DLL Odmiany DLL Co umieścić w DLL Pisanie DLL Pisanie i używanie rozszerzającej DLL Eksportowan ie zmiennych i funkcj i z DLL Importowanie symbol i do programu Implementowanie eksportowania symboli z DLL Podsumowani e
955 957 960 961 962 963 963 970 971 972 974 975
Ćwiczenia
Rozdział 19. lączenie się
ze źródłami danych
Podstawy baz danych Nieco o języku SQL Pobieranie danych z użyciem języka SQL Łączenie tab el w języku SQL Sortowanie rekordów : Obsługa baz danych w MFC Klasy MFC obsługujące ODBC Tworzenie aplikacji bazodanowej Rejestrowanie bazy danych ODBC Generowan ie programu MFC ODBC Poznaj strukturę programu Testowanie przykładu Sortowanie zestawu rekordów Zmienianie podpisu okna Używanie drugiego obiektu zestawu rekordów Dodawanie klasy zestawu rekordów Dodawanie klasy widoku dla zestawu rekordów Dostosowywan ie zestawu rekordów Dostęp do wielu widoków tablic Przeglądanie zamówień na produkt Przeglądanie informacji o kliencie Dodawanie zestawu rekordów dla informacji o kliencie Tworzenie zasobu okna dialogowego z informacjami o kliencie Tworzenie klasy widoku dla informacji o kliencie Dodawanie filtra Implementacja parametru filtra Łączenie okna dialogowego Order z oknem dialogowym Customer Testowanie przeglądarki bazy danych Podsumowanie Ćwiczenia
VislJal C++ 2005. Od podslaw Rozdział20.lklualizacja źródeł danych
1033
Operacje aktual izacji Operacje aktualizacji CRecordSet Transakcje Prosty przykład uaktualnienia Dostosowywanie aplikacji Zarządzanie procesem aktualizacji Implementacja trybu uaktualniania Dodawanie wierszy do tabeli Proces wpisywania zamówienia Tworzenie zasobów Tworzenie zest awów rekordów Tworzenie widoków zestawu rekordów Dodawanie kontrolek do zasobów dialogu Implementacja przełączania okien dialogowych Tworzenie identyf ikatora zamówienia Przechowywanie danych zamówienia Wybieranie produktów dla zamówienia Dodawanie nowego zamówienia Podsumowanie Ćwiczenia
1033
1034
1036
1038
1040
10 42
1044
1052
1053
1054
1055
1055
1060
1064
1068
1073
1075
1077
1082
1082
Rozdział21.lplikacjewYkorzystująceWindows Forms
1083
Poznaj formularze systemu Windows Poznaj aplikacje Windows Forms Zmienianie właściwości formularza Jak startuje aplikacja Dostosowywanie GUl aplikacji Dodawanie kontrolek do formularza Dodawanie zakładek Korzystanie z kontrolki GroupBox Używanie kontrole k Button Korzystanie z kontrolki WebBrowser Sposób działania aplikacji Winning Application Dodawanie menu kontekstowego Tworzenie procedur obsługi zdarzeń , Obsługa zdarzeń dla menu l.lrnits Tworzenie okna dialogowego Używanie okna dialogowego Dodawanie drugiego okna dialogowego Implementacja elementu menu Help/About Obsługa kliknięcia przycisku Reagowanie na menu kontekstowe Podsumowanie
1083
1084
1086
1087
1088
1089
1092
1094
1097
1099
1100
1102
1102
1108
1109
1115
1120
1128
1128
1131
1138
1139
Ćwiczenia
Rozdział 22. Dostęp
do źródeł danych waplikacjach Windows Forms
Praca ze źródłam i danych Dostęp do danych i ich wyświetlanie Używanie kontrolki DataGridView Używanie kontrol ki DataGridView w trybie
niezwiązanym
1141
1142
1143
1143
1145
Spis Ireści Dostosowywan ie kontrolki DataGridView Dostosowywan ie komórek nagłówkowych Dostosowywanie pozostałych komórek Dynamiczne ustawianie stylów komórki Używanie trybu związanego Komponent BindingSource Korzystanie z kontro lki BindingNavigator W ią zan ie z pojedynczymi kontrolkami Praca z wielom a tabelami Podsumowani e Ćwiczenia
17 1151
1152
1153
1160
1165
1166
1171
1174
1178
1179
1180
Dodalek A Slowa kluczowe w Języku C++
1181
Dodatek B Kody ASCii
1183
Skorowidz
1189
18
Visual C++ 2005. Od podstaw
oautorze Ivor Horton z wyk ształcenia jest matematykiem, a do informatyki zwabiła go obietnica zarobków przy niewielkim nakładzie pracy. Mimo że rzeczywistość okazała się całkiem inna - dużo pracy i raczej średnie zarobki - komputerami Ivor zajmuje się do dziś. Pracował już jako programista, projektant systemów, konsultant oraz kierownik wdrażania projektów o dużym stopniu złożoności. dużych
Horton ma wieloletnie doświadczenie w tworzeniu i wdrażaniu systemów komputerowych zastosowanie w projektowaniu inżynierskim oraz w produkcji w różnych sekto rach gospodarki. Posiad a także duże doświadczenie w tworzeniu czasami przydatnych pro gramów w różnych językach programowania oraz nauczaniu, przede wszystkim naukow ców i inżynierów, robienia tego samego. Książki na temat programowania pisze już od ponad dziesięciu lat. Pośród jego naj nowszych publikacji znajdują się pozycje dotyczące języków C, C++ oraz Java. Obecnie, kiedy Ivor nie pisze książek o programowaniu i nie zajmuje się doradzaniem , jego głównymi zajęciami są łowienie ryb, podróżowanie oraz szlifowanie francuskiego . mających
20
Visual C++ 2005. Od podstaw
Wstęp
Witaj drogi Czytelniku. Dzięki temu egzemplarzowi możesz stać się efektywnym progra mistą C++. Najnowszy system firmy Microsoft Visual Studio 2005 pozwala na tworzenie programów w dwóch różnych, ale blisko spokrewnionych wersjach języka C++. Obsługuje on zarówno oryginalną, standardową wersję C++ ISO/ANSI, jak również jego nowszą wersję znaną pod nazwą C++/CLI, która została stworzona przez Microsoft i jest dzisiaj standardem ECMA. Obie te wersje uzupełniają się i pełnią różne role. CH ISO/ANSI służy do tworzenia wysoko wydajnych programów, które można uruchamiać natywnie na komputerze. Natomiast CH/CLI został przygotowany specjalnie z myślą o platformie .NET. Z książki tej nauczysz się programować w obu wersjach C++. Przy pisaniu programu w ISO/ANSI CH znaczna część kodu generowana jest automatycznie. Mimo tego ułatwienia istnieje także konieczność samodzielnego wpisywania jego dużych partii. Do tego celu trzeba dobrze rozumieć ideę programowania zorientowanego obiektowo, a także dysponować znaczną wiedzą na temat specyfiki programowania dla systemu Windows . Mimo że C++/CLI stworzony został dla platformy .NET , jest on także narzędziem wspoma gającym tworzenie aplikacji za pomocą biblioteki Windows Forms, przy użyciu której można tworzyć programy, pisząc niewielkie ilości kodu, a czasami nawet bez takiej potrzeby. Oczywiście, gdy zachodzi potrzeba dodania kodu do aplikacji Windows Forms, nawet nie wielkiej jego ilości, trzeba posiadać dogłębną wiedzę na temat języka CH/CLI. Język
C++ ISO/ANSI jest nadal wybierany przez wielu profesjonalistów, ale szybkość two rzenia programów, jaką oferuje język C++/CLI w połączeniu z biblioteką Windows Forms, powoduje, że ma on także duże znaczenie. Z tego też powodu zdecydowałem się przedstawić w tej książce oba rodzaje języka C++ .
Dla kogo iest ta książka Celem tej książki jest nauka pisania w języku C++ programów przeznaczonych dla systemu operacyjnego Microsoft Windows przy użyciu programu Visual C++ 2005 lub jednej z edycji środowiska Visual Studio 2005. Książka ta nie wymaga żadnego wcześniejszego doświad czenia w programowaniu w jakimkolwiek innym języku programowania. Książka ta jest dla Ciebie, jeśli: • Posiadasz niewielkie doświadczenie w programowaniu w innych językach, takich jak BASIC czy Pascal , i chcesz nauczyć się C++ oraz rozwinąć praktyczne zdolności programowania dla systemu Microsoft Windows.
22
Visual C++ 2005. Od podstaw • Masz pewne
doświadczenie w
środowisku niż
w
środowisku
programowaniu w C lub C++, ale w innym Windows, i chcesz poszerzyć swoje umiejętności o programowanie Windows przy użyciu naj nowszych narzędzi i technologii.
• Dopiero zaczynasz programować i masz wystarczająco dużo chęci, aby zgłębiać tajniki programowania w języku C++. Aby nauka była owocna, musisz przynajmniej znać podstawy działania komputera - jak wygląda organizacja pamięci oraz w jaki sposób przechowywane są dane i instrukcje.
oCZym jest ta książka Pisałem tę książkę z myślą nauczenia Czytelnika podstaw programowania w języku C++ przy użyciu obu technologii obsługiwanych przez Visual C++ 2005. Niniejszy egzemplarz stanowi szczegółowy przewodnik po obu typach języka C++. Zatem opisane tutaj zostało tworzenie programów dla systemu Windows w natywnym języku C++ ISO/ANSI przy użyciu biblioteki Microsoft Foundation Classes (MFC) oraz w języku C++/CLI przy użyciu biblioteki Windows Forms. Ze względu na wszechobecność technik bazodanowych w dzisiej szych czasach, książka ta zawiera również wprowadzenie do technik, za pomocą których można uzyskać dostęp do zasobów danych zarówno z poziomu programów utworzonych w technologii MFC, jak i Windows Forms. Programy MFC wymagają pisania większych ilości kodu w porównaniu z aplikacjami Windows Forms. Spowodowane jest to tym, że Win dows Forms pozwala na korzystanie z wysoko rozwiniętych narzędzi Visual C++, umoż liwiających utworzenie całości graficznego interfejsu użytkownika (ang. Graphical User Interface - GUl) w trybie graficznym przy automatycznym wygenerowaniu kodu. Z tego też względu większa część tej książki poświęcona została programowaniu w technologii MFC, a nie Windows Forms.
Organizacja książki •
Rozdział
1. stanowi wprowadzenie do podstawowych zagadnień, które należy móc tworzyć zarówno natywne, jak i korzystające z platformy .NET programy w języku C++. Dodatkowo wprowadzam także podstawy posługiwania się środowiskiem programistycznym Visual C++ 2005. Podstawy te pozwolą na wykorzystanie możliwości Visual C++ 2005 do tworzenia różnego typu programów w języku C++, o których będzie mowa w dalszych rozdziałach książki. zrozumieć, aby
•
Rozdziały
2. - 10. poświęcone zostały nauce obu wersj i języka C++ oraz podstawowych zagadnień i technik znajdowania błędów. Każdy z tych rozdziałów został napisany według tego samego wzoru. Pierwsza połowa poświęcona jest tematom związanym z C++ ISO/ANSI, a druga traktuje o C++/CLI.
•
Rozdział
11. stanowi opis struktury aplikacji systemu Microsoft Windows i opisuje oraz pokazuje najważniejsze komponenty, które posiada każdy taki program. W rozdziale tym znajdują się wyjaśnienia prostych przykładowych programów
Wstęp
23
korzystających z C++ ISO/ANSI oraz API Windows, jak również przykład prostego programu utworzonego w technologii C++ /CLI przy użyciu biblioteki Windows Forms.
•
Rozdziały 12. - 17. szczegółowo opisują możliwości , jakie daje MFC przy budowie GUl. Nauczysz się tworzyć i używać najczęściej spotykane kontolki do budowy graficznego interfejsu użytkownika swojego programu, a także obsługiwać zdarzenia będące rezultatem interakcji użytkownika z programem. W ten sposób utworzymy w pełni działającą aplikację. Dodatkowo na przykładzie tego programu nauczysz się drukować i zapisywać na dysku dokumenty przy użyciu biblioteki MFC.
•
Rozdział
18. zawiera niezbędne informacje potrzebne do tworzenia własnych bibliotek przy użyciu MFC. Dowiesz się, jakiego rodzaju biblioteki możesz tworzyć, oraz utworzysz przykładowe biblioteki, które będę współpracowały z programem napisanym w poprzednich sześciu rozdziałach.
•
Rozdziały 19. i 20. poświęcone zostały uzyskiwaniu dostępu do zasobów danych z poziomu aplikacji MFC. Nauczysz się uzyskiwać dostęp do bazy danych w trybie tylko do odczytu, a następnie poznasz podstawowe techniki programistyczne pozwalające uaktualniać zawartość bazy danych przy użyciu biblioteki MFC. W przykładach wykorzystano bazę danych Nortwind, którą można pobrać z sieci . Opisane techniki można również zastosować do własnego źródła danych .
• W rozdziale 21. za pomocą Windows Forms oraz C++/CLI piszemy przykładowy program, dzięki któremu nauczymy się tworzyć kontrolki Windows Forms, dopasowywać je do własnych potrzeb i ich używać. Program ten jest rozbudowywany w trakcie rozdziału, pozwalając Czytelnikowi na praktyczne zdobywanie doświadczenia. •
Rozdział 22. bazuje na wiedzy zdobytej w poprzednim rozdziale. Poświęcony został on kontrolkom służącym do uzyskiwania dostępu do źródeł danych oraz sposobom dopasowywania ich do własnych potrzeb. Nauczysz się także tworzyć programy z dostępem do bazy danych bez wpisywania kodu źródłowego.
Wszystkie techniki programistyczne opisane w poszczególnych rozdziałach zostały zilustro wane konkretnymi przykładami. Na końcu każdego rozdziału znajduje się podsumowanie najważniejszych zagadnień w nim poruszonych. Większość rozdziałów została dodatkowo uzupełniona o ćwiczenia pozwalające zastosować zdobytą wiedzę w praktyce. Rozwiązania do tych ćwiczeń można pobrać ze strony wydawcy. Część książki poświęcona
samemu językowi C++ bazuje na przykładowych programach trybie konsoli, z którymi komunikacja odbywa się z poziomu wiersza poleceń. Dz ięki temu można skupi ć s i ę na samych możliwościach oferowanych przez język C++, bez wprowadzania niepotrzebnego zamętu związanego z zawiłościami programowania GUl Windows. Programowanie dla systemu Windows jest możliwe dopiero wtedy, gdy zdobędzie się gruntowną wiedzę na temat języka programowania C++. działających w
sobie prostotę mogą rozpocząć naukę od samego C++ ISO/ANSI. Każdy z roz 2. - 10. najpierw opisuje określone możliwości języka C++ ISO/ANSI, a następnie wprowadza nowe właściwości dostępne w C++ /CLI dla tego samego kontekstu . Powodem takiej organizacji książki jest fakt , że C++/CLI został określony jako rozszerzenie C++
Osoby
ceniące
działów
24
Visual C++ 2005. Od podstaw ISO/ANSI. W związku z tym, aby zrozumieć C++/CLI , należy wpierw nauczyć się C++ ISO/ ANSI. Można zatem skupić s i ę jedynie na tematach opisujących s ta n dardow ą wersję języka C++ w rozdziałach od 2. do 20. i pominąć części dotyczące C++/CLI. Następnie można przejść do tworzenia programów dla systemu Windows w języku C++ ISO/ANS] bez konieczności pamiętania o drugiej wersji tego języka . Do C++/CLI można powrócić, gdy poczujemy się pewnie w standardowej wersji. Można oczywiście rozpocząć naukę obu wersji języka od samego początku , stopniowo zwiększając swoją wiedzę na ich temat.
Czego będZiesz
potrzebować
do tei książki
Aby móc w pełni korzystać z tej książki, potrzebujesz jednego z trzech programów: Visual Studio 2005 Standard Edition, Visual Studio 2005 Professional Edition lub Visual Studio 2005 Team System . Visual C++ Express 2005 nie przyda s i ę nam, ponieważ nie zawiera biblioteki MFC. Aby móc zainstalować oprogramowanie Visual Studio 2005, należy posiadać system Windows XP z zainstalowanym zestawem poprawek Service Pack 2 lub Windows 2000 z zainstalowanym Service Pack 4. Wymagania sprzętowe Visual Studio to co najmniej procesor z zegarem l GHz, 256 MB pamięci RAM oraz nie mniej niż 1 GB wolnej prze strzeni na dysku systemowym oraz 2 GB na dysku, na którym zostanie zainstalowany pro gram. Do zainstalowania pełnej dokumentacj i MSDN dostępnej razem z oprogramowaniem potrzebne będzie dodatkowe 1,8 GB na dysku instalacyjnym. Przykłady z bazą danych korzystają z bazy Northwind Traders. Można ją znaleźć, s zu k aj ąc frazy Northwind Traders na stronie http://msdn.microsoft.com, z której można ją pobrać . Można oczywiście skorzystać ze wszystkich opisywanych przykładów w pracy z dowolną inną bazą danych.
Aby odnie ść największe korzyści z czytania tej książki, należy mieć zapał do nauki oraz z uporem dążyć do opanowania naj potężniejszego dostępnego obecnie narzędzia programi stycznego dla systemu Windows. Musisz się poświęcić i wpisać wszystkie przykłady kodu oraz je przeanalizować, a także spróbować rozwiązać zadane ćwiczenia. Wszystko to brzmi o wiele gorzej, niż prezentuje się w rzeczywistości . Nie oprzesz się uczuciu zaskoczenia, jak wiele udało Ci się osiągnąć w krótkim czasie . Należy także pamiętać, że każdy, kto uczy się programować, od czasu do czasu przechodzi trudne chwile. Ale jeśli się nie poddasz, z czasem wszystko stanie się jasne. Książka ta pomoże Ci rozpocząć eksperymentowanie na własną rękę, a co za tym idzie - odnieść sukce s jako programista C++ .
Konwencie Aby umożliwi ć Czytelnikowi odniesienie jak największych korzyści z czytania tej i ułatwić zorientowanie się w temacie, w książce tej przyjęto kilka konwencji.
książki
Wstęp
Jako Spróbuj sam oznaczamy
ćwiczenia,
które powinny
zostać
25
wykonane na podstawie tekstu
książki.
Jak to działa Po kilku Spróbuj sam
następuje
Jak to działa, czyli
W ramkach takich jak ta przechowywane średnio do otaczającego je tekstu.
Wskazówki, porady, sztuczki i uwagi Style w
są
szczegółowe objaśnienie
są ważne
informacje
wpisanego kodu.
odnoszące się
lekko przesunięte i napisane
bezpo
taką czcionką.
tekście:
• Nowe terminy i ważne słowa pisane ich pierwszego pojawienia się. • Kombinacje klawiszy prezentowane
są pismem
pochylonym w momencie
są następująco:
• Nazwy plików, adresy URL oraz kod w
obrębie
Ctrl+A.
tekstu oznaczone są następująco:
persistence.properties. • Kod prezentowany jest na dwa
różne
sposoby:
Nowe i ważne fragmenty kodu w przykładach znajdują się w ramkach Ramka używana jest do oznaczania kodu mniej ważnego w określonym kontekście lub kodu. który był już wcześniej prezentowany. Pracując
z
przykładami
w
książce,
kod
można wpisywać ręcznie
lub
skorzystać
z zasobów
dostępnych dla tej książki. Wszystkie przykłady kodu z tej książki można pobrać ze strony
http://helion.pl/ksiazki/vcppo.htm.
•
26
Visual C++ 2005. Od podstaw
1
Programowanie
przy użyciu lisual C++ 2005
Programowanie dla systemu Window s nie jest trudne , a Microsoft Yisu al C++ 2005 sprawi a, staje się ono wręcz banalne, o czym przekonamy s i ę w trakcie czytania tej książk i . Jest tylko jeden problem: zanim zagłęb imy się w zawiło ści programowania dla Windowsa, najpierw musimy dokładnie zapozna ć si ę z możliwo ściam i oferowanymi przez język C++, a w szcze gólności z technikami programowania zorientowanego obiektowo w tym języku. Techniki te s ta now i ą podstawę efektywn ości wszy stkich narzędzi dostarczanych przez Yisual C++ 2005 dla programowania w systemie Windows. W zwi ązku z tym bardzo ważne jest ich dobr e zro zumienie. W rozdziale tym dowiemy się: że
są najw ażniejsze składniki środowiska
•
Jakie
•
Z czego
•
Czym
są rozwiązania
•
Czym
są
•
Jak
utworzyć
•
Jak
sk omp i l ow ać , sk o nso l i d ować
skład a się
programy
Yisual C++ 2005.
platforma .NET oraz jakie oferuje i proj ekty oraz j ak
działające
s ię je
korzyści .
tworzy.
w trybie konsoli.
i ed ytować program. i uruchomi ć program konsolowy w C++.
A zatem nadszedł czas, by włączyć komputer, wisko Yisu al C++ oraz rozpocząć przygodę.
uruchomić
system Windows i potężne
ś ro d o
Środowisko programistyczne .NET Środowisko programistyczne .NET stanowi cen t ra l n ą koncepcję Yisual C++ 2005, jak również wszystkich innych produktów firmy Microsoft wykorzystujących tę platformę. Środowisko .NET składa się z dwóch komponentów : Common Language Runtime (CLR) ,
28
Visual C++ 2005. Od podstaw w którym wykonywane są programy, oraz zbioru bibliotek, zwanych bibliotekami klas środo wiska .NET. Biblioteki klas platformy .NET do starczają funkcji potrzebnych do wykonania kodu w CLR bez względu na użyty język programowania. Oznacza to, że programy .NET napisane w C++, C# lub jakimkolwiek innym języku obsługującym platformę .NET korzy stają z tych samych bibliotek .NET. Za pomocą pakietu Visual C++ 2005 można tworzyć dwa podstawowe typy programów w C++. Istnieje możliwość napisania programu , który jest wykonywany natywnie, na tym samym komputerze - tego typu programy nazywamy programami natywnymi C++ i two rzymy je w C++ ISO/ANSI. Drugi typ to programy działające pod kontrolą CLR , które zostały napisane w rozszerzonej wersji C++, czyli C++/CLI. Programy te nazywamy programami CLR lub programami C++/CLI. Platforma .NET nie jest częścią Visual C++ 2005, ale raczej składnikiem systemu operacyj nego Windows, który ułatwia tworzenie oprogramowania oraz usług sieciowych. Platforma ta zapewnia większą niezawodność kodu i jego bezpieczeństwo,a także pozwala na integrację kodu C++ z kodem napisanym w ponad 20 innych językach programowania, które z nią współpracują. Jedną z wad programowania dla platformy .NET jest niewielka strata wydaj ności , ale w większości przypadków jest ona całkowicie niezauważalna.
Common Language Runtime (CLRJ CLR jest standardowym środowiskiem do wykonywania programów napisanych w wielu różnych językach wysokiego poziomu, takich jak Visual Basic, C# czy właśnie C++. Spe cyfikacja CLR w chwili obecnej zawiera się w standardzie CLI (ang. Common Language Infrastructurei, europejskiego stowarzyszenia producentów komputerów ECMA (ang . Euro pean Computer Manufacturersi - ECMA-335 , a także w równorzędnym standardzie ISO ISO/lEC 23271 , a więc CLR jest implementacją tego standardu. Można łatwo odgadnąć , dlaczego język C++ dla CLR nazywany jest C++/CLI - jest to C++ dla Common Language Infrastructure (wspólna infrastruktura dla języków). Dzięki temu kompilatory C++/CLI można spotkać także w innych systemach operacyjnych, które posiadają implementację CLI.
Wszelkie informacje o standardach ECMA dostępne są pod adresem: http ://www. ecma -international.org. Z tej strony można nieodpłatniepobrać standard ECMA-335. CLI jest w rzeczywistości specyfikacją maszyny wirtualnej, która umożliwia uruchamianie programów napisanych w różnych językach programowania wysokiego poziomu w różnych systemach operacyjnych bez zmiany lub ponownej kompilacji kodu źródłowego. CLI defi niuje standardowy język pośredni dla maszyny wirtualnej , do którego kompilowany jest kod napisany w jednym z języków programowania wysokiego poziomu. Na platformie .NET język ten nazywany jest Microsoft Intermediate Language (MSIL). Kod pośredni jest ostatecznie mapowany na kod maszynowy "w locie" przez kompilator typu JIT podczas wykonywania programu. Kod pośredni CLI można oczywiście uruchomić w dowolnym śro dowisku posiadającym implementację CLI .
Rozdzial1. • Programowanie przy użyciu Visual C++ 2005
29
CLI definiuje także wspólny zbiór typów danych, zwany Common Type System (CTS), którego należy używać przy pisaniu programów w językach mających na celu implementację CLI. CTS określa sposób używania typów danych w CLR i zawiera zestaw predefiniowanych typów. Można także definiować własne typy danych, ale należy trzymać się określonych reguł , aby zachować zgodność z CLR (o tym za chwilę). Standardowy system reprezentacji typów danych pozwala na jednolitą obsługę danych z poziomu komponentów napisanych w różnych językach programowania, a także na ich integrację w obrębie jednej aplikacji . CLR znacznie zwiększa bezpieczeństwo danych i niezawodność kodu, częściowo ze względu na fakt, że dynamiczne przydzielanie i zwalnianie pamięci odbywa się w pełni automatycznie, a częściowo ponieważ kod MSIL jest dokładnie sprawdzany i poddawany walidacji przed wykonaniem programu. CLR jest tylko jedną implementacją specyfikacji CLI , która jest wykonywana w systemie Microsoft Windows na komputerach osobistych. Bez wątpienia implementacje CLI dla innych systemów operacyjnych i platform sprzętowych także będą się pojawiać. Terminy CLI i CLR mogą być czasami stosowane zamiennie, ale należy pamiętać , że nie oznaczają one dokładnie tego samego. CLI jest specyfikacją standardu, CLR zaś stwo rzonąprzez firmę Microsoft implementacją CLI.
Pisanie programów wC++ Visual C++ 2005 umożliwia tworzenie wszelkiego rodzaju programów i ich składników . Jak już wspominałem wcześniej, w systemie Windows mamy do wyboru dwa typy aplika cji: programy wykonywane za pomocą CLR oraz programy kompilowane bezpośrednio do kodu maszynowego i wykonywane natywnie na komputerze . Tworząc aplikacje oparte na oknach dla CLR, jako podstawę GUl wykorzystuje się Windows Forms, które dostarczane są w bibliotekach platformy .NET. Korzystanie z Windows Forms znacznie przyspiesza tworze nie graficznego interfejsu użytkownika, gdyż tworzy się go w trybie graficznym ze standar dowych komponentów, a kod generowany jest automatycznie. Programiście pozostaje już tylko dopasowanie tak powstałego kodu do własnych potrzeb w celu uzyskania wymaganej funkcjonalności. Tworząc
kod wykonywany natywnie, do wyboru mamy kilka opcji . Jedną z nich jest użycie biblioteki Microsoft Foundation Classes (MFC) służącej do zaprogramowania interfejsu użytkownika aplikacji Windows. Biblioteka MFC zawiera w sobie API systemu operacyjnego Windows do tworzenia i kontrolowania GUl, a także znacznie ułatwia proces rozwoju pro gramu. API Windows powstało dużo wcześniej niż język C++, a więc nie zawiera żadnych cech właściwych technice programowania zorientowanego obiektowo, a byłoby tak, gdyby zostało napisane dzisiaj. Oczywiście, nie ma obowiązku używania MFC. Jeśli chcemy zyskać na wydajności , możemy napisać kod C++ z bezpośrednim dostępem do API Windows. Kod C++ wykonywany w CLR opisywany jest jako CH zarządzany (ang . managed C++), dane i kod są zarządzane przez CLR. W programach CLR zwalnianie pamięci przydzielonej dynamicznie odbywa się automatycznie. W ten sposób eliminuje się ryzyko wystąpienia błędów typowych dla natywnych aplikacji CH. Kod CH, który wykonywany jest poza CLR, zwany jest czasami przez Microsoft CH niezarządzanym (ang. unmanaged C++), ponieważ CLR nie bierze udziału w jego wykonywaniu. Korzystając z niezarządzanego ponieważ
30
Visual C++ 2005. Od podslaw C++, trzeba samodzielnie przydzielać i zwalniać pamięć podczas wykonywania programu . Należy się także liczyć z obniżeniem poziomu bezpieczeństwa, które daje CLR . Niezarządzany C++ może być czasami nazywany natywnym C++, gdyż kompilowany jest on wprost do kodu maszynowego . Na rysunku 1.1 pokazano podstawowe
możliwości
tworzenia programów w C++.
Rysunek 1.1
System operacyjny
Sprzęt
Rysunek 1.1 nie przedstawia jednak pełnego obrazu. Program może składać się jednocześnie z kodu napisanego w zarządzanym i natywnym C++ , a więc nie musimy trzymać się sztywno jednego stylu programowania. Oczywiście, mieszając dwa różne typy kodu , tracimy pewne rzeczy, a więc podejście to powinno być stosowane wyłącznie wtedy, gdy jest to konieczne, na przykład gdy chcemy przekonwertować istniejący już program napisany w natywnym C++ na program działający pod kontrolą CLR. Korzyści wynikające z używania zarządzanego C++ nie są oczywiście dostępne z poziomu C++ natywnego, a komunikacja pomiędzy składnikami programu napisanymi w tych dwóch typach języka może być znacznie wydłu żona. Możliwość łączenia zarządzanego i niezarządzanego kodu w jednej aplikacji może oka zać się jednak nie do przecenienia, gdy zajdzie potrzeba rozwinięcia lub rozszerzenia istnieją cego niezarządzanego kodu przy jednoczesnym korzystaniu z zalet używania CLR. Oczywiś cie, tworząc program od początku, przed rozpoczęciem jego pisania należy zdecydować się, jakiego typu aplikacją ma on być .
Nauka programowania dla slslemu Windows Tworzenie programów wykonywanych w systemie Windows oparte jest zawsze na dwóch podstawowych aspektach działania: utworzeniu graficznego interfejsu użytkownika (GUl), z którym użytkownik wchodzi w interakcje, oraz wykonaniu kodu przetwarzającego te inte
Rozdzial1. • Programowanie przy użyciU Visual C++ 2005
31
rakcje w celu zapewnienia aplikacji funkcjonalności. Visual C++ 2005 znacznie ułatwia pracę nad tymi aspektami tworzenia aplikacji Windows . W dalszej części tego rozdziału przekonamy się, że można stworzyć działający program dla Windowsa z GUl bez napisania nawet jednego wiersza kodu . Cały podstawowy kod może zostać wygenerowany automatycznie przez Visual C++ 2005 . Zrozumienie sposobu działania tego kodu jest jednak niezbędne, gdyż później będziemy chcieli go zmodyfikować i rozszerzyć, aby wykonywał zamierzone przez nas czyn ności. Aby tego dokonać , musimy bardzo dobrze rozumieć C++ . Z tego powodu na początku skupimy się na nauce samego języka C++ (zarówno natywnego, jak i w wersji C++/CLI), bez wdawania się w zawiłości programowania dla systemu Win dows. Gdy opanujemy już sam język C++, przejdziemy do tworzenia prawdziwych aplikacji Windows przy użyciu obu wersji języka C++. Oznacza to, że podczas nauki C++ będziemy tworzyć programy działające z poziomu wiersza poleceń. Dzięki takiemu podejściu będzie można skupić się na specyfice działania języka C++ i uniknąć w przyszłości komplikacji związanych z tworzeniem i kontrolą GUL Po opanowaniu C++ stwierdzisz, że przejście od praktycznego wykorzystania zdobytej wiedzy do tworzenia programów dla Windowsa jest naturalnym krokiem.
Nauka C++ Visual C++ 2005 standardach:
obsługuje
w
pełni
dwie wersje języka C++, zdefiniowane w dwóch
różnych
• Standard C++ ISO/ANSI służący do implementacji natywnych programów - C++ niezarządzany . Ta wersja języka obsługiwana jest przez większość platform komputerowych. • Standard C++/CLI, który został zaprojektowany specjalnie do tworzenia aplikacji działających pod kontrolą CLR i stanowi rozszerzenie C++ ISO/ANSI. Rozdziały od 2. do 10. poświęcone są nauce języka C++. Ze względu na fakt, że C++/CLI jest rozszerzeniem C++ ISO/ANSI , pierwsza część każdego rozdziału wprowadza elementy języka C++ ISO/ANSI, a druga objaśnia dodatkowe możliwości, których dostarcza C++/CLI. Pisząc programy w C++/CLI , możemy w pełni wykorzystać możliwości platformy .NET, co nie jest możliwe w programach pisanych w C++ ISO/ANSI. Mimo że C++/CLI jest rozszerze niem C++ ISO/ANSI , aby program mógł zostać wykonany całkowicie pod kontrolą CLR, musi on zostać napisany zgodnie z wymaganiami tej technologii. Oznacza to, że C++ ISO/ANSI posiada pewne właściwo ści , których nie można wykorzystywać w CLR. Jednym z przykładów, jak można się domyślić, jest brak kompatybilności mechanizmów przydzielania i zwalniania pamięci oferowanych przez C++ ISO/ANSI z CLR . Do zarządzania pamięcią musimy korzy stać z mechanizmu CLR, a to z kolei oznacza, że musimy używać klas C++/CLI, a nie na tywnych klas C++ .
32
Visual C++ 2005. Od podstaw
Standardy C++ Standard ISO/ANSI zdefiniowany jest w dokumencie ISO/lEC 14882 opublikowanym przez American National Standards Institute (ANSI). C++ ISO/ANSI istnieje od roku 1998 i ma już ugruntowaną pozycję . Obsługiwany jest przez kompilatory większości komputerowych platform sprzętowych i systemów operacyjnych. Programy napisane w C++ ISO /ANSI można dość łatwo przenosić pomiędzy różnymi systemami, chociaż prawdziwym wyznaczni kiem tego , czy dany program można łatwo przenieść, czy nie , są funkcje klas przez niego używanych w szczególności klas związanych z budową GUl. Standard C++ ISO/ANSI jest wybierany przez wielu profesjonalnych programistów ze względu na jego powszechną implementację oraz dlatego, że jest to jeden z naj potężniej szych dostępnych obecnie języków programowania.
Dokument iso.org.
opisujący
standard C++ ISO/ANSI
można zamówić
na stronie: http://www.
C++/CLI jest natomiast wersją języka C++, która rozszerza jego standardowe możliwości, czemu lepiej obsługuje specyfikację CLI zdefiniowaną w standardzie ECMA-355. Pierwsza wersja robocza tego standardu pojawiła się w 2003 roku i była rozwijana ze wstępnej specyfikacji techn icznej stworzonej przez Microsoft w celu umożliw ienia uruchamiania programów C++ na platformie .NET. Tak więc zarówno CLI, jak i C++ /CLI wywodzą się z firmy z Redmond , a ich przeznaczeniem jest współpraca z platformą .NET. Oczywiście ustandaryzowanie CLI oraz C++/CLI znacznie podwyższa prawdopodobieństwo implemen tacji w środowiskach innych niż Windows . Należy jednak pamiętać, że mimo iż C++/CLI jest rozszerzeniem C++ ISO/ANSI, to niektórych właściwości tego języka nie możemy wykorzy stywać, jeżeli chcemy, aby nasze programy działały w pełni pod kontrolą CLR . O właściwo ściach tych piszę w następnych rozdziałach.
dzięki
CLR ma pewne właściwości, które dają mu znaczną przewagę nad środowiskiem natywnym. Programy pisane dla CLR są bezpieczniejsze i mniej podatne na potencjalne błędy, które łatwo popełnić podczas wykorzystywania wszystkich możliwości C++ ISO/ANSI. CLR usu wa również wszelkie niekompatybilności związane z zastosowaniem różnych języków wyso kiego poziomu poprzez ustandaryzowanie środowiska, dla którego tworzone są programy. Dzięki temu można łączyć moduły napisane w C++ z modułami napisanym i w innych języ kach, takich jak C# lub Yisual Basic .
Aplikacje działające
wtrybie konsoli
Poza typowymi programami dla Windowsa, Yisual CH 2005 pozwala także na pisanie, kom pilowanie i testowanie programów C++ pozbawionych całego bagażu wymaganego od apli kacji okienkowych. Aplikacje te działają w oparciu o tryb tekstowy i wiersz poleceń . W Yisual CH 2005 nazywają się one aplikacjami konsolowymi (ang. eonsole applicationsy, ponieważ komunikacja z nimi odbywa się za pomocą klawiatury i ekranu w trybie tekstowym . Pisząc tego typu programy, można odnieść wrażenie, że odchodzimy nieco od tematu książki (jest to konieczne przed rozpoczęciem programowania specjalnie dla systemu Windows), ale jest to najlepszy sposób nauki C++. Nawet prosty program w Windowsie zbudowany jest
Rozdział 1.
• Programowanie przy użyciu Visual C++ 2005
33
liczby wierszy kodu i ważne jest, aby zawiłości związane z systemem Windows nie naszej uwagi skupionej na mechanizmach działania języka C++. W związku z tym w początkowych rozdziałach, w których uczymy się samego języka C++, będziemy tworzyć proste aplikacje konsolowe, a dopiero później przejdziemy do bardziej skompliko wanych, złożonych z dużej liczby wierszy kodu, programów dla Windowsa. z
dużej
rozpraszały
Podczas nauki C++ będziemy mogli skoncentrować się na właściwościach języka, nie mar twiąc się o środowisko, w którym operujemy. Aplikacje konsolowe, które będziemy tworzyć, posiadają interfejs tekstowy, ale dla zrozumienia C++ to całkowicie wystarczy. Sam język z definicji nie posiada żadnych możliwości graficznych. Oczywiście programowaniu graficz nego interfejsu użytkownika poświęciłem dużo miejsca, ale w tej części książki, która została poświęcona programowaniu dla Windowsa przy użyciu biblioteki MFC w natywnym C++ oraz Windows Forrns z CLR . Istnieją dwa rodzaje aplikacji konsolowych i będziemy używać obu. Aplikacje konsolowe Win32 kompilowane są do kodu natywnego i za ich pomocą będziemy wypróbowywać moż liwości C++ ISO/ANSI. Aplikacje konsolowe CLR tworzone są dla CLR, a więc będziemy ich używać, pracując z językiem CH/CLI.
Koncepcie programowania wsystemie Windows do programowania dla systemu Windows zakłada wykorzystanie wszystkich w Visual C++ 2005. Narzędzia służące do tworzenia nowego projektu potrafią automatycznie wygenerować kod szkieletu różnego rodzaju aplikacji, włączając w to podstawowe programy dla Windowsa. Proces pisania każdego programu lub komponentu w Visual C++ 2005 rozpoczyna się od utworzenia nowego projektu. Aby sprawdzić , jak to działa, w dalszej części rozdziału utworzymy kilka przykładów włącznie ze szkieletem pro gramu dla Windowsa.
Nasze
podejście
narzędzi dostępnych
Programy w Windowsie mają inną budowę niż typowe aplikacje konsolowe wykonywane za pomocą wiersza poleceń - są bardziej skomplikowane. W aplikacji konsolowej dane można przyjmować wprost z klawiatury i wyniki działań wysyłać z powrotem do wiersza poleceń. Programy dla Windowsa natomiast pobierają i wysyłają dane wyłącznie za pomocą funkcji systemu Windows . Nie pozwalają one na dostęp do zasobów sprzętowych . Ze względu na fakt, że system Windows pozwala na uruchamianie kilku aplikacji naraz, musi on umieć określić, dla której z nich przeznaczone zostało dane zdarzenie, np. kliknięcie przyciskiem myszki lub naciśnięcie klawisza na klawiaturze, a następnie wysłać sygnał do właściwego programu. Dzięki temu system Windows sprawuje podstawową " ko n tro l ę nad całym procesem komuni kacji z użytkownikiem. A zatem natura interfejsu pomiędzy użytkownikiem a systemem Windows jest taka, że po zwala na wiele różnych operacji wejścia i wyjścia w tym samym czasie. Użytkownik może wybrać jedną z wielu opcji dostępnych w menu, kliknąć przycisk na pasku narzędzi czy przy ciskiem myszki w dowolnym miejscu okna aplikacji. Dobrze zaprojektowany program dla Windowsa musi być przygotowany na wszelkiego rodzaju dane wejściowe w dowolnym czasie, gdyż nie ma sposobu dowiedzenia się z góry, jakiego rodzaju dane wejściowe zostaną przekazane . Czynności tego typu wykonywane przez użytkownika są przechwytywane przez system jako pierwsze i nazywają się zdarzeniami. Zdarzenie wywołane przez użytkownika
34
Visual C++ 2005. Od podstaw w obrębie interfejsu powoduje zazwyczaj wykonanie określonego fragmentu kodu. A zatem sposób wykonywania całego programu zależy od zachowania użytkownika. Programy ope rujące w ten sposób nazywane są programami zdarzeniowymi i różnią się od zwykłych programów proceduralnych, które odznaczają się pojedynczą kolejnością wykonywania . Wprowadzanie danych do programu proceduralnego kontrolowane jest przez jego kod i może mieć miejsce tylko wtedy, gdy program na to zezwoli. Tak więc program Windows składa się przede wszystkim z fragmentów kodu , które reagują na zdarzenia spowodowane przez użyt kownika lub sam system. Struktura tego typu programu została przedstawiona na rysunku 1.2.
Rysunek 1.2 Każdy prostokąt na rysunku 1.2 reprezentuje fragment kodu napisany specjalnie do obsługi jednego określonego zdarzenia. Z rysunku można wywnioskować, że przedstawiony pro gram jest nieco rozbity ze względu na brak połączeń pomiędzy niektórymi blokami, ale tak nie jest, gdyż głównym spoiwem jest tutaj system operacyjny Windows. Pisząc program, można go traktować jako swego rodzaju naukę wykonywania określonych czynności w sys temie Windows.
Rozdział 1.
• Programowanie przy użyciu Visual C++ 2005
35
Oczywiście wszystkie moduły obsługujące różne zdarzenia zewnętrzne, takie jak wybór menu
lub kliknięcie przyciskiem myszki , mają dostęp do wspólnej puli danych właściwych dla danej aplikacji. Dane te zawierają informacje o tym, czym jest program - np. bloki tekstu w edytorze lub rekordy przechowujące punkty gracza w programie mającym za zadanie śle dzenie wyników drużyny piłkarskiej - jak również informacje o niektórych zdarzeniach ma jących miejsce podczas wykonywania programu . Te współdzielone dane pozwalają różnym częściom programu, które wydają się niezależne, komunikować się oraz operować w skoor dynowany i zintegrowany sposób. Więcej na ten temat piszę w dalszej części książki. Nawet najbardziej podstawowy program dla Windowsa składa się z kilku wierszy kodu, a w programach wygenerowanych za pomocą kreatora takiego jak Visual C++ 2005 kilka przeistacza się w kilkaset. Aby uprościć proces nauki C++, potrzebujemy jak najprostszego kontekstu. Na szczęście Visual C++ 2005 posiada ś ro d o w i s k o w sam raz nadające się do tego celu.
Czym jest zintegrowane środowisko programistyczne Zintegrowane środowisko programistyczne (ang. Integrated Developm ent Environment IDE) , które dostarczane jest z Visual C++ 2005, jest kompletną platformą do tworzenia, kom pilowania, konsolidowania i testowania programów napisanych w C++. Tak się składa, że doskonale nadaje się również do nauki języka C++ (w szczególności w połączeniu z dobrą książką).
Visual C++ 2005 zawiera wiele w pełni zintegrowanych narzędzi zaprojektowanych w celu uproszczenia całego procesu pisania programów w C++. Część tych narzędzi poznamy już w tym rozdziale, ale zamiast przedzierać się przez nudną listę abstrakcyjnych opcji i właściwo ści, najpierw opanujmy podstawy, aby zobaczyć, jak działa IDE. Reszta przyjdzie stopniowo, w miarę postępu nauki.
Składniki
systemu
Podstawowymi składnikami Visual C++ 2005, dostarczanymi jako część IDE, są edytor, kompilator, program łączący (konsolidator) oraz biblioteki. Są to narzędzia niezbędne do napisania i wykonania programu w C++ . Ich funkcje zostały opisane poniżej .
Edylor Edytor jest interaktywnym środowiskiem do tworzenia i edycji kodu źródłowego w języku C++. Poza typowymi, znanymi każdemu funkcjami typu kopiuj i wklej, edytor posiada także funkcję kolorowania kodu . Edytor automatycznie rozpoznaje podstawowe słowa kluczowe
36
VisIlai C++ 2005. Od podstaw w języku C++ i nadaje im odpowiedni kolor, zgodnie z ich przeznaczeniem. Funkcja ta nie tylko sprawia, że kod jest o wiele bardziej czytelny, ale także pozwala natychmiast zoriento wać się, że został popełniony błąd przy wpisywaniu tych słów.
Kompilator Kompilator konwertuje kod źródłowy na kod obiektowy oraz wykrywa błędy występujące podczas procesu kompilacji i o nich raportuje. Kompilator potrafi wykryć wiele różnego rodzaju błędów związanych z nieprawidłowym lub nierozpoznanym kodem, jak również błę dów strukturalnych, np. kiedy fragment kodu nigdy nie zostanie wykonany. Kod obiektowy wygenerowany przez kompilator przechowywany jest w plikach zwanych plikami obiekto wymi. Istnieją dwa rodzaje kodu obiektowego, który może zostać wygenerowany przez kom pilator. Kody te zazwyczaj przechowywane są w plikach o rozszerzeniu .obj.
Program łącząCY Program łączący (konsolidator) dołącza różne moduły wygenerowane przez kompilator z pli ków z kodem źródłowym, dodaje wymagane moduły z kodem z bibliotek dostarczanych jako część C++ oraz łączy wszystko w jedną wykonywa1ną całość. Konsolidator może także wykrywać błędy i o nich raportować, np. gdy brakuje części programu lub gdy znajdzie odwołanie do nieistniejącego komponentu biblioteki.
Biblioteki Biblioteka to po prostu zbiór wcześniej napisanych procedur, które rozszerzają możliwości C++, dostarczając standardowych, profesjonalnie zaprojektowanych jednostek kodu, które można wykorzystać we własnych programach w celu wykonania niektórych częstych operacji. Operacje zaimplementowane przez procedury w rozmaitych bibliotekach dostar czanych przez Visual C++ 2005 znacznie zwiększają produktywność, ponieważ pozwalają zaoszczędzić czas potrzebny na napisanie i testowanie kodu dla tych operacji. Wspominałem już o bibliotece platformy .NET, ale jest ich o wiele więcej, zbyt wiele, by je wszystkie tutaj wymienić, ale najważniejsze z nich zostaną opisane.
języka
Standardowa biblioteka C++ definiuje podstawowy zestaw procedur wspólnych dJa wszyst kich kompilatorów C++ ISO/ANSI. Zawiera wiele procedur, na przykład funkcje operujące na liczbach (na przykład obliczające pierwiastek kwadratowy czy funkcje trygonometryczne), procedury przetwarzania znaków i ciągów, takie jak klasyfikacja znaków i porównywanie ciągów, a także wiele innych. W trakcie nauki języka C++ ISO/ANSI nauczymy się posługi wać wieloma z nich. Istnieją także biblioteki obsługujące rozszerzenia C++/CLI do C++ ISO/ANSI. Natywne aplikacje oparte na oknach obsługiwane są przez bibliotekę zwaną Microsoft Foun dation Classes (MFC). Biblioteka ta w znacznym stopniu ułatwia proces tworzenia graficz nego interfejsu aplikacji. Więcej na temat biblioteki MFC dowiemy się po zakończeniu nauki języka C++. Inna biblioteka zawiera zestaw narzędzi - zwanych Windows Forms - mniej
Rozdział 1.
• Programowanie przy użyciu Visual C++ 2005
37
więcej o d po w i ad ający c h
bibliotece MFC dla programów opartych na oknach, które wyko nywane są za pomocą ś ro d o w is k a .NET . W dalszej częśc i ks i ążki dowi emy się, jak używać biblioteki Windows Forms do tworzenia programów.
Używanie IDE Wszystkie programy w tej książce s ą tworzone i wykonywane wewnątrz IDE. Po uruchomien iu aplikacj i Visual C++ 2005 powinni śm y zoba czyć okno podobne do tego na rysunku 1.3. 1'';
m [gJ
Start Page - Microsoft Visual Studio Edit View rocs
File
- =t
..
l'r1SON: Vlsual C+ +
Recent Proleci'
C+ + At Wark : IRegis:tr ar , Finding su bme nus . and Mor-e Fr l, 08 sep 2C06 21:49 ;4 1 GMT - Thls rnonlh : DLL problams, conta xt menus, rvu= C str j-qs to managedC++, and mors.
C+ + At Wark : Cr eat e dynamie dialogs, sat ellite Dt.Ls, and more fv'o1, 07 Aug 2006 2 1:36 :2 1 GMT - Th is mon lh Pau l rx.ssoa te ac hes
Open : Create:
Project.;
1\.';Jf"-!'"' s a..
Pro]BC t ..
[weo SIt..
rea ders the rkjl t wCtI to ( rea le dyna mk: dł a logs , explains setalute OLls and discusses lcI1guagereso.rce Oll s. C + + At Wark : Customizing Combobox and Listbox Fn, 07.1J ł 2OC620 :29 :28 GMT - This rnonlh Faul Djt esc ta codes same M ~rosoft OffK:e· styls dialog box featur es.
Net ti ng C + + : Resouc:e Cleanup
Ge lting Sta rted
No detin1t.1on e e i e e e e e
Ready
Rysunek 1.3 Okno znajduj ące się po lewej stronie na rysunku 1.3 to okno ekspl oratora rozwiązań (So/ution Exp/orer), okno znajdujące się w prawym górnym rogu, w którym obecnie wyświetlona zo st ała strona startowa, to okno edytora (Edit or window), a okno na samym dole to okno wyj ś ci a (Output window). Okno eksploratora rozwiązań umożl iwia nawigację pomiędzy plikami programu oraz wy świetlan i e ich zawarto ści w oknie edytora, a także dodawanie nowych plików do programu. Okn o Solution Explorer może m ieć do trzech dodatkowych z akładek (na rysunku 1.3 widoczne s ą tylko dwie) , które reprezentują C/ass View (widok klas), Resour ce View (widok zasobów) oraz Property Manager (menedżer właściwo ści) aplika cji . Wyboru wyśw i e t l a nyc h zakład e k można dokonać w menu View. Okno edytora służy do wprowadza nia i modyfikowania kodu źródłowego oraz innych komponentów aplikacji. Okno Output wyświetla komunikaty powstałe w wyniku kompilacji i konsolidacji programu .
38
Visual C++ 2005. Od podslaw
Opcje paska narzędzi Paski narzędzi , które mają być wyśw i etl an e , w Visual C++ można wybrać, przyci skiem myszy w polu paska n arzędzi. Pojawia się menu zawieraj ące pasków n arzędzi (rysunek lA). Aktywne paski są zaznaczone.
Rysunek 1.4
'" l:=: '"
IL......J
klikając
prawym
listę dostępnych
Bu ild Class Designer Crystal Reports - In ser t Crys ta I Reports - Ma in Data Design Database Diagr-am
El
Debug Debug Location Device Dialog Edito r Formatti ng Help HTML Source Edit ing Image Editor Layout Query Designer Report Border s Report For matti ng Sour ce Contro i
El Standar d Sty le Shee t Tab le Designer Text Editor
W menu tym można wybrać , które paski narzędzi maj ą być zawsze widoczne. Można sobie podobne ś ro d ow i s ko pracy jak na rysunku 1.3, wybi eraj ąc kolejno elementy menu: Sui/d, Class Designer, Debug , Standard oraz View Designer. Aby wybrać element z listy, na leży klikn ąć na szarym polu po jego lewej stronie . Aby sc h ować element, trzeba kliknąć znak zaznaczenia znajdujący si ę po jego lewej stronie.
stworzy ć
Nie ma potrzeby przeładowywać okna aplikacji paskami n arzędzi , które mogą s ię nam kiedyś Niektóre z nich pojawiają się automatycznie, gdy są potrzebne, a więc prawdopo dobnie w większości przyp adków najlepszym rozwiązaniem okażą się domyślne ustawienia. Podczas tworzenia programu mo żemy dojść do wniosku , że byłoby wygodniej, gdyby niektóre paski narzędzi były wyświetlone cały czas. Zestaw wyświetlanych pasków można modyfi kowa ć wedle potrzeb, klik ając praw ym przyciskiem myszy na szarym polu w obrębi e paska n arzędzi i wybieraj ąc żąd an e paski z menu kontekstowego. przydać .
Rozdział 1.
• Programowanie przy użyciu Visual C++ 2005
39
Podobnie jak we wszystkich programa ch w Windowsie, w paskach narzędzi Visual C+ + 2005 dostępn e są chmurki z podpowiedziami . Aby dowiedzieć s ię. do czeg o służy dana opcja, należy umieścić nad nią kursor i odcz ekać sekundę lub dwie na wyświetlenie informacji w chmurce.
Dokowalne paski narzędzi Dokowalny pasek narzędzi to taki , który można dowolnie przemieszczać w obrębie okna za pomocą myszy . Kiedy zostanie umieszczony w pobli żu jednej z czterech krawędzi okna , jest dokowany i wyglądem przypomina paski widoczne na górze okna. Pasek znajdujący się w górnej linii, zawierający ikony dyskietek i ramkę tekstową po prawej stronie lornetki, nosi nazwę Standard. Można go przeciągnąć w inne miejsce okna , klikając go lewym przyciskiem myszy i - nie puszczając tego przycisku - umieszczając go w innym dowolnym miejscu. Po odciągnięciu od krawędzi pasek zamienia się w oddzielne okno, które można dowolnie przemieszczać.
Po odciągnięciu dokowalnego paska narzędzi wygląda on jak standardowy pasek widoczny na rysunku 1.5. Ma on postać niewielkiego okna opatrzonego odpowiednią etykietą. Pasek w takim stanie nazywa się paskiem pływającym. Wszystkie paski narzędzi widoczne na rysunku 1.3 mogą być dokowane i pływające. Spróbuj przeciągnąć niektóre z nich. Kiedy zostaną zadokowane, wracają do swojego dawnego wyglądu. Paski można dokować przy każdej z czterech krawędzi okna głównego.
Rysunek 1.5 Niektóre ikony paska zadań Visual C++ 2005 będą wyglądały podobnie do tych znanych z innych aplikacji systemu Windows, ale ich przeznaczenie w Visual C++ może być trochę inne. Z tego powodu będę wyjaśniał, do czego one służą, gdy nastąpi potrzeba ich użycia. Jako że do tworzenia nowego programu za każdym razem trzeba tworzyć nowy projekt, dobrym punktem startowym nauki obsługi Visual C++ 2005 będzie zaznajomienie się z mechanizmem definiowania projektów.
Dokumentacia Nadarzy się wiele sytuacji, w których będziemy mieli potrzebę zasięgnięcia dodatkowych informacji o Visual C++ 2005. Wyczerpującym źródłem wiedzy na ten temat jest dokumenta cja MSDN (ang. Microsoft Development Network Librarys. Zawiera ona opis wszystkich możliwości programu, a także wiele innych informacji. Podczas instalacji Visual C++ 2005 pojawia się opcja pozwalająca zainstalować pełną dokumentację MSDN. Jeżeli dysponujesz wystarczającą ilością miejsca na dysku, to zachęcam Cię do jej zainstalowania.
40
Visual C++ 2005. Od podstaw Aby uzyskać dostęp do zasobów MSDN, należy nacisnąć klawisz F l . Menu Help umożliwia przeszuk iwanie dokumentacji na różne sposoby. Poza źródłem wiedzy o możliwościach pro gramu, dokumentacja MSDN stanowi przydatne narzędzie, gdy ma się do czynienia z błędam i w kodzie , o czym przekonamy się w dalszej części rozdziału .
Projekt' i rozwiązania Projekt jest zbiorem wszystkich składników składających się na program - może to być program konsolowy, program oparty na oknach lub jeszcze inny typ programu. Zazwyczaj składa się on z jednego lub większej liczby plików z kodem źródłowym oraz prawdopodobnie innych plików zawierających dodatkowe dane . Wszystkie pliki projektu przechowywane są w folderze projektu , a szczegółowe informacje o nim przechowywane są w pliku XML o rozszerzeniu . vcproj, który również znajduje s i ę w folderze projektu. Folder projektu zawie ra równ ież inne foldery, w których zapisywane są pliki powstałe w procesach kompilacji i konsolidacji projektu. Czym jest rozwiązanie, mówi już sama jego nazwa. Jest to mechanizm łączący wszystkie pro gramy i inne zasoby składające się na rozwiązanie jednego problemu związanego z przetwa rzaniem danych . Na przykład rozproszony system zgłaszania zamówień dla operacji bizneso wych mógłby składać się z kilku różnych programów, z których każdy mógłby być rozwijany jako projekt w obrębie jednego rozwiązania. Tak więc rozwiązanie stanowi folder, w którym przechowywane są wszelkie informacje dotyczące jednego lub większej liczby projektów. Co za tym idzie, w folderze tym znajduje się co najmniej jeden podkatalog z projektem. Dane na temat projektów rozwiązania przechowywane są w dwóch plikach o rozszerzeniach .sln oraz .suo. Nowe rozwiązanie tworzone jest automatycznie, gdy tworzy się nowy projekt, chyba że dodamy go do już istniejącego rozwiązania. Kiedy podczas tworzenia projektu zostanie utworzone rozwiązanie , to istnieje możliwość póź niejszego dodawania do niego następnych projektów. Można dodawać projekty dowolnego rodzaju, ale zazwyczaj dodaje się takie, które są w jakiś sposób powiązane z już istniejącym lub istniejącymi projektami w rozwiązaniu. Z reguły, jeżeli nie istnieją żadne przeciwwska zania, każdy projekt powinien być przypisany do jakiegoś rozwiązania. Wszystkie przykłady w tej książce stanowią pojedyncze projekty z własnymi rozwiązaniami .
Definiowanie projektu Pierw szą czynnością, którą należy wykonać , aby rozpocząć pisanie programu w Yisual C++ 2005, jest stworzenie nowego projektu, kolejno wybierając opcje File/New/Project lub naci skając kombinację klawiszy Ctrl+Shift+N. Poza plikami zawierającymi cały kod i wszelkie inne dane, które składają się na program , w folderze projektu znajduje się plik XML. Są w nim zapisywane wszystkie opcje Yisual C++ 2005, których używaliśmy. Mimo że nie ma potrzeby własnoręcznego edytowania tego pliku (tym zajmuje się w całości IDE), to można go otworzyć i sprawdzić, co zawiera. Pamiętaj tylko, aby nie zmienić przez przypadek jego zawartości.
Na tym
skończymy, jeśli
chodzi o teorię. Czas
zabrać się
do pracy.
Rozdział1.
• Programowanie przy użyciu Visual C++ 2005
41
~ Tworzenie proiektu aplikacji konsolowej dla systemu Win32 Utworzymy teraz projekt aplikacj i konsolowej. Najpierw z menu Fil e n ależy w ybr a ć opcje New/Projec t. Pojawi się okno dialogowe tworzenia nowego projektu, podobne do pokazanego na rysunku 1.6. -
_-
..
-
-
-- -
-----
-
----
-
[1]rBJ
New Project Project types :
- ---,
lIisual Studio installed templates
1 - - - -.0. 0.00.. 0 -
ATL CLR
00
;~ W in32 Console Applicatron
General
t
m(@,
Templates :
;= Visual C++
Mf C Smar t Oevt e Win32
Other Languages
O\her ProJect Types
I
1'5IW k132 ProJect
I
~v Temp lat~
. Search Onlne Templ atesooo
L
IA prcject for creatrng a Wrn32 consoleapplication LQCation:
l ID :\Translations'ł>ellon\jvO'
sa"!lon Name :
,
Name :
Cwl _0l
I CW1_Ol
~'
Hortons Visual C++
.. -
I
-
L~l l
2005\Przyk łady
I
~Create di' ectDry for -soluton
I
ca ncel
I
--
I
I
BrOWS8 ...
OK
II
Rysunek 1.6 W lewym panelu okna dialogowego New Pr oject pokazane s ą dostępne typy tworzonych projektów . My wybieramy Win32. W ten sposób informujemy program , którego kreatora ma użyć do utworzen ia wstępn ych plików projektu . W prawym panelu widoczna jest lista szablo nów dostępnych dla wybranego typu projektu. Wybrany szablon zostanie wykorzystany przez kreator podczas tworzenia plików projektu. W następnym oknie, które poj awia się po klik n ięciu przycisku OK, możemy ustawić opcje dla tworzonych plików. W przypadku większo ści typów lub szablonów autom atycznie tworzony jest podstawowy zestaw modułów źródło wych programu . Możemy
teraz wpisać w polu Name wybraną nazwę dla naszego projektu, np. Cwl_Ol. Visual C++ 2005 pozwal a na stosowanie długich nazw plików, a więc mamy tu duże pole manewru. Nazwa folderu rozwiązania pojawia się w polu tekstowym na dole i domyślnie jest taka sama jak nazwa projektu. W razie potrzeb y można j ą jednak zmienić . W tym samym okn ie można także zmieni ć lok al izację folderu rozwiązani a na dysku za pomoc ą pola Location. Jeżeli wpi szemy tylko nazwę projektu, to zostanie on umieszczony w folderze o takiej samej nazwie w lokalizacji pok azanej w polu Location. Domyślnie, jeżeli fold er rozwiązania nie istnieje, zostanie on automatycznie utworzony. Jeśli chcemy, aby nasze pliki zostały zap isane w innym
42
Visual C++ 2005. Od podstaw katalogu , wystarczy zmienić ścieżkę w polu Location, wpisując ją ręcznie lub wyszukując za pomo cą opcji Browse. Kliknięcie przycisku OK spowoduje ukazanie s i ę okna dialogowego kreatora aplika cji Win32, który został zapre zentowan y na rysunku 1.7.
Rysunek 1.7 Welcom e to th e Win32 Application Wlzard
These ere the currentprO)ect settings:
Ovet"łiew AppkaŁkm
5ettirqs
• ccesce ~(~ion
ekkFinishfrem any wroow to eccept tbe current seł:Łf'J05 . Afteryou creete the project, see the pecject 'sreeone. txt f ~ e for inforrMtion ebout the projectfeaturesand flles that.ere ęenereted.
",. "
"' I
LI
Next>
II
F" j,h
II
C.ncel
l
Okno to zawi era informacj e o wybr anych opcjach. Kliknięcie przycisku Finish spowoduj e utworzenie na podstawie tych informacji wszystkich plików projektu. W oknie tym możem y także zmienić ustawienia aplikacji , klikając Application Settings po lewej stronie kreatora, jak pokazano na rysunku 1.8.
Rysunek loB Appllcation Set tings
Overvlew
AppIication SeUjng<
Add corrmcn heeder f ~es for:
ApplicatiOn tvce :
O 'f!lfldows application
o CQO'oie applicotloo
D an D~FC
O Qll
O 2lalk 10 ' 01")' AddilionalQPl;1ons:
D ~mpty projed ~f.oort~ J)l,
o Erecompded beeeer .
I < Prevlou, I "-"
F ,,~h
II
Cancel
Okno Application Settings pozwala na wybór opcji projektu. C h oć w przypadku w iększości projektów, które będziemy tworzyć podczas nauki języka C++ , wybierzemy opcję Empty project, tym razem możemy pozostawić ją bez zmian i kliknąć przycisk Finish . Kreator apli kacji utwo rzy projekt ze wszystkimi domyślnymi plikami.
Rozdział 1. • Programowanie przy użyciu VisIlai C++ 2005
43
Folder projektu ma taką samą nazwę, jaką podaliśmy dla samego projektu, oraz zawiera wszystkie pliki składające się na projekt. Folder rozwiązania ma nazwę taką samą jak folder projektu - chyba że ją zmieniliśmy - oraz zawiera pliki definiujące zawartość rozwiązania. Przeszukując zawartość folderu rozwiązania za pomocą eksploratora Windows, stwierdzisz, że zawiera on trzy pliki : • plik z rozszerzeniem .sln, w którym zapisywane
są
informacje o projektach
rozwiązania,
• plik z rozszerzeniem .suo, w którym przechowywane dotyczącego tego rozwiązania,
są
opcje
użytkownika
• plik z rozszerzeniem .ncb, który przechowuje dane Intellisense dla rozwiązania. Intellisense to narzędzie automatycznie uzupełniające i podpowiadające podczas pisania kodu w oknie edytora. Jeżeli
zajrzymy do folderu projektu za pomocą eksploratora Windows, to znajdziemy tam plików, z których jeden to ReadMe.txt, zawierający infor macj e o zawartości plików utworzonych dla projektu. Jedynym plikiem, o którym może nie być żadnych informacji w pliku ReadMe.txt,jest plik o złożonej nazwie typu Cwl _OI.vcproj.NazwaKomputera. NazwaUzytkownika.uzytkownik, w którym przechowywane są ustawienia projektu. sze ść
Utworzony projekt zostanie automatycznie otwarty przez Visual C++ 2005 w lewym panelu, jak widać na rysunku 1.9. Celowo zwiększyłem jego szerokość, aby było widać pełne nazwy na zakładkach .
Okno Solution Explorer pokazuje wszystkie projekty w bieżącym rozwiązaniu oraz zawarte w nich pliki - u nas oczywiście jest tylko jeden projekt . Zawartość każdego z plików można wyświetlić w nowej zakładce w oknie edytora, dwukrotnie klikając jego nazwę lewym przy ciskiem myszy w zakładce okna Solution Explorer. Pomiędzy poszczególnymi otwartymi pli kami w panelu edycyjnym można się szybko przemieszczać, klikając odpowiednią zakładkę. Zakładka
C/ass View pokazuje listę klas zdefiniowanych dla projektu oraz treść każdej z nich. W naszej aplikacj i nie ma żadnych klas, a więc zakładka jest pusta. Kiedy będziemy mówić o klasach, przekonasz się, że za pomocą zakładki C/ass View można łatwo i szybko poruszać się po kodzie odnoszącym się do definicji i implementacji wszystkich klas.
44
VislJal C++ 2005. Od podstaw Zakładka
Property Manager pokazuje właściwości, które zostały ustawione dla wersji testo wej i ostatecznej (ang. Debug i Release) projektu. Znaczenie tych wersji wyjaśnimy w dalszej części rozdziału. Dowolną właściwość można zmienić, klikając ją prawym przyciskiem myszy i wybierając opcję Properties z menu kontekstowego. Spowoduje to wyświetlenie okna dialo gowego, w którym można ustawić właściwość projektu . Innym sposobem wyświetlenia okna dialogowego właściwości jest naciśnięcie kombinacji klawiszy Alt+F7. Więcej na ten temat piszę przy okazji opisywaniu wersji testowej i ostatecznej programu. Zakładka Resource View pokazuje okna dialogowe, ikony, paski narzędzi i inne zasoby uży wane przez program. Jako że nasz program to aplikacja konsolowa, nie używa on żadnych zasobów. Gdy rozpoczniemy pisać programy dla Windowsa, to w tym miejscu pojawi się wiele elementów. Za pomocą tej zakładki można dodawać do projektu dostępne zasoby lub
edytować już istniejące .
Jak w przypadku większości składników IDE Visual C++ 2005, w zakładce Solution Explorer, a także w innych zakładkach dostępne są menu zależne od kontekstu, które pojawiają się po kliknięc iu prawym przyciskiem myszy jednego z elementów zakładki, a czasami także w jej pustym obszarze. Jeżeli panel Solution Explorer przeszkadza Ci podczas pisania kodu, możesz go ukryć, klikając ikonę Autohide. Aby go ponownie wyświetlić, należy kliknąć jego nazwę po lewej stronie okna IDE.
Modyfikowanie kodu źródłowego Kreator aplikacji generuje kompletny program konsolowy Win32, który można poddać kom pilacji i uruchomić . Niestety program ten w obecnym stanie nic nie robi . Aby był on bardziej interesujący, należy wnieść do niego kilka zmian . Jeżeli nie widać go jeszcze w panelu Edi tor, dwukrotnie kliknij plik Cwl_Ol.cpp w panelu Solution Explorer. Jest to główny plik z kodem źródłowym programu, który został wygenerowany przez kreator aplikacji (rysu nek 1.10).
Rysunek 1.10
twl Ol.cpp~tP~
... x
I
Sil
(Global SCope)
~; L
TO '_'""'"""' r e t.ur n
9'
ta
vi --l
~ e r qc ,
- TCHAR'
a"gv[) I
o:
II
I
11
li
rz
I I
.J.
I <
-
I
> II ~
Rozdział 1.
• Programowanie przy użYCiu Visual C++ 2005
45
Jeżeli nie widzisz u siebie numerów linijek, to z menu Tools wybierz Options. Pojawi się okno opcj i. W oknie tym poszukaj opcji d oty czący ch edyt ora tekstowego (Text Editor) i kliknij C/C++, a następnie w prawej części okna zaznacz opcję Line numbers. Najpierw tylko z grub sza objaśnię, do czego służy kod widoczny na rysunku 1.10. Więcej na ten temat dowiesz się
trochę później.
komentarzami . Wszystko, co znajduj e s i ę za znakami / /w tym samym Jeżeli chcesz za pomoc ą komentarzy opisywać, co robi program, używaj tych znaków. Dwie pierwsze linijki
są
wi erszu, jest ignorowane przez kompilator.
W czwartej linijce znajduje się dyrektywa #i nc l ude, która zastęp owana je st zawartością pliku stdafx .h. Jest to standardowy sposób dodawan ia zawartości plików z rozszerzeniem .h do plików z kodem źródłowym o rozszerzeniu .cpp w programa ch w C++. Wiersz numer 7 jest pierwszym , który zawiera wykonywalny kod oraz
rozpoczęcie funkcji
_tmai nr). Funkcja to po prostu nazwany fragment kodu, który wykonuje jakieś zadanie. program w C++
s kła d a s i ę
Każdy
z co najmniej jednej , a zazwyczaj wielu funkcji .
Wiersze 8. i 10. zawierają odpowiednio otwarcie i zamknięcie nawiasu klamrowego, w obrębie które go znajduje s i ę wykonywalny kod funkcji _tmain O. A zatem cały wykonywalny kod znajduje si ę w wierszu 10., a jego jedynym zadani em je st zakoń czenie działania programu. Możemy
teraz
dodać następujące
II Cwl _OI.cpp: definiowanie punktu II
dwa wiersze kodu w oknie edytora:
wejściowego
dla aplikacji konsolowej .
#include "st dafx.h" #include int _tma in(i nt argc. _TCHAR* argv[]) {
st d: :cout return O:
«
"Witaj
św i ec i e
vn":
Niezaciemn ione wiersze to te, które zostały wygenerowane na samym początku. Wiersze, które należy dodać , są w ramce. W celu dodania nowego wiersza umieść kursor na końcu poprzedniego i naci śnij klawisz Enter, co spo woduje utworzenie nowego, pustego wiersza, w którym można wpisać kod. Pamiętaj, że Twój kod musi być identy czny z kodem pokaza nym na listingu. W innym przypadku program może nie dać się poprawnie skompilować. Pierwszy z dwóch nowych wierszy to dyrektywa #i ncl ude dodająca do pliku źródłowego treść standardowych bibliotek C++ ISO/ANSI. Biblioteka zawiera definicje podstawo wych operacji wejścia-wyjścia. Drugi wiersz wysyła do wiersza poleceń tekst. st d: :cout jest nazwą standardowego strumienia wyjściowego i drugi dodany wier sz dokonuje zapi su do niego łańcucha "Wi t aj ś w i eci e I \n". Wszystko, co pojawi się pomiędzy podwójnymi cudzy słowam i, wypisywane jest w wierszu poleceń.
46
Visual C++ 2005. Od podstaw
Kompilacja rozwiązania Aby skompilować rozwiązani e, n al eży n a cisnąć klawi sz F7 lub wybrać z menu Build/Build Solution. Można także kliknąć odpowi edni przycisk na pasku narzędzi. Przyciski paska narzę dzi menu Build mogą nie być widoczn e, ale można to łatwo zmienić, klikając prawym przyci skiem myszy w obszarze paska narzędzi i wybi eraj ąc pasek Build z listy. Kompilacja programu powinna zakończyć się pomyślni e . J eżeli poj awi ą s i ę bł ędy, upewnij się, czy w kodzie nie ma żadnych pomyłek, a więc w s z c ze g ó l n ośc i dokł adnie sprawdź dwa nowe wiersze.
Pliki tworzone podczas kompilacji aplikacji konsolowej Po pomyślnym zakończeniu kompilacji projektu zajrzyj do folderu projektu i znajdź podkatalog o nazwie Debl/g . Katalog ten zawiera pliki powstałe w procesie wła śnie ukończonej kompilacji projektu. Zau waż, że znajduj e się w nim kilka plików. Wszystkie pliki, poza tym z rozszerzeniem .exe, który j est naszym programem w wykonywa1 nej formie , nie są dla nas i n te re s uj ąc e i nie musimy zbyt wiele o nich w i ed z i eć . Aby j ednak zaspokoić Twoj ą ci ekawość, zw ięźle wyj aśn iam, do czego służą bardziej interesujące z nich.
Rozszerzenie pliku
Opis
.exe
Program w postaci wykon ywalnej. Plik ten powstaje tylko wted y, gdy kompil acja i konsolidacja z akończą się powod zeniem .
.obj
Pliki te to pliki obiektowe i tworzone są przez kompilator. Zawierają one kod maszynowy z plik ów źródłowych programu. Razem z plikami bibliotek uż yw ane są przez konsolid ator do utworzenia pliku .exe.
.ilk
Plik ten używ any jest przez konsolidator w momencie przebudowy projektu . Pozwala on temu programowi na stopniowe dołączanie plików obiektowych utworzonych ze zmodyfikow anego kodu źró dł o we g o do istniejącego pliku .exe. Dzięki temu unika si ę ponownej kons olid acji wszystkich komponentów programu przy każdej je go zmianie.
.p ch
Jest to prekompilowany plik naglówkowy. W plikach tego typu przechowywane s ą duże ilo ś ci kodu, który nie podlega modyfikacji (w szczególności kod dostarc zany prz ez biblioteki C++). Kod ten zostaje przetworzony jeden raz, a następnie je st prz echowywany w pliku o roz szerzeniu .pch. Dzięki tym plikom ponowna komp ilacja programu zajmuje znacznie mniej czasu.
.pdb
Plik ten zaw iera informacj e debu gowania, które są wykorzystywane podczas uruchamia nia programu w trybie debugowania. W trybie tym możn a dynamicznie przegląd a ć informa cje generowane podczas działania programu .
.idb
Zawiera informacj e
u żywane
podczas przebudowy
rozwiązan i a .
Wersie 1es1owa i os1a1eczna programu Za pomocą menu Project/Cwl Ul Properties można ustawić wiele opcji dla projektu . Opcje te okre ślaj ą sposób przetwarzania kodu źródłowego podczas kompil acj i i konsol idacji . Zestaw opcji, za pomo cą którego utworzony został wykonywalny program, nazywa si ę konfigura cją (ang. conjiguration). Podczas tworzenia nowej powierzchni robocz ej dla projektu Visual
Rozdział 1.
• Programowanie przy użyciu Visual C++ 2005
47
C++ 2005 automatycznie tworzy konfiguracje do utworzenia dwóch wersji aplikacji. Jedna z nich, zwana wersją testową (ang. debug version), zawiera informacje pomocne przy poszu kiwaniu błędów w programie. Jeśli coś jest nie w porządku, przy użyciu wersji testowej moż na wykonać kod krok po kroku, sprawdzając dane w programie. Druga wersja to wersja osta teczna, która nie zawiera żadnych informacji pomocnych w debugowaniu i kompilowana jest z włączoną opcją optymalizacji, dzięki czemu otrzymujemy możliwie najbardziej wydaj ny moduł wykonywalny. Te dwie konfiguracje wystarczą nam na potrzeby tego kursu, ale jeżeli chcemy dodać inne konfiguracje dla aplikacji, to można to zrobić za pomocą opcji Configuration Manager znajdującej się w menu Build. Zauważ, że element ten nie jest widoczny, jeżeli nie ma załadowanego żadnego projektu. Oczywiście, nie jest to żadnym problemem, ale może być mylące, jeśli tylko przeglądamy interfejs programu, aby zobaczyć, co zawiera. Wyboru konfiguracji, z którą ma pracować nasz program, dokonujemy, zaznaczając odpo wiednią pozycję z listy rozwijanej Active solution configuration znajdującej się w oknie dia logowym Configuration Manager, jak widać na rysunku 1.11. Configuration Ma~ager
Rysunek 1.11
..a.c tlY8 soll tJJn coofgJraoon:
:0
~
~ase
_de--'p--' kJ--' ) ·_
,;Edrt-,=-",~>
-
A _c_ tive _ '_OlJ _tioo --,-p _latfur _ m_'
~r! ~32y .,---------.J
'V
--'---' Platform
WII'132
r1JlR! __ ;u ~
-----,
--"
Buikl
o
c_
Wybierz interesującą Cię konfigurację, a następnie naciśnij przycisk Close. Podczas two rzenia aplikacji będziesz pracować z konfiguracją testową. Po przeprowadzeniu testów przy użyciu konfiguracji debugowania, kiedy program nie sprawia żadnych problemów, zazwyczaj kompiluje się go jako wersję ostateczną. W ten sposób powstaje zoptymalizowany kod bez zbędnych możliwości debugowania i śledzenia, co sprawia, że działa on szybciej i zajmuje mniej pamięci.
Uruchamianie programu skompilowaniu rozwiązania możemy uruchomić nasz program, wciskając klawiszy Ctrl+F5. Powinno ukazać się okno, które zostało zaprezentowane na rysunku 1.12.
Po
pomyślnym
kombinację
48
Visual C++ 2005. Od podstaw
RysUnek 1.12
.. .
••
\H taj ś w Le c I e Aby kun ly n u uu",ć~
Ih' c i ćn i j
d O \.łOl ny
x
_ D
k lrt uis..! .
.
II _
_ _
Jak widać na rysunku, tekst, który znajdował się pomięd zy podwójnymi cudzysłowami, został wypisany w wierszu poleceń . Znaki \ n na końcu ciągu to specjalna sekwencja, zwana znakiem zastępczym, która oznacza znak nowego wiersza. Znaki zastępcze służą do reprezentowa nia w łańcuchach znaków, których nie można bezpośrednio wpisać z klawiatury.
Rm!rImI Tworzenie pustego projektu konsolowego Poprzedni przykład zawiera pewną ilość niepotrzebnego bagażu, który nie jest nam potrzebny podczas pracy z prostymi przykładami w języku C++. Domyślnie wybrana opcja prekom pilowanych nagłówków spowodowała stworzenie w projekcie pliku stdafx .h. Mechanizm ten usprawnia proces kompilacji w przypadku programu składającego się z dużej liczby plików, ale w wielu naszych przykładach jest on niepotrzebny. W takich przypadkach rozpoczynamy od utworzenia nowego projektu , do którego możemy dodać własne pliki źródłowe. Możesz sprawdzić, jak to dzi ała, tworząc nowy projekt w nowym rozwiązaniu dla programu konso lowego Win32 o nazwie Cwl_02. Po wprowadzeniu nazwy projektu i kliknięciu przycisku OK kliknij Applieation Settings po lewej stronie okna dialogowego, które się ukaże. N astęp nie po prawej stronie odszukujemy opcję Empty projeet i zaznaczamy ją, jak pokazano na rysunku 1.13.
Rysunek 1.13
Win32 ~P lic atio n Wizard - Cw1 ~02-
-
-- - m~
-
Application Settings
Overview
App~ cation type:
o l1ijr>Jows
. Add comrr.on heeder nes for:
. ~ic.t ion
o CQ'lsoie.pphcation
eh
O Q.ll
o
~tatic library
Aó1itional Opt IOOS:
o ~mpty proj ect o
t..,rLlft ..
er"'" c'
"lot
(j,-
I <:~relllous I
.I
f01ish
II
C. ncel
I
Po kliknięciu przycisku Finish, podobnie jak poprzednio, utworzony zostanie nowy projekt, ale bez ż adnych plików źródłowych.
Rozdzial1. • Programowanie przy użyciu Visual C++ 2005
49
Następnie
dodajemy nowy plik źródłowy do projektu. Klikamy prawym przyciskiem myszy w panelu Solunon Explorer i wybieramy Add/New !tem z menu kontekstowego. Pojawia się okno dialogowe. Po lewej stronie klikamy opcję Code, a następnie po prawej wybieramy C++ File (.cpp) . Wpisz nazwę pliku Cwl_02, takjak widać na rysunku 1.14. -
-
-
-
-
Add New Item - CwC02 Categorie s :
r'
-- --
-
--
m[g]
"-1
Templates :
Visual C++ Ul
Code Data
Visual Studio installed templates
t:.l C++ File (.epp)
t!!l
Header File (.h)
1!;)Module-Definition File (.def) ~ ln stalle r Clsss
~Midl File (.idl)
'i!l Comp:>nent Class
Resource Web
Utility Proper ty Sheets
_ My T~p~~!~S
.j
Search
I
ontne Templates...
I
L.
l
Creates a file containl '19 CH socrcs eode
Name: Locatlon :
I.
..
I
ICW1.o2/ , I d :\T ransla tJOns\)1elion\) vor HortDns Vlsual CH 2005\,Pr zyklady\Cw l . 02\Cw l . 02
II
Browse., ,
II
Cancel
..
I
Add
I I
Rysunek 1.14 przycisku OK do projektu dodawany jest nowy plik, a jego zawartość zostaje oknie edytora. Plik jest oczywiście pusty, a więc widoczne jest tylko białe pole. W oknie edytora wprowadź do niego n astępującą treś ć :
Po
kliknięciu
wyświetlona w
II Cwl_02.cpp - prosty program konsolowy.
#incl ude
II Podstawowa biblioteka II wejś cia-wyjś cia.
int ma i n() (
st d: :cout st d: :cout st d: :cout ret urn O:
Zauważ, że
« « «
"To j est prosty program. który wy świetla te kst. " « st d .endl : "M oż n a wy św ietl i ć wię c ej lini j ek t ekstu . " « st d: :endl : "powt a r zaj ą c in st r uk cj ę wyj śc i a podob n ą do tej " « st d: :endl .
II Powrót do systemu operacyjnego.
w czasie pisania kodu program automatycznie robi wcięcia. Wcięcia w języku C++ stosowane w celu zwiększenia przejrzystości kodu . Edytor stosuje wcięcie dla każdego wiersza na podstawie zawartości poprzedniego. W czasie wpisywania można także zaobser wować kolorowanie składni. Niektóre elementy programu pokazane są w różnych kolorach, ponieważ edytor automatycznie koloruje elementy języka w zależności od ich przeznaczenia. są
50
Visual C++ 2005. Od podstaw Kod na p ow y ż s zym listingu jest kompletnym programem. Można zauw a ży ć kilka różnic w porównaniu z kodem automaty cznie wygenerowanym przez kreator aplikacji w poprzednim przykładzie . Brakuje dyrektywy #i ncl ude dla pliku stdafx.h. Nie dołączyli śmy tego pliku do naszego projektu , gd yż nie używamy w nim narzęd zia prekompilowanych n agłówków . Tutaj mamy funkcj ę o nazwie ma i n, a w poprzednim przykład z ie była to _ tmai n. W rzeczyw i s tośc i wszystkie programy w C++ ISO/ANSI ro zpoczynaj ą si ę od funkcji main ( ). Microsoft dodał także wersję tej funkcji o nazwie wma i n, która jest u żyw an a przy wykorzystaniu znaków Uni code . Funkcja _ tma i n z o s t ał a zdefin iowana jako ma i n lub wma i n w zależn o ś c i od tego, czy w programie będ ą u żywane znaki Unicode. W poprzednim p rzykładzie funkcja _t ma in została niejawnie zdefini owana jako ma in. Funkcj i o nazwie mai n używamy we wszystki ch przykła dach w CH ISO/ANSI. Instrukcje w yj ś c i a st d: :cout
«
są trochę
inne. Pierwsza instrukcja w main( ) to:
"To j est prosty program. który
wy św tet la
tekst . "
«
st d :endl :
W dwóch miej scach pojawia się o perator « i za każd ym razem powoduje on wysłanie wszystkiego, co po nim następuje, do st d: :cout , czyli stand ardowego strumienia w yj ścio wego. Ciąg spomiędzy podwójnych c u d zys ł o w ó w zostaje w y słany najpierw do strumienia, a następnie do st d: :endl, który zdefiniow any jest w bibliotece standardowej jako znak nowego wiersza. Wc ze śniej wewnątrz łań cu ch a jako znaku nowego wiersza użyl i śm y znaku za s tęp czego \ n umieszczonego w cudzysłowach . Poprzednie wyraże n i e moglibyśmy również zap i s ać w następując y sposób: st d cout
«
"To j est prosty program , który
wyświet l e
t ekst .\ n":
Powinienem wyjaśnić , dlaczego powy ższy wiersz jest na przy ciemnionym tle . Ot ó ż , gdy p is zę wiersz kodu, który już wcześniej wid zieli śmy , to um ieszczam go na białym tle. Po wyż szy wiersz jest nowy, a więc o z naczyłe m to poprzez umie szczenie go na ciemniejszym tle . Tak jak poprzednio, możemy teraz s kom p i l ow a ć nasz projekt. Z auważ, że wszystkie otwarte pliki źró d ł o we zo stan ą zapisane automatycznie, jeżeli nie zr obili śmy tego sami w cze śniej . Po pomyślnym skompilowaniu programu w ci śnij kombinację klawi szy Ctrl+F5 w ce lu jego uruchomienia. Pojawi si ę okno podobne do tego, które jest wido czne na rysunku 1.15.
Rysunek 1.15
"
C:\WINDOWS\system32\cmd.exe
~~ ż~:~~y~~1:~ri2~:t~~:j ~~~i~ekY~;~::~: tekst . ~b~tk~~~~~~o~:~~r~:~1 ~ n~Jj~~t: lr.~d~~:~i~~ l ej .
1I1!1E:l
a
D Błędy Jeżeli
wpiszemy kod programu niepoprawnie, to kompilator zgło s i błędy. Aby sprawdzi ć , jak celowo popełnimy jeden błąd w naszym programie. Je żel i jednak udało Ci s i ę już zro b ić j akiś błąd , to mo że sz go wykorzyst ać do wykonan ia tego ćwicze ni a. Przejdź do okna edytora i usuń średnik znaj d uj ący s i ę na ko ń cu przedostatniego wiersza pomiędzy nawiasami to
działa,
Rozdział 1.
• Programowanie przy użyciu Visual C++ 2005
51
klamrowymi (ósmy wiers z). N astępnie skompiluj program ponownie. Panel wyników na dole zawiera teraz n astępujący komunikat o błędzi e:
C2143: synt ax error : mi ssi ng ' : ' before ' retur n' Każdy
komun ikat o błędzi e podc zas kompilacji ma swój numer, które go znaczenie m ożna w dokumentacji . W tym przypadku wiadomo, co s p ow o d owało wy s tąp i e ni e pro blemu . Jednak w wielu przypadkach dokumentacja może o kazać s i ę bardzo pomocna w odna lezieniu źródła problemu . Aby otwo rzyć tę część dokumentacji, która dotyczy naszego błędu , n ale ży klikn ąć wiersz zawie rający numer błędu i nacisnąć FI . Pojawi się nowe okno z dodat kowymi inform acjami na tem at błędu. Możn a to wypróbow ać na naszym błędzie. sp rawdzić
Po poprawieniu błędu możemy ponownie spróbować skompilować projekt. Operacja ta prze biega sprawnie, gd yż definicja projektu ś l edzi status plików s kład aj ącyc h s ię na niego. Pod czas normalnego procesu komp ilacji Visual C++ 2005 ponownie kompiluje tylko te pliki, które zmieniły się od momentu poprzedniej kompilacji. Ozn acza to, że j eśli mamy projekt skł adający się z kilku plików źródłowych i od momentu ostatniej kompilacji projektu zmiany wprowadziliśmy tylko do jednego z nich, to tylko ten jeden plik zostanie ponownie skompi lowany przed pro cesem kon sol idacji mając ym na celu utworzenie nowego pliku .exe. Będ ziemy także omawiać kł ad
pro gramy konsolowe CLR, a zatem projektu konsolowego CLR .
poniżej
przedstawiam przy
~ Tworzenie projektu konsolowego elB N a ci śnij
klawisze Ctrl+Shijt+N, aby pojawiło się okno dialogowe New Project. N astępnie jako typ projektu wybieramy CLR, a j ako szablon - CLR Console Application, j ak pokazano na rysunku 1.16. W polu Name wpisz nazwę Cwl _03. Po klikn ię c iu przycisku OK zostaną utworzone pliki projektu. Dla projektu konsolowego CLR nie ma żadnych opcji , a więc przy użyciu tego szablonu zawsze rozpoczynamy pracę z tym samym zestawem plików. Jeśli chcemy stwo rzy ć pusty projekt (w tej książce nie będziem y tego robić ) , to musimy skorzysta ć z innego specjalnie do tego przygotowanego szablonu. Na rysunku 1.17 w panelu Solu/żon Explorer mamy kilka plików gdy tworzyliśmy projekt konsolowy Win32.
więcej, niż widzieliśmy,
W wirtu alnym folderze Resouree Files zn ajdują się dwa pliki . Plik o rozszerzeniu . ico prze chowuje ikonę apl ikacji, która będzie widoczna po zminim alizowaniu okna programu. Plik o rozszerzeniu .re zapisuje zasoby aplikacj i - w tym przypadku zawiera tylko ikonę. W projekcie znajduje się także plik o nazwie Assemblylnfo.cpp . Każdy progr am CLR składa się z jednej lub większej liczby asemblacji, które stanowią zbiór kodu i zasobów tworzących funkcjonalną jednostkę. Asemblacj a zawiera równ ież dużą ilo ś ć danych dla CLR - specy fikacje używanych typów danych , informacje o wersj i kodu oraz czy do tej asembl acji mogą mie ć dostęp inne asemblacje. Mówiąc krótko, asembl acja jest podst awowym tworzywem do budowy wszystkich programów CLR .
52
Visual C++ 2005. Od podstaw -
-
-
-
-
m~ mI§]
New Project Templates :
Projecl types : - v.sual C++ ATL QR
I
--"isu a! studio installed t empl ates
~, ASP. NE T Web Servk:e
~' ''.j ;; l i mfłi1 m!tiM
General
H ,SQL Server ProjecI
MFC Smart Devlce W n32 .!J Other Languages ." Other Project Types
.ill WJndows Form s Controi Laary
r n Class Librar y 3lCLR Emply Projec l ',J1 Wndows Forms Apphcallon ifll W indows Serv ice
J eżel i kod źród łowy pliku Cwl_03.cpp nie jest widoczny, to kliknij go dwukrot nie w panelu Solulian Explorer. Jego zawartość powin na wy glądać ja k na rysunku I . 18.
Plik ten zawiera tę samą dyre ktywę #i ncl ude co d omy śln y program w natywnym C++, po niew a ż programy CLR u żywają n agłówk ów prekompilowan ych w celu podnie sien ia wy d ajn oś ci . P oni żs zy wiersz jest nowy :
using namespace Syst em:
Rozdzial1. • Programowanie przy użyciu Visual C++ 2005 ... x
/ CWC03.cppt. Start I'ag
cli
(Global Seope)
113 /"- Cwl _0 3 . c p p
~ ' l # lnC IUde ~:
ue i n q
'"
" ssc
:
deź x
g ł o llJny v
="' 1
p La k p r o j ekt.n .
~I
h"
I
n eme ap e ce Sys t em ;
I
-7'8 r n t;
mę i.n
3' 1{
Canso le : :U r::: i t.eL ine ( L"tJ ita j
9' 1); 11 )
1:: 1
53
t e r r evcave c em . : Sc r i ng A> Aa r::: g S ) ś e t ec t e v j r
re turn O;
'-'- - -
..
.... .
2"; ) JI
Rysunek 1.18 Wszystkie narzędzia biblioteki .NET są zdefiniowane w obrębie jakiej ś przestrzeni nazw. Wszystkie standardowe biblioteki, których najprawdopodobniej będziemy używać , należą do przestrzeni nazw System. Ale czym właściwie je st przestrzeń nazw ? Przestrzeń
nazw jest bardzo prostym pojęciem. W kodzie programu oraz w kodzie tworzącym biblioteki .NET znajduje się bardzo dużo rzeczy , które muszą mieć swoje nazwy (typy danych, zmienne, bloki kodu zwane funkcjami). Z tym związany jest jeden problem - łatwo jest czemuś nadać nazwę, która została już użyta w innym miejscu, co prowadzi do nieporozumień . Przestrzenie nazw pomagają uniknąć tego problemu . Wszystkie nazwy w kodzie biblioteki zdefiniowanej w przestrzeni nazw System poprzedzone są przedrostkiem stanowiącym nazwę tej przestrzeni. Tak więc nazwa Str i ng w bibliotece to w rzeczywisto ści System: :String. Oznacza to, że jeżeli przez nieuwagę u żyjemy w nasz ym kodzie nazwy St ri ng, to w celu odwołania się do tej nazwy w bibliotece .NET możem y u ży ć zapisu System: :St ri ng. Dwa dwukropki ( : :) stanowią operator, który nazywany jest operatorem zasięgu. W naszym przypadku operator ten oddziela nazwę przestrzeni nazw Syst emod nazwy typu Stri ng. W przykładach dotyczących natywnego C++ używali śmy go we fragmentach std: :cout oraz std : :endl. W tym przypadku sytuacja wygląda podobnie - std jest nazwą przestrzeni nazw bibliotek natywnego C++, a cout i end l stanowią nazwy zdefiniowane w obrębie tej przestrzeni i reprezentują odpowiednio standardowy strumień wyj ściowy oraz znak nowego wiersza. Zastosowane w przykładzie wyra żenie us i ng namespace pozwala nam używać dowolnych nazw z prze strzeni nazw System, bez konie czności podawania jej nazwy jako przedrostka. Jeżeli spowodowal i śmy konflikt nazw, to problem ten możemy rozwiązać, usuwając wyraże nia usin g namespace i jawnie przyporządkowującnazwę z biblioteki do nazwy przestrzeni nazw. Wię cej na temat przestrzeni nazw dowiesz s i ę w rozdziale 2. Program możemy skompilować i widoczny jest na rysunku 1.19.
uru chomi ć , naci skając
klawisze Ctrl+F5. Rezultat tego
54
Visual C++ 2005. Od podstaw
Rysunek 1.19
Wynik d ział an i a tego kodu jest taki sam jak kodu z pierwszego tekstu odpowiada wiersz : Consol e: :Wr iteLi ne(L"Wit aj
przykładu .
Za
wyświet lenie
ś wi ecie " ) ;
W tym przyp adku w celu wydru kowania w wierszu po lec e ń za warto ś c i c u dzysłowów p o słu żyl iśmy s i ę funk cj ą na leżącą do biblioteki .NET, a więc jes t to odpowie dnik CLR wyraże nia w natyw nym C++ , którego u ży l iś my w przykła dzie Cwl_O l : st d: :cout « Wy raże n i e
"Witaj
ś w t ec ie
vn" :
CLR j est bardziej przejrzyste
niż wyraż eni e
w natywn ym C++.
Ustawianie opcji wVisual C++ 2005 I stn iej ą dwa rodzaj e opcj i, które m o ż e my ustawi ać. Może my ustawi ć opcje narzęd z i Visua l C++ 2005, które mają zastosowanie w każdy m projekcie, lub opcje dotyczące konkretnego proj ektu, o kreś lające sposó b przetwarzania kod u tego proj ektu podczas procesów komp ilacj i i konsolidacji . Opcje ustawia s ię w oknie dialogowy m Options (Tools/Op tions) . Okno to wi doczne j est na rysunku 1.20. Opti~~5
D Always show Err"," List if build f1nishes wl th errors
D Track Active !tem in so lutlon Explorer 0Show advanCedbuild configuratlons
o Always show solut ion 0 s ave new projects w hen created 0warn user when the project Iocation is no t trusted 0 Show OUtput w rnow when bulld star ts DPrompt for symbohc renaming when renamng files
t OK
Rysunek 1.20
II
cancel
Rozdział 1.
Klikając
jeden ze znaków +
• Programowanie przy użyciu Visual C++ 2005
55
znajdujących się
obok elementów w lewym panelu, spowodujemy podtematów. Na rysunku 1.20 widać opcje podtematu General elementu Projects and Solutions . W prawym panelu widoczne są opcje dostępne dla wybra nego podtematu. W tej chwili interesują nas tylko niektóre z nich , ale dobrze jest poświęcić później trochę czasu na zapoznanie się z pozostałymi . Aby wyświetlić pomoc dotyczącą bie żących opcji , należy kliknąć znak zapytania znajdujący się w prawym górnym rogu okna.
wyświetlenie listy dostępnych
Tworząc
nowy projekt, prawdopodobnie chcemy wybrać domyślny katalog, w którym mają przechowywane wszystkie pliki. Możemy tego dokonać za pomocą pierwszej opcji widocznej na rysunku 1.20. Wystarczy wybrać lokalizację, w której chcemy przechowywać wszystkie pliki naszych rozwiązań i projektów . być
Aby ustawić opcje odnoszące się do każdego projektu C++, należy kolejno wybrać Projects and Solutions/VC++ Project Settings w lewym panelu. Można także dostosować ustawienia tylko dla bieżącego projektu, wybierając pozycję Prop erties z głównego menu Project. Ten element menu zawsze zawiera na
początku nazwę bieżącego
projektu .
Tworzenie iuruchamianie programów dla Windowsa Abyśmy
mogli przekonać się, jak proste jest to zadanie, utworzymy teraz dwie działające aplikacje Windows . Najpierw stworzymy program w natywnym C++, wykorzystującym bibliotekę MFC, a następnie aplikację Windows Forms działającą pod kontrolą CLR. Kod tych programów przedyskutujemy trochę później , gdy będziemy już posiadali niezbędną do ich zrozumienia wiedzę. Jednak już teraz przekonasz się, że procesy ich tworzenia są na prawdę proste.
Tworzenie aplikacji MFC Na początek, jeżeli mamy otwarty jakiś projekt (je śli jest otwarty, to na pasku tytułu głównego okna widnieje jego nazwa), to możemy go zamknąć, wybierając z menu File CIose Solution . Można także utworzyć od razu nowy projekt, a wtedy automatycznie zostanie zamknięte bie żące rozwiązanie.
dla Windowsa, należy wybrać New/Project z menu File lub wcisnąć klawiszy Ctrl+Shijt+N, a następnie wybrać typ projektu MFC oraz szablon projektu MFC Application. Projekt nazwiemy Cwl_04, jak pokazano na rysunku 1.21. Aby
utworzyć program
kombinację
Po kliknięciu przycisku OK pojawi się okno dialogowe tworzenia programu Application Wizard. W oknie tym mamy możliwość wyboru spośród wielu właściwości, które chcemy umieścić w naszej aplikacji . Występują one jako elementy listy po prawej stronie okna, jak widać na rysunku 1.22 . Wielu z nich będziemy używać jeszcze wielokrotnie . Wszystkie te opcje możemy w tej chwili zignorować i zatwierdzić domyślne ustawienia. W tym celu klikamy przycisk Finish, aby utworzyć nowy projekt z domyślnymi ustawieniami. Panel Solutton Explorer w oknie IDE wygląda teraz tak , jak pokazano na rysunku 1.23 .
56
Visual C++ 2005. Od podstaw
Iemplates : Visu al St udio installed templa t es
f~ MFC Appl ication
Mi MFC ActiveX Contra I m\ MFC DLL
ił1
~!.-,:.,!,p lat es
S mart Oevlee Win32 Other Lar<juages
Other Pro ject Types
• ' Search Online Ternplates...
A prcject fOr' creabng an applicatoo that uses the Mk:rosoft Fwndation Class Library t:1ame : ~ocatlon :
SolutlOnNaille:
D:\T ranslabons\{lelion\Ivor Hortons Visual C++ 2005'f'rzyklady
I
Cw l _D4
0 Create 'g irectory fOr solution
OK
'l[
Cancel
Rysunek 1.21 Rysunek 1.22 W elco me t o the MFC Applic at ion Wiz ard
'l hese ere
Overvicw Application Type
Compound Oocument Support Dccument Template Str1nQS
Detebese Suppott User Interface
Peetu-es
AdvencedFeetures Genereted
the ct.r'rent prc ject seUings:
• MtJItiple document nerface • No detebese support
• Nocompound document support Cllck Finishfrorn any windowto eccect the rurrent
settoęs .
After you « ee te the crotect, see the prolect's reedrre .txt f~ e for information
ebout the project teetwes end files that ere qenereted .
dasses
Next
Za uważ, że sc howałem zakła d kę
>
II
Firlsh
II
(oneel
Property Manager, kli kając j ą pra wym przyciskiem myszy i wybie rając Hide z menu , które s ię pojawi ł o. Lista utworzonych plik ów jest dosyć dłu ga . Do pisania programów dla Windowsa trzeba mieć bardzo dużo miejsca na dysku twar dym ! Pliki z rozszerzeniem .cpp zawi erają wykonywalny kod w ję zyku C++ , a z rozszerze niem .h kod w C++ składający s ię z defin icji wykorzystywanyc h w kodzie wyko nywa lnym.
Pliki O rozszerzeniu .ico zawierają ikony. Wszystkie pliki zostały pogrupowane i umiesz czone w odpowiednich podkatalogach dla ułatwienia dostępu do nich . Nie są to jednak prawdziwe katalogi i nie zobaczymy ich w folderze projektu na dysku . Jeśli
zajrzymy do foldera rozwiązania Cwl_04 za pomocą eksploratora Windows lub jakie gokolwiek innego programu służącego do przeglądania plików na dysku , to zauważymy , że w sumie zostały wygenerowane 24 pliki. Trzy z nich znajdują się w folderze rozwiązania , 17 w folderze projektu, a pozostałe cztery w podkatalogu folderu projektu o nazwie res. Pliki w tym folderze zawierają zasoby wykorzystywane przez program - takie jak menu oraz iko ny. Wszystkie te pliki zostają utworzone po wpisaniu żąd anej nazwy projektu . Teraz już łatwo zrozumieć , dlaczego tak dobrym pomysłem j est stworzenie oddzielnego folderu dla każdego projektu. Wśród
plików w folderze projektu znajduje się plik o nazwie ReadMe.txt. W nim znajduje s ię przeznaczenia każdego pliku wygenerowanego przez kreator aplikacji MFC . Można go odczytać za pomocą programów Notepad, WordPad lub nawet edytora Visual C++ 2005. Aby obejrzeć go w oknie edytora, należy kliknąć go dwukrotnie w panelu Solutżon Explorer.
wyjaśnienie
Kompilacia iuruchamianie aplikacii MFC Przed uruchomieniem programu należy skompilować kod źródłowy , a następnie moduły pro gramu poddać procesowi konsolidacji. Robi s i ę to w identyczny sposób jak w przypadku programu konsolowego. W celu zaoszczędzen ia na czas ie można użyć kombinacji klawiszy Ctrl+F5, co spowoduje kompila cję oraz uruchomienie pro gramu .
58
Visual C++ 2005. Od podstaw Po kompilacji projektu w oknie Output widzimy, że nie wystąpiły żadne błędy, a program rozpoczyna działanie. Okno wygenerowanego przez nas programu widać na rysunku 1.24.
Rysunek 1.24
na rysunku , wygenerowane zostało w pełni funkcjonalne okno , z menu i paskiem Mimo że sam program nic określonego nie robi (dodanie funkcjonalności należy do programisty), to wszystkie menu działają. Możemy je wypróbować , a nawet utworzyć nowe okna, wybierając opcję New z menu File .
Jak
w idać
narzędzi .
Myślę, iż każdy się ze mną zgodzi , że utworzenie programu dla Windowsa za pomocą kreatora aplikacji MFC nie wymagało zaangażowania zbyt wielu szarych komórek. Więcej wysiłku będzie trzeba włożyć w zrobienie czegoś pożytecznego z wygenerowanym przed chwilą programem, ale też nie będzie to zadanie zbyt trudne. Niektórzy ludzie piszący powa żne-programy dla Windowsa za pomocą staroświeckich metod , bez użyc ia Visual C++ 2005 , przed rozpoczęciem prób musieli przynajmniej na kilka miesięcy przestawiać się na dietę rybną. Dlatego tak wielu programistów miało zwyczaj jadać sushi . Dzięki Visual C++ 2005 nie ma już takiej potrzeby. Chociaż tak naprawdę nigdy nie wiadomo, co czai się za rogiem w świecie technologii programowania. Jeżeli lubisz sushi, to lepiej nie przestawaj go je ść, tak na wszelki wypadek.
Tworzenie aplikacji Windows Forms W tym przypadku skorzystamy z innego kreatora. Tworzymy jeszcze jeden projekt, ale tym razem wybieramy opcję CLR w lewym panelu okna dialogowego New Project oraz szablon Windows Forms Application. Następnie wpisujemy nazwę projektu Cwl _05, jak widać na rysunku 1.25.
w tym przypadku nie mamy żadnych opcji do wyboru, a więc naciskamy OK w celu utworze nia nowego projektu.
Rozdział 1. -
-
--~
--
-
-
-
-
-
-
• Programowanie przy użyciu Visual C++ 2005
---
-
-
--------
New Project Pro ject types :
-
_ visual .~tudio Installed templates W' ASP.NET Web Service ,~C LR Console Applicatlon ij1SQL Server Project .i'iJ Windows Form s Controi Librar y
General MFC
smart Device Win32 iii Olher Languages
iłI Othar Projec t Types
A proJect for creathj
GlClass LIbrar y ::!J QR Empty Projsct .]:lWhc!ows Forms Application .!mWhc! ows Service
~y Temp la t es
. .: Search Online Templa tes...
an applicalion w llh a Wndows user interface
I v! I
: CWl _osl
Name :
Location: SO....tlon :
-ffi~
CJ9j
Telll'lates :
Ci Visual c++ ATL CLR
59
. iD:\ TranslatKJns\helion\Jva
Hor tons vi sus l c+ + 2005\Pr zy k ł ady
~
!creata new Soubon Solu tion Na me:
-
~
__ _:J -, -
Brows e...
I
Cancel
I
0 create drectorv filr solulion
-
---
I
OK
II
Rysunek 1.25 W panelu Solution Explorer, widocznym na rysunku 1.26, pokazano pliki, które zostały wyge nerowan e dla tego projektu.
app.rc Source F iles ej Asserrbly ln fil .cpp c.::'} c w l _OS.cpp cj stdafx.cpp ReadMe.txt
""ilsolutio...
w tym
projekcie mamy znacznie mniej plików - w sumie jest ich tylko 15 (włącznie z plika Jest to spowodowane między innymi tym, że początkowe GUl jest prostsze n iż w aplikacj i w natywnym C++ używającym biblioteki MFC . Aplikacja Windows Fonns nie
mi
rozwiązania) .
60
Visual C++ 2005. Od podslaw ma żadnych menu ani pasków narzędzi i składa s ię tylko z jednego okna . Oczywiście , łatwo te elementy dodać , ale kreator aplikacji Windows Forms nie zakłada z góry, że potrzebujemy ich od samego po czątku. Okno edytora wygląda trochę inaczej, jak
widać
na rysunku 1.27.
Rysunek 1.27 W okn ie edytora zam iast kodu widzimy okno aplikacj i. Jest to spowodowane tym, że pro jektowanie GUl dla Windows Forms zorientowane jest na tryb graficzny , a nie kodowy. Ele menty interfejsu umies zczamy w oknie, przeciągając je lub umi eszczając w odpowiednich miejscach w trybie graficznym, a Visual C++ 2005 automatycznie wstawia potrzebny kod. Naciśn ięcie klawiszy Ctrl+Alt+X lub wybranie z menu Viewopcji Toolbbx spowoduje poja wienie się dodatkowego okna zawierającego listę składników GUl , jak widać na rysunku 1.28. Okno Toolbox przedstawia listę standardowych komponentów, które można dodawać do apli kacji Windows Forms . Możemy na próbę dodać kilka przycisków do okna projektu Cwl_05. W tym celu klikamy Bulion na liście w oknie Toolbox, a następnie klikamy w obszarze klienc kim okna apl ikacji Cwl_05 wyświetlonego w oknie edytora w miejscu, w którym chcemy umieścić nasz przycisk . Można dowolnie dopasować rozmiar przycisku , przeciągając jego krawędzie, oraz przem ieszczać go w dowolne miejsce za pomocą przeciągania . Aby zm ieni ć jego etykietę, wystarczy ją wpisać - spróbuj napisać Sta rt , a następnie naciśnij Enter. Napis na przycisku zmienia się i jednocześnie pojawia się inne okno, pokazujące właściwości tego przycisku. Nie będziemy się teraz nimi zajmować . Wyjaśnię tylko, że są to opcje pozwalające na kontrolę wyglądu przycisku i że za ich pomocą możemy go dostosować do własnych po trzeb. Spróbujm y doda ć jeszcze jeden przycisk z napisem St op. Okno edytora będzie wyglą dało podobnie do tego na rysunku 1.29. W trybie grafi cznym można w dowolnym czasie dodać dowolny komponent GUl, a kod zostanie automatycznie dopasowany. Spróbuj dodać kilka innych komponentów w podobn y sposób jak pierwsze dwa, a następnie skompiluj i uruchom program, wciskając klawisze Ctrl+F5. Po wykonaniu tych czynności aplika cja prezentuje się w pełnej krasie. Mogłoby być jeszcze prościej?
Rozdzial1. • Programowanie pru u2rciu Visual C++ 2005 Rysunek 1.28
Toolbox
61
• -l=l X
',' AlI WIndows fonn.
; ! Common Cootrols II; Pointer
o Button o CheckBox l "O Checked-istBox ~ ComboBox
Podsumowanie W tym rozdziale poznaliśmy podstawy tworzenia różnego typu aplikacji za pomocą Visual CH 2005. Utworzyliśmy i uruchomiliśmy natywne programy konsolowe CLR, a za pomocą kreatorów aplikacji utworzyliśmy oparte na bibliotece MFC programy Windows oraz urucha miany pod kontrolą CLR - Windows Forms.
62
VisIlai C++ 2005. Od podstaw Z tego
rozdziału powinniśmy zapamiętać, że:
•
Common Language Runtime (CLR) to implementacja firmy Microsoft standardu CLI (ang. Common Language Infrastructurei .
•
Platforma .NET składa działające pod CLR.
•
Natywne aplikacje CH pisane
•
Programy napisane w CH/CLI uruchamia
•
Rozwiązanie jest zbiorem rozwiązanie
się
z CLR oraz bibliotek .NET, które są
wspomagają aplikacje
w języku C++ ISO/ANSI. się
za
pomocą
CLR.
jednego lub większej liczby projektów, które razem pewnego problemu związanego z przetwarzaniem danych. składają się
na
tworzą
funkcjonalnąjednostkę
•
Projekt zawiera kod i elementy, które w programie.
•
Asemblacjajest podstawowąjednostką w programach CLR . Wszystkie tego typu programy składają się z co najmniej jednej asemblacji.
Zaczynając
od drugiego rozdziału aż do połowy książki, będziemy tworzyć programy konsolowe. Wszystkie przykłady ilustrujące sposoby użycia elementów języka C++ są uruchamiane przy użyciu aplikacji konsolowych Win32 lub CLR. Do aplikacji opartych na MFC, tworzonych za pomocą kreatora, powrócimy, gdy opanujemy w wystarczającym storiU sekrety języka C++.
2 Dane, zmienne
i działania arytmetyczne
W tym rozdziale nauczysz się podstaw programowania w języku C++. Po jego lekturze na uczysz się pisać proste programy w C++ w tradycyjnej formie: wejście-przetwarzanie-wyjście. Jak już informowałem w poprzednim rozdziale, najpierw opiszę właściwości języka C++ ISO/ANSI, a następnie przejdę do omówienia dodatkowych cech lub różnic w języku C++/CLI. przy użyciu działających przykładów będziemy mieli okazję zdobyć w poruszaniu się po środowisku Visual C++. Dla każdego przykładu w książce, przed przejściem do kompilacji i uruchomienia, należy utworzyć oddzielny projekt. Pamiętaj, że projekty definiowane w tym rozdziale i we wszystkich następnych aż do dziesią tego są aplikacjami konsolowymi .
W trakcie nauki
języka
więcej doświadczenia
W rozdziale tym dowiesz
się :
• Jakajest struktura programu w C++. • Czym są przestrzenie nazw . • Czym są zmienne w C++ . • Jak
definiować
zmienne i stałe w C++.
• O podstawowych operacjach wprowadzania danych z klawiatury oraz danych na ekran. • Jak
wykonywać
obliczenia arytmetyczne.
• Co to jest rzutowanie typów. • Co to jest zasięg zmiennej .
wysyłania
64
Visual C++ 2005. Od podslaw
Struktura programu wC++
Programy działające jako aplikacje konsolowe w Yisual C++ 2005 pobierają dane z wiersza poleceń i do niego też wysyłają wyniki. Aby uniknąć niepotrzebnego grzebania w skompli kowanych mechani zmach tworzenia i zarządzania aplikacją Windows, bez posiadania wiedzy pozwalającej je zrozumieć, wszystkie przykłady mające ułatwić zrozumienie języka C++ będą aplikacjami konsolowymi Win32 lub .NET. Dzięki temu będziem y mogli całkowicie skupić się na języku C++. Po j ego opanowaniu będziemy w stanie poradzić sobie z aplika cjami Windows . Najpierw zobaczymy, jaka jest struktura programu konsolowego. Każdy
program napisany w języku C++ składa się z co najmniej jednej funkcji. W rozdziale l . widzieli śmy przykład programu konsolowego Win3 2, który zawierał tylko jedną funkcję ma t ru ), gdzie main to nazwa tej funkcji . Każdy program w języku C++ ISO/ANSI zawiera funkcję main() i wszystkie programy w C++, bez względu na rozmiar, składają się z kilku funkcji main() , oznaczającej początek programu, oraz pewnej liczby innych funkcji. Funk cja to po prostu blok kodu o unikalnej nazwie, który jest wywoływany w celu wykonania za pomocą jej nazwy. Jak widzieliśmy w rozdziale 1., aplikacja konsolowa Win32 wygenero wana przez kreator aplikacji ma podstawową funkcję o nazwie _tmai n. Nazwa ta może ozna czać zarówno main,jak i wmai n, w zależności od tego , czy program używa znaków Unicode, czy nie. Nazwy wmain i _tmain zostały stworzone przez firmę Microsoft. Nazwa tej funkcji w standardzie CH ISO/ANSI to mai n. Będę jej używał we wszystkich przykładach w języku CH ISO /ANSI. Typowy program komunikujący się za pomocą wiersza taką, jaka została zaprezentowana na rysunku 2.1.
poleceń może posiadać strukturę
Wykonywanie programu przedstawionego na rysunku 2.1 zaczyna się w miejscu rozpoczęcia funkcji main() . Następnie kontrolę przejmuje funkcja input_names (), która zwraca wynik w miejscu znajdującym się bezpośrednio za tym, w którym została wywołana w nat ru ). Następnie w funkcji main() wywoływana jest funkcja sort_names(), a po powrocie kontroli do main() wywoływana jest ostatnia funkcja output_names () . Po zakończeniu wysyłania wy ników na wyjście kontrola wraca z powrotem do funkcji mai n() i program kończy działanie . Oczywiście , różne
programy mogą mieć całkiem inną strukturę, ale ich wykonywanie zawsze rozpoczyna się od funkcji main(). Główną zaletą podziału programu na funkcje jest fakt, że poszczególne jego części można pisać i testować oddzielnie. Drugą zaletą jest możliwość wykorzystania raz napisanych funkcji w innych programach. W bibliotekach C++ znajduje się wiele standardowych funkcji, których można używać we własnych programach. Dzięki nim można zaoszczędzić bardzo dużo pracy. Więcej
na temat tworzenia i
~
używaniafunkcji
dowiesz
się w
rozdziale 5.
Prosly prOgram
Prosty przykład nowy projekt -
pomoże
nam lepiej zrozumieć poszczególne elementy programu. Utwórzmy to szybko zrobić za pomocą kombinacji klawiszy Ctrl+Shift+N.
możemy
Rozdział2.
• Dane, zmienne i działania arytmetyczne
65
Po wywołaniu funkcja zaczyna wykonywanie kodu od pierwszego wiersza void lnpurnamest) [
Wykonywanie programu rozpoczy na się od funkcji mainO
II ... return ;
int mainO )
(
inputjrarnesl):
sort _namesO; void sort jrarnest) output_names();
[ +-
'--
II ...
return O; return ; )
l
Wynik działania funkcji mainO zostaje zwrócony do systemu operacyjnego Wynik działania funkcji zostaje zwrócony za miejscem, w którym została wywołana
void outpurnarnest) [
II ... return ;
l
Rysunek 2.1 Kiedy pojawi się okno dialogowe New Project, widoczne na rysunku 2.2, wybierz typ pro jektu Win32 i szablon (ang. templatey Win32 Console Application . Projekt nazwij Cw2_01. Po kliknięciu przycisku OK ukaże się nowe okno dialogowe, podobne do tego, które widać na rysunku 2.3. Przedstawione w nim są podstawowe informacje na temat tego , co zostanie wygenerowane przez kreator. Kliknięcie Application Settings po lewej stronie okna spowoduje wyświetlenie dodatkowych opcji dla aplikacji Win32 , jak widać na rysunku 2.4. Domyślnie utworzona zostanie aplikacja konsolowa zawierająca plik z funkcją main () , ale my zaczniemy pracę od najbardziej podstawowej struktury projektu. W tym celu zaznaczamy opcję Empty project i klikamy przycisk Finish. Utworzony został nowy projekt, ale nie zawiera on żadnych plików. Jego zawartość można sprawdzić w panelu Solution Explorer, jak widać na rysunku 2.5.
66
Visual C++ 2005. Od podstaw --
-
-
-
-
--
-
(1]1&1
New Project
lm @]
Ta rrolates :
Project types:
r
8 vis ual C++
ATl
Visua! _~tudio
installed templates
~ Win32 Console Applicatlon
, CLR General
31 Wln32 Project
My Templates
MFC Smart Oevice
1 .'
Wln32
Search Onllne TemplalEs..,
I
Othsr Languages
- Oltl er Project ryp ss
I I I
II ..J!
A project for creating a Win32 console application
Name:
"
Location:
-- - - §T rans la t lor~ 'I1e lion \I ,a- HorlOns
SOlution Name:
I c w2_01 _ _
---- - - -
I
,
[ Cw2_01
Visual CH
2005l/'r~ła dy
dl
Browse..,
I
Cancel
I
I o CrealE directDry for solutbn
- - ---- --
l
OK
II
Rysunek 2.2 Rysunek 2.3 Welcome to th e Win32 Applicatlon Wlzard
o vervtew Application Settings
These ere the rurrent oroject s e trinęs : •
Consołe
applicalion
dek Flnish łrom any windOlł\l to ecceot the CLU"ren\':settinQs; , After yOU creete the project, see the prcjecrs readme.t xt filefor inforTl"latiOn aboutthe proe ct feetwes andfi1es thet M e eenereted .
" H.
Pracę
N_xl >
li
FI",sh
I[
Concel
rozpoczniemy od dodania nowego pliku źródłowego do projektu. W tym celu klikam y prawym przyciskiem myszy Source Fi/es w panelu Solution Explorer i wybieramy kolejno Add/New ltem. W tym momencie powinno pojawić się okno dialogowe Add New Item , podob ne do widocznego na rysunku 2.6.
Rozdział 2.
• Dane. zmienne i działania arytmetyczne
67
Rysunek 2.4 Appllcation Settings
Applic~tłon
Addcommon beeder files for:
Apphcation tvpe:
Overview
Settings
o \'1.ind_ appkcalioo o C<,;'1so1e applicatlon
,.
O l
o ~atic hbrary
Ad
o ~""ty
prc ject
~.oPO"t.~
f',.
aho.Jll"
I < Previous I
'j : ~~ ,
Finish
II
Cancel
Rvslmek 2.5 CI Solution 'Cw2_01 ' (l ,]ll [lEli[l
project)
Header Files
Resource Files Source Files
Klikając,
wybieramy szablon C++ File ( cpp) , a następnie wpisujemy nazwę pliku, tak jak to pokazane na rysunku 2.6. Rozszerzenie .cpp zostanie nadane plikowi automatycz nie i nie trzeba go podawać . Nie ma żadnych przeszkód, aby plikowi nadać tę samą nazwę, którą ma projekt. Plik projektu ma rozszerzenie . vcproj i to go będzie odróżniało od pliku
zostało
źródłowego .
Kliknij przycisk Add w celu utworzenia nowego pliku. w panelu edytora w oknie IDE: II Cw2_0/. cpp
~ Modu le-D efinilion File (.def) -!!.ll nstaller Class
.gM dl File (.idl) -!!.l Component Class
Utili tl Proper ty Sheets
My lemplates U Search Online Templates...
I
I I !
t Creates a file contain,'9 CH source code
§~r .J1a me >
Name: Locatlon:
----
Id ;\Tr anslationslj;elon\lvor Herm s Vlsuai CH -
-
I
-
200S\PrzykladY\Cw2_01\CW2_01
-
-
I
I I Browse...
I
II
I
Add
Cancel
Rysunek 2.6 i nt mai n() {
i nt apples. oranges: i nt f ruit: apples = 5: oranges = 6: fr ul t = appl es + oranges: cout cout cout
« « « «
endl : "Mamy me tylko pomar ań c ze .. . v, w sumie mamy " « f ruit « end l :
ret urn O:
II Deklaracja dwóch zmiennych typu ca łko wi t ego II ... i jeszcze jedna zmienna typu całkowitego. II Ustawi anie wartośc i początko wych. II Obli czanie sumy wszystkich owocó w. II Rozpoczęc ie « end l
wysyłania
od nowego wiersza.
owoców." : II
Wysłan ie
znaku nowego wiers za.
II Konie c progr amu .
Powyższy przykład
ma na celu pokazanie kilku sposobów pisania instrukcji w języku C+ +, ale nie stanowi wzoru dobrego stylu programowania. że
nasz plik ma rozszerzenie .cpp, to zostanie on zidentyfikowany jako plik z kodem C++, zaś znajdujące się w nim słowa kluczowe rozpoznane przez edytor będą prz edstawione w odpowiednich kolorach . Można to sprawdzić, wpisując I nt zamiast in t . Int nie zostanie nadany żaden kolor stosowany dla słów kluczowych.
Jako
źródłowym
W panelu Solution Explorer naszego projektu widzimy nowo utworzony plik. W panelu tym zawsze pokazywane są wszystkie pliki projektu . Kliknięcie zakładki Class View w dolnej czę ści panelu Solulion Explorer spowoduje pojawienie się panelu Class View. Jest on podzielony
Rozdział 2.
• Dane, zmienne i działania arytmetyczne
69
na dwie części - górną, która zawiera funkcje globalne i makra projektu (oraz klasy, kiedy dojdziemy do zagadnień związanych z ich tworzeniem), oraz dolną, w tej chwili jeszcze pustą. Funkcja ma i n() pojawi się w dolnym panelu, jeśli w górnym wybierzemy Global Functions and Variables. Widać to na rysunku 2.7. Więcej na ten temat powiem trochę później, a na razie zapamiętajmy, że globalne mogą być funkcje i (lub) zmienne, zaś ich właściwościąjest to, że dostęp do nich można uzyskać z dowolnego miejsca w programie.
Rysunek 2.7
Class Vlew
.
;-
~
-
... li- x
.
~
~ O ~
<Search>
""
.]1
Cw2 01
"MSm'.i@"Mj,\·Im'm Macrosand Constants
'-
' ,
,
"
• ..
_ .-
._
..
.~ mai1(void)
--
~ So lutJon E
1 ę] <;_,?_s ~ _ ."",-~~~\~~J~IRe source .,
Program można skompilować i poddać konsolidacji na trzy sposoby. Można wybrać z menu Build polecenie Build Cw2_01, nacisnąć klawisz F7lub wybrać odpowiedni przycisk z paska narzędzi (aby sprawdzić, do czego służy dany przycisk na pasku narzędzi, wystarczy najechać na niego kursorem i chwilę odczekać). Jeżeli operacja kompilacji' zakończyła się powodze niem, to program możemy uruchomić, wciskając klawisze Ctrl+F5 lub wybierając polecenie Start Without Debugging z menu Debug. W oknie wiersza poleceń powinniśmy zobaczyć następujący rezultat:
Mamy nie tylko pomarańcze
- w sumie mamy 11 owoców.
Aby kontynuować. naciśnij dowolny klawisz.
Pierwsze dwa wiersze zostały utworzone przez program, a ostatni informuje, w jaki sposób można zakończyć jego działanie i zamknąć wiersz poleceń.
Komentarze wprogramie Pierwsze dwa wiersze w kodzie to komentarze. Są one ważną częścią każdego programu, ale nie stanowią wykonywalnego kodu - służą tylko jako pomoc podczas jego analizowania. Wszystkie komentarze są ignorowane przez kompilator. Dwa ukośniki występujące jeden po drugim, nieznajdujące się wewnątrz łańcucha znaków (o łańcuchach będziemy jeszcze mó wić), oznaczają, że wszystko, co się za nimi znajduje aż do końca wiersza, jest komentarzem.
l
W języku polskim operacje kompilacji i konsolidacji często określa się jednym słowem "kompilacja" - przyp. tlum.
70
Visual C++ 2005. Od podstaw Niektóre wiersze w programie zawierają zarówno koment arze, jak i instrukcje. Można także używać innego typu komentarzy, których granice określane są przez znaki /* oraz */. Na przy kład pierwszy wiersz programu można było napisać następująco: /*
Cw2 Ol.cpp */
Komentarze rozpoczynające się od znaków / / obejmują tylko to, co znajduje się za nimi w tym samym wierszu . Natomiast komentarze w stylu / * . . . */ obejmują wszystko, co znajdzie się pomiędzy nimi, i mogą obejmować kilka wierszy. Moglibyśmy na przykład napisać : / *
Cw2_01.cpp
Prosty przykład owy program.
*/
Wszystkie cztery wiersze są komentarzem. to możemy ozdobi ć je ramką:
Jeśli
chcemy
wyróżnić
kilka wierszy komentarza,
/ *****************************
* Cw2_01. cpp *
* Prosty
przykład owy
prog ram. *
********** ************** ***** /
Zasada jest taka, że w naszym kodzie zawsze powinniśmy stosować zrozumiałe komentarze. Powinny one być na tyle jasne, żeby inny programista (lub my sami) mógł po jakimś czasie zrozumieć przeznaczenie i sposób działania danego fragmentu kodu .
Dyrektywa #include - pliki naglówkowe Po komentarzach znajduje się dyrektywa #i nel ude:
#i nclude Dyrektywy służą do wydawani a kompilatorowi poleceń - w tym przypadku nakazujemy mu, by przed kompilacją do programu dodał zawartość pliku < iostream > . Plik ten nazywany jest plikiem nagłówkowym, gdyż j est on zazwyczaj dołączany na samym początku programu. W rzeczywistości do bardziej pasuje nazwa nagłówek, ponieważ w standardzie ANSI C++ nagłówek nie musi zawierać się w pliku. Ja jednak będę posługiwał się terminem plik nagłówkowy, ponieważ w Visual C++ 2005 wszystkie nagłówki przechowywane są w plikach . Nagłówek zawiera definicje niezbędne, gdy chcemy używać instrukcji wejścia-wyjścia C++. Gdybyśmy nie umieścili zawartości nagłówka w programie, nie moglibyśmy go skompilować , ponieważ używamy w nim wyrażeń, które są zależne od definicji zawartych w tym pliku. W Visual C++ dostępnych jest wiele plików nagłówkowych , które znacznie rozszerzają nasze możliwości. Będziemy je stopniowo poznawać, w miarę zdo bywania coraz większych umiejętności posługiwania się językiem. Wyrażenie #i nel ude jest jedną z kilku dyrektyw preprocesora. Visual C++ rozpoznaje je i oznacza w oknie edytora kolorem niebieskim . Dyrektywy preprocesora są poleceniami wykonywanymi przez proces wstępnego przetwarzania kompilatora, który ma miejsce przed
Rozdział 2.
• Dane, zmienne i działania arytmetyczne
71
kompilacją
kodu do post aci obiektowej . Dyrektywy preprocesora zazwyczaj w jaki ś sposób na kod, zanim zostanie on skompilowany . Zaczynają się zawsze od znaku #' Kolejne dyrektywy preprocesora będziemy poznawać, gdy zajdzie potrzeba ich u życia. oddziałują
Przestrzenie nazw ideklaracia usino Jak dowiedzieliśmy się w rozdziale l., biblioteka standardowa to obszerny zbiór procedur napisanych w celu wykonywania wielu często spotykanych zadań, a przykładem mogą być obsługa strumienia wejścia-wyjścia czy wykonywanie podstawowych obliczeń arytmetycz nych . Ze względu na fakt, że liczba zarówno tych procedur, jak i innych elementów mających swoje nazwy jest bardzo duża, istnieje ryzyko, że przez przypadek użyjemy do własnych celów nazwy, która została już wcześniej użyta w bibliotece standardowej . Przestrzeń nazw to me chanizm, który pozwala na uniknięcie problemów związanych z duplikacją nazw. Dokonywane jest to poprzez skojarzenie pewnego zbioru nazw, takiego jak na przykład z biblioteki standar dowej , z czymś w rodzaju rodziny nazw, która jest nazwą przestrzeni nazw. Z każdą nazwą zdefiniowaną w kodzie, należącą do jakiejś przestrzeni nazw, skojarzona jest ta przestrzeń nazw. Wszystko, co znajduje się w bibliotece standardowej C++ ISO/ANSI, zde finiowane jest w przestrzeni nazw o nazwie std. A zatem każdy element z tej biblioteki, do którego możemy uzyskać dostęp w naszym programie, ma swoją nazwę, a jako kwalifikator pojawi a się nazwa przestrzeni nazw std. Nazwy eout oraz endl zdefiniowane są w bibliotece standardowej, a więc ich pełne nazwy to st d : :eout oraz st d: :endl - przykład ich działania widzieliśmy w rozdziale l. Dwa dwukropki oddzielające nazwę przestrzeni od nazwy encji stanowią tak zwany operator zasięgu. Ma on także inne zastosowania, które będą jeszcze omawiane. Używanie pełnych nazw w programie zaciemniłoby trochę kod. Dobrze by było, gdybyśmy mogli używać prostych nazw bez kwalifikatora w postaci nazwy przestrzeni nazw st d. Poniższe dwa wiersze naszego programu, które następują po dyrektywie #i nel ude dołączającej plik nagłówkowy , nam to umożliwiają:
using st d: :cout : usi ng std : :endl: Są
to deklaracje using, które informują kompilator, że nazw eout oraz endl z przestrzeni std w programie bez określania nazwy tej przestrzeni. Od tej pory kompilator będzie wiedział, że wszystkie przypadki wystąpienia nazwy eout po pierwszej deklaracji usi ng należą do przestrzeni nazw biblioteki standardowej . Nazwa eout reprezentuje standardowy strumień wyjścia, który domyślnie odpowiada wierszowi poleceń, a endl reprezentuje znak nowego wiersza. będziemy używali
Więcej części
o przestrzeniach nazw oraz o sposobie definiowania tego rozdziału .
własnych
powiemy sobie w dalszej
Funkcja mainO Funkcja mai n() w przykładzie składa się z nagłówka funkcj i definiującego jąjako mai n() oraz wszystkiego, co znajduje się pomiędzy nawiasami klamrowymi ({}). Nawiasy klamrowe zawierają wykonywalne instrukcje funkcji, które łącznie nazywa się jej ciałem.
72
Visual C++ 2005. Od podstaw Jak się przekonamy, wszystkie funkcje składają się z nagłówka ( m i ę dzy innymi) definiujące go nazwę funkcji, po którym następuje ciało funkcji składające się z pewnej liczby instrukcji programu zamkniętych pomiędzy nawiasami klamrowymi. Ciało funkcji może nie zaw ierać żad nyc h instrukcji , wtedy po prostu funkcja nic nie robi. Funkcj a, która nic nie robi, może wyd ać
się
zbyteczna, ale kiedy piszemy duży program, jego na funkcjach , pomijając kod wielu z nich i pozostawiając je z minimalną lub zerową zaw artością. Takie działanie oznacza, że możemy skompilować i uruchomić kompletny program ze wszy stkimi jego funkcjami w do wolnym czasie, a ich kod dodawać stopniowo. kompletną strukturę możemy początkowo odwzorować
Instrukcje programu Instrukcje składające się na ciało funkcj i ma i n() zakończone są znakiem średnika . To właśnie wyznacza koniec instrukcji, a nie koniec wiersza . W związku z tym instruk cję można rozbić na wiele wierszy, je śli dzięki temu kod będzie bardziej przejrzysty. Można także umie ścić kilka instrukcji w jednym wierszu . Instrukcja je st podstawową jednostką identyfikującą czynno ści wykonywane przez program. Mo żna ją porównać ze zdaniem w akapicie, gdzie każde zdanie opisuje j akąś odrębn ą koncepcję , ale zarazem stanowi fragment bardziej ogólnej całości, mając z nią liczne powiązania. Instrukcja jest samodzielnądefinicjąjakiejśczynności, którą ma wykon ać komputer, ale można ją łączyć z innymi instrukcjami w celu zdefiniowania bardziej złożonej czynnoś ci lub operacji liczenia. ś red n i k
Działanie
funkcji jest zawsze określone przez kilka instrukcji, z których każda zakończona Spójrzmy na podany przed chwilą przykładowy kod, aby ogólnie zorientować s i ę w sposobie działania instrukcji i funkcji . Bardziej szczegółowo opisuję wszystkie rodzaje instrukcji w dalszej części tego rozdziału .
jest
średnikiem.
Pierwsza instrukcja w ciele funkcji main () to:
int apples . oranges:
II Deklaracja dwóch zmiennych typu
całkowitego .
Instrukcja ta definiuje dwie zmienne - apples oraz oranges. Zmienna jest nazwanym frag mentem pamięc i komputera, którego możemy używać do przechowywania danych , a instruk cja nadaj ąca nazwę jednej lub większej liczbie zmiennych nazywana jest deklaracją zmien nej. Słowo kluczowe i nt oznacza, że zmienne apples i oranges mogą przechowywać liczby całkowite . Za każdym razem, gdy deklarujemy zmienną w programie, musimy określi ć, jakie go typu dane będzie ona przechowywać , czyli wskazać typ zmiennej. N astępna
instrukcja deklaruje jeszcze jedną zm ienną typu
int fruit:
11...ijeszczejedna zmienna typu
c ałko w i te g o
-
frui t :
ca łkowitego.
Mimo że za pomocą jednej instrukcj i można zadeklarować kilka zmiennych, jak zrobiliśmy w naszym przykładzie ze zmiennymi appl es i oranges, to jednak dobrze jest umieszczać wszystkie deklaracje w osobnych wierszach. Pozwala to na dodanie dla każdej z nicb od dzielnego komentarza, w którym możemy wyjaśnić ich przeznaczenie.
Rozdział2.•
Następny
appl es
wiersz kodu przedstawia =
5: oranges
=
6:
Dane. zmienne i działania arytmetyczne
73
się następująco :
II Ustawianie wartości początko wych .
Wiersz ten zawiera dwie instrukcje , każda z nich zakończona jest ś re d n i k i e m . Napisałem tutaj tak , a by pok azać, że kilka instrukcji może wystąpi ć w jednym wierszu . Mimo że n ie jest to obowiązkowe , to do zasad dobrego stylu programowania n ależy umieszczanie tylko jednej instrukcji w wierszu, ponieważ zwiększa to czytelno ś ć kodu. Dobrą praktyką programistyczną jest pisanie kodu w taki sposób, aby był on łatwy do odczytania i s twa rzał jak najmniej okazj i do popełnien i a błędu . Dwie instrukcje w poprzednim wierszu przechowują wartoś ci 5 i 6 w zmiennych app l es i ora nges . Instrukcje te nazywamy instrukcjami przypisania , poniew a ż przypisują one nowe wartości do zmiennych. Zn ak = jest operatorem przypisania. Następna instrukcja
f ruit = apples
+
to :
oranges:
II Obliczanie sumy wszys tkich owoców.
Ta instrukcja jest także instrukcją przypisania, ale trochę inną niż poprzednie, gdyż po prawej stronie operatora przypi sania zawiera dod atkowo wyrażenie arytmetyczne. W yrażenie to dodaje wartości przechowywane przez zm ienne appl es i or anges , zaś wynik zapisuje do zmiennej fru i t . Następne
trzy
wyrażeni a
to:
cout « end l : cout « "Mamy ni e t yl ko « " . w sumi e mamy cout « endl :
II Rozpoczę cie pom a r a ń cze.
« f ruit « "
«
wysyłania
w nowym wierszu.
endl
OWOCÓ~I . " :
II WysIanie znaku nowego wiersza.
Wszystkie one są instrukcjami wyjściowymi. Pierwsza instrukcja znajduje się tutaj w pierw szym wierszu i wys yła na ekran znak nowego wiersza za pomocą słowa kluczowego endl . W j ę zyk u C++ źró dło wprowadzanych dan ych lub cel wysyłanych danych nazywane są stru mieniem. Nazwa cout określa standardowy strumień wyjściowy, a operator « informuje, że wszystko, co znajduje si ę po jego prawej stronie, ma zostać wysłane do strumienia wyjścio wego - cout . Operator « pokazuje kierunek, w którym mają zostać skierowane dane - od zmiennej lub łańcucha po prawej stronie operatora do wyjścia po lewej. Tak więc w pierwszej instrukcji wartość reprezentowana przez na zwę endl . która oznacza znak nowego wiersza, wysł ana zostanie do strumienia zidentyfikowanego przez cout , zaś dane wysłane do cout są drukowane w wierszu poleceń. Znaczenie nazwy cout i operatora « zdefiniowane jest w pliku nagłówkowym biblioteki stan dardowej < iostream > , który dodaliśmy na sam ym poc zątku do programu za pomo cą dyrek tywy #i nc l ude. cout w bibliotece standardowej jest nazwą, a wię c należy do przestrzeni nazw std. Gdyby nie deklaracja usi ng, to nazwa ta nie zostałaby rozpoznana , chyba że użyl ibyśmy pełnej nazwy z kwalifikatorem - std : :cout, jak już w s p o m i n ałe m wcześn iej . Ze względu na fakt , że cout jest nazwą zarezerwowanądo reprezentowania standardowego strumienia wyj ściowego, nie powinno się jej używać do innych celów, a więc na przykł ad nie można jej stosować jako nazwy zmiennej w programie. Oczywiście używanie tej samej nazwy w odnie sieniu do różn ych rzeczy zwiększa prawdopodobieństwo powstania nieporozumień.
74
Visual C++ 2005. Od podstaw Druga instrukcja
wyjścia
podzielona została na dwa wiersze:
cout « "Mamy nie t yl ko p om a rańcze .. . « "- w sumie mamy " « fruit «
"
« endl
owoców. ":
już mówiłem wcześniej, każdą instrukcję można podzielić
na dowolną liczbę wierszy, czemu kod stanie się bardziej przejrzysty. Koniec instrukcji zawsze oznaczony jest średnikiem, a nie końcem wiersza. Następujące po sobie wiersze są odczytywane i łączone przez kompilator w jedną instrukcję do momentu napotkania średnika oznaczającego koniec instrukcji. Oznacza to, że jeżeli zapomnimy na końcu instrukcji postawić średnik, to kompila tor potraktuje następny wiersz jeszcze jako część tej instrukcji. W rezultacie zazwyczaj po wstaje coś , czego kompilator nie potrafi zrozumieć, więc zgłasza błąd .
Jak
dzięki
Instrukcja ta wysyła łańcuch znaków: ,,Mamy nie tylko pomarańcze ... " do wiersza poleceń , po którym następuje znak nowego wiersza (endl), łańcuch" - w sumie mamy", wartość zmien nej fruit oraz łańcuch "owoców". Nie ma żadnych przeciwwskazań co do łączenia w taki sposób różnych wysyłanych elementów . Instrukcja wykonywana jest od lewej do prawej, a każdy element wysyłany jest do strumienia eout. Należy zauważyć, że każdy element, który ma zostać wysłany do eout , poprzedzony jest operatorem « . Trzecia i zarazem ostatnia instrukcja wyjścia wysyła już tylko znak nowego wiersza. Rezultat wszystkich tych trzech instrukcji oglądamy na ekranie. Ostatnia instrukcja w programie to:
retur n
o:
// Koniec programu.
ona wykonywanie funkcji maint ), która zatrzymuje program. Kontrola powraca do systemu operacyjnego . Bardziej szczegółowo na temat tych instrukcji będziemy jeszcze mówili.
Kończy
Instrukcje w programie wykonywane są w takiej kolejności, w jakiej zostały wpisane , chyba że któraś z nich celowo ten stan zmienia. Instrukcje zmieniające normalną kolejność wykony wania opisane zostały w rozdziale 3.
Riale znaki Terminem białe znaki w C++ określa się wszystkie znaki tabulacji, nowego wiersza , przesu nięcia strony oraz komentarze. Białe znaki rozdzielają poszczególne części instrukcji oraz pozwalają kompilatorowi zorientować się, gdzie kończy się jej jeden element (np. i nt ), a gdzie zaczyna następny. W innych przypadkach białe znaki są ignorowane i nie wywołują żadnego efektu. Spójrzmy na i nt
fruit:
Pomiędzy
poniższą przykładową instrukcję : // ...i jeszcze j edna zmienna typu ca łko wi t ego .
i nt a fr uit musi być co najmniej jeden biały znak, aby kompilator mógł rozróż te dwa elementy. Można oczywiście dodać więcej białych znaków, ale zostaną one zigno rowane . Wszystko, co znajduje się za średnikiem, to białe znaki, a więc są one ignorowane. nić
Rozdział 2.•
Spójrzmy teraz na inny
fr uit
~
apples
+
Dane. zmienne i działania arytmelyczne
75
przykład:
oranges :
II Obliczani e sumy wszystkich owoców.
Pomiędzy
frui t i = oraz = i app l es nie muszą występować żadne białe znaki, choć można je chcemy. Bierze się to stąd, że znak = nie jest znakiem należącym do alfabetu ani cyfrą, a więc kompilator potrafi oddzielić go od otaczających znaków . Podobnie wygląda sytuacja ze znakiem + - nie ma konieczności wstawiania białych znaków w jego sąsiedztwie, ale można to zrobić w celu zwiększenia czytelności kodu.
zastosować,jeżeli
Jak już powiedziałem , białe znaki używane są do rozdzielania elementów instrukcji, w in nych przypadkach są one ignorowane przez kompilator (z wyjątkiem oczywiście łańcuchów znaków w cudzysłowach) . Dzięki temu, aby zwiększyć przejrzystość kodu w swoich progra mach, możemy wstawiać dowolną liczbę białych znaków, tak jak zrobiliśmy wcześniej, roz bijając instrukcję wysyłającą dane na kilka wierszy . Pamiętaj, że w C++ koniec instrukcji oznaczany jest średnikiem.
Bloki instrukcji Kilka instrukcji
można umieścić pomiędzy
nawiasami klamrowymi . To, co powstaje, nazywa blokiem jest ciało funkcji. Taką złożoną instrukcję można traktować jako pojedyncze wyrażenie (o czym przekonamy się przy omawianiu podejmowania decyzji w C++ w rozdziale 3.) W rzeczywistości wszędzie tam , gdzie można wstawić pojedynczą instrukcję, można również wstawić cały blok instrukcji otoczony nawiasami klamrowymi. W konsekwencji wewnątrz bloków mogą znaleźć się inne bloki, które można zagnieżdżać w dowolnej liczbie. się
blokiem instrukcji lub
instrukcją złożoną . Przykładowym
Bloki instrukcji wywierają także poważny wpływ na zmienne, ale więcej na ten temat powiem w dalszej części rozdziału przy okazj omawiania zasięgu zmiennych.
Programy konsolowe generowane automatycznie W poprzednim przykładzie utworzyliśmy pusty projekt bez żadnych plików źródłowych, które później dodaliśmy samodzielnie. Jeśli pozwolimy kreatorowi na wygenerowanie projektu tak jak w rozdziale l., to utworzy w nim kilka plików, których zawartości powinniśmy dokładnie się przyjrzeć. Utwórzmy nowy projekt konsolowy Win32 o nazwie Cw2_01A i tym razem pozwólmy kreatorowi działać, nie zmieniając żadnych ustawień. Projekt zawiera trzy pliki z kodem: pliki źródłowe Cw2_0IA.cpp i stdafx.cpp oraz plik nagłówkowy stdafx.h, Pliki te dostarczają podstawowych narzędzi, których możemy potrzebować w programie konsolowym, i składają się na działający program, który w obecnym stanie nic nie robi . Jeżeli mamy otwarty jakiś projekt, to możemy go zamknąć, wybierając z menu File polecenie C/os e Solution. Możemy także utworzyć nowy projekt, a wtedy bieżący zostanie automatycznie zamknięty, chyba że zechcemy go dodać do tego samego rozwiązania. Najpierw przyjrzymy
się zawartości pliku
Cw2_0IA:
76
Visual C++ 2005. Od podstaw #include "stdaf x.h" i nt _tmai n(i nt argc . _TCHAR* argv[] )
{
retu rn O;
Zawartoś ć
tego pliku znacznie
#i ncl ude dla pliku
różni się
nagłówkowego
od poprzedniego przykładu. Mamy tutaj dyrektywę stdafx.h, której wcześniej nie było. Program zaczyna się od
funkcji _t ma i nt ), a nie mai nt ). Kreator aplikacji wygenerował plik nagłówkowy stdafx.h jako część projektu. Po otworzen iu tego pliku zobaczymy, że zawiera on dwie dyrektywy #i ncl ude dla plików nagłówkowych biblioteki standardowej stdio.h oraz tehar.h. Plik stdio.h jest starym nagłówkiem obsługują cym stand ardowe operacje wejścia-wyjścia, które były używane przed pojawieniem się obec nego standardu C++ ISO/ANSI. Jego funkcjonalność pokrywa się z nagłówkiem . tehar.h jest nagłówkiem stworzonym przez firmę Microsoft i definiuje funkcje tekstowe. W zasadzie plik stdafx.h służy jako zbiór standardowych, dołączanych do projektu plików systemowych, które dodalibyśmy do projektu za pomocą dyrektywy #i ncl ude. Podczas nauki CH ISO/ANSI nie będziemy potrzebowali żadnego z nagłówków pojawiających si ę w pliku nagłówkowym stdafx.h, co jest jednym z powodów n ieużywania domyślnych ustaw ień gene rowania aplikacji przez kreator. Jak już wspominałem , Visual C++ 2005 wykorzystuje funkcję wmai n( ) w zamian za ma i n() wtedy, gdy tworzony program używa znaków Uni code. Funk cja wmain ( ) została stworzona przez firmę Microsoft i nie należy do standardu C++ ISO/ANSI. W związku z tym n agłówek tchar.h definiuje nazwę _tmain, dzięki czemu jest ona zastępowana przez main, ale jeżeli sym bol_UNICODE został zdefiniowany, to zostanie zamieniona na wma in. Aby więc poinformować , że program korzysta ze znaków UNICODE, należy dodać następującą instrukcję na początku pliku nagłówkowego stdafx.h :
#define UNI COOE Po tych wszystkich
wyjaśnieniach będziemy
main O we wszystkich
przykładach w
konsekwentnie trzymali C++ ISO/ANSI.
się
stosowania funkcji
Deliniowanie zmiennych Podstawowym celem ws zystkich programów komputerowych jest przetwarzanie danych i zwracanie wyników . Podstawowym elementem tego procesu j est posiadanie fragmentu pamięci, któremu możemy nadać wybraną nazwę, do którego możemy się odwoływać przy u życiu tej nazwy oraz w którym możemy przechowywać dane . Każdy fragment pamięci o takich wła ś ciwościach nazywa się zmienną. Jak już wiemy, każda zmienna przechowuje dane określonego typu , który ustalamy podczas jej definiowania w programie. Zmienna może zostać zdefiniowana do przechowywania tylko liczb całkow itych (to znaczy danych typu i nt eger) i nie można jej używ ać do liczb ułam
Rozdział 2.
• Dane, zmienne i działania arytmetyczne
77
kowych. Wartość przechowywana przez zmienną w danym momencie zależna jest od instruk cji w programie i zazwyczaj zmienia się wielokrotnie w czasie wykonywania przez program obliczeń. Poniżej opisuję
zasady nadawania nazw zmiennym wprowadzanym do programu.
Zasady nadawania nazw zmiennym Nazwa nadana zmiennej to jej identyfikator lub po prostu nazwa zmiennej . W nazwach zmiennych można używać wielkich i małych liter alfabetu, cyfr oraz znaku podkreślenia. Żadne inne znaki nie są dozwolone i w przypadku niezastosowania się do tych reguł podczas kompilacji zazwyczaj otrzymamy komunikat o błędzie. Nazwy zmiennych muszą dodatkowo zaczynać się od litery lub znaku podkreślenia. Najlepiej , aby nazwa odzwierciedlała rodzaj przechowywanych informacji. Ze względu na fakt , że w Visual C++ 2005 nazwy zmiennych mogą mieć długość do 2048 znaków, mamy dość duże pole manewru. Poza zmiennymi, w C++ nazwy można nadawać także innym elementom, które podlegają takim samym zasadom nazewniczym co zmienne. Używanie nazwo maksymalnej długości może znacznie utrudni ć odczytywanie kodu progra mu, a ponadto ich wpisywanie zabiera dużo czasu (chyba że wyjątkowo sprawnie posługuje my się klawiaturą) . Ważniejszym powodem do niestosowania tak długich nazw jest fakt, że nie wszystkie kompilatory potrafiąje obsłużyć. Jeśli przewidujemy, że nasz kod będzie kom pilowany także w innych środowiskach, to dobrze jest ograniczyć długość nazw do 31 znaków . Liczba ta, będąc wystarczającą do stworzenia znaczących nazw, jest także bezpieczna, jeśli chodzi o ograniczenia większości kompilatorów. nazwy zmiennych mogą rozpoczynać się od znaku podkreślenia , to lepiej tak nie w ten sposób unikamy ryzyka wystąpienia potencjalnych konfliktów ze standar dowymi zmiennymi systemowymi, które mają taką właśnie formę . Z tego samego powodu powinniśmy także unikać nazw zmiennych rozpoczynających się od dwóch znaków pod Mimo
że
robić , gdyż
kreślenia . Poniżej
zamieszczam
•
cena ,
•
rabat,
•
pKszta1t,
•
wartosc_,
•
LICZNIK.
przykłady dobrych
nazw zmiennych:
Nazwy takie jak 8_Ba11 , 7Up czy 6_pack są niedozwolone. Podobnie jak Cisza ! czy Anna-Maria , chociaż Ann a_Mar i a jest już w porządku. Oczywiście Anna Mari a jest nieprawidłowąnazwą, gdyż spacje w nazwach zmiennych są niedozwolone. Zauważ, że nazwy zmiennych repub l i can i Republ i can są różne , ponieważ wielk ie i małe litery są rozróżniane. Oczywiście w nazwach nie mogą się pojawiać białe znaki, a ich przypadkowe tam umieszczenie spowoduje powstanie dwóch lub więcej nazw zamiast jednej, co z kolei zazwyczaj prowadzi do zgłoszenia błędu przez kompilator.
78
Visual C++ 2005. Od podstaw Często stosowanąkonwencjąjest m ałej .
od
O klasach
piszę
rozpo czynanie nazw klas od wielkiej litery, a nazw zmiennych w rozdziale 8.
Slowa kluczowe wC++ W C++ istnieje pewna liczba zarezerwowanych słów, tzw . słów kluczowych, które mają spe cjalne znaczenie w języku. Edytor Visual C++ 2005 oznacza je specjalnym kolorem - u mnie domyślnym jest niebieski. Jeżeli słowo kluczowe nie zost ało wyróżnione kolorem, to zna czy, że wpisaliśmy je niepoprawnie. Należy pamięta ć , że
w przypadku słów kluczowych , tak jak i wszystkich innych elementów wielkie i małe lite ry. Na przykład program, który omawialiśmy wcześniej , zawierał słowa kluczowe int i ret urn. Gdybyśm y napisali Int lub Return, to nie byłyby to już słow a kluczowe i nie zostałyby one jako takie rozpoznane. W trakcie poznawa nia język a C++ poznamy jeszcze wiele słów klu czowych . Należy zawsze się upewnić , czy nazwy nadawane różnym elementom programu, takim jak np. zmienne, nie są identyczne ze słowami klu czowymi w C++. Pełna lista słów kluczowych używanych w Visual C++ 2005 znajduje s i ę w dodatku A.
języka
C+ +,
rozróżn i ane są
Deklarowanie zmiennych Jak już widzieli śmy , deklaracja zmiennej jest typu. Na przykład :
instrukcją określającą nazwę
zmiennej danego
int val ue: fragment kodu deklaruje zmienną o nazwie val ue, która może przechowywać liczby T yp dan ych , które może przechowywać zmienna va l ue, określony został przez słowo kluczowe i nt (który wła śnie oznacza liczby cał kow i te) . Ze względu na fakt, że i nt jest słowem klu czowym , nie mo żemy go użyć jako nazwy jednej ze swoich zmiennych. Powyższy
całkowite .
Zauważ, że
deklaracja zmiennej zawsze zakonczona j est ś redn ikiem.
jednej dekl aracji można nadać nazwy wielu zmiennym, ale jak już wcześniej jest je deklarować za pomocą pojedynczych instrukcji - każda w od dzielnym wierszu. Czasami będę od tej zasady odstępował, ale tylko w przypadkach, gdy kod zajmowałby zbyt wiele stron.
Za
pomocą
wspominałem, lepiej
dane (na przykład wartość liczby c a łko wi tej ), nie wystarczy tylko nazwy . Mus imy także skojarzyć z nimi fragment pamięc i komputera. Proces ten nazywa się definicją zmiennej . W C++ deklaracja zmiennej stanowi zarazem jej definicję (z wyjątkiem kilku przyp adków, o który ch będziemy jeszcze mówi ć) . W przypadku pojedyn czej instrukcji podajemy nazwę zmiennej i jednocze śnie przypisujemy ją do obszaru pamięci o odpowiednim rozmiarze.
Aby móc
przechowywać
zdefiniować
A zatem instrukcja :
int value:
Rozdział2.•
Dane. zmienne i działania arytmetyczne
79
jest zarówno deklaracją, jak i definicją. Za pomo cą nazwy zadekl arow anej zmiennej va l ue uzyskujemy dostęp do zdefiniowanego fragmentu pamięci komputera, w którym można prze chowywać pojedynczą wartość typu i nt.
Terminu deklaracja używa się, kiedy wprowadzanaj est nazwa do programu wraz z infor o j ej przeznaczeniu. Termin " defini cja " odnosi się natomiast do procesu przydzie lenia tej nazwie obszaru pamięci komputera. Zmienne można deklarowa ć i definiować w jednej instrukcji - jak w powyższym przykładzie. Powodem takiego dokladn ego roz dzielenia terminów " deklaracja " i " definicja" j est fakt, że można spo tkać instrukcje będąc e deklaracjami. ale nie definicjami. macją
Zmienne w programie mu szą być deklarowane w miejscu znajdującym się wcześniej niż ich pierwsze użycie. Dobrą praktyką w C++ jest deklarowanie zmienn ych w pobliżu miejsca ich pierwszego użycia.
Wartość początkowa zmiennei Deklarując zmienną, możn a pod ać
jej wartość początkową. Deklaracja zmiennej z przypisa niem do niej wartości po czątkowej nazyw a się inicjalizacją . Aby zainicjalizować zmienną podczas deklaracji, wystarczy po jej nazwie postawić znak równości, a po nim podać żądaną wartość. Każda z poniższych instrukcji nadaje zmiennym wartość początkową: int valu e = o:
int count ~ 10:
int number ~ 5 :
W tym przypadku wartość początkowa zmiennej va l ue wynosić 10, a zmiennej number - 5.
będzie
O, zmiennej count
W C++ istnieje jeszcze inny spos ób wpisywania początkowej wartości dla zmiennej, zwany notacją funkcjonalną. Zami ast podawać wartość po znaku równości, można ją umieścić w nawiasach okrągłych po nazwie zmiennej . Wszystkie powyższe przykłady można zapisać następująco :
i nt val ue (O) :
i nt count t l u) :
in t number ( 5) :
Jeśli
nie podamy wartoś ci początkowej zmiennej, to zazwyczaj będzie ona przechowywała to, co z os tało po poprzednim programie w przydzielonym jej obszarze pamięci (jest od tej reguły wyjątek, o którym będziemy mówi ć w dalszej części rozdziału). W miarę możliwości powin no się ini cj al izować wszystkie zmienne. Jeśli zmienne przy rozpoczęciu pracy programu mają znane wartości, to ł atwiej jest znaleź ć źródło problemu, gdy wystąpią błędy. Jednej rzeczy możemy by ć pewni - błęd y na pewno wystąpią.
80
Visual C++ 2005. Od podstaw
Podstawowe typy danych
Rodzaj informacji przechowywanych przez zmienną określony jest przez typ danych. Wszyst kie dane i zmienne w programie muszą być określonego typu. Standard C++ ISO/ANSI definiuje pewną liczbę fundamentalnych typów danych określanych za pomocą słów klu czowych. Nazwa "typy fundamentalne" bierze się stąd, że służą one do przechowywania pod stawowych danych komputera - przede wszystkim danych numery cznych , do których wlicza się także litery, ponieważ są one reprezentowane za pomocą kodu numerycznego. Do tej pory widzieliśmy już słowo kluczowe i nt używane do definiowania zmiennych przechowujących liczby całkowite. W C++/CLI dostępne są także podstawowe typy danych, które nie należą do standardu ISO/ANSI - o nich będzie mowa w dalszej części rozdziału. Jedną
z cech języka zorientowanego obiektowo jest możliwość definiowania własnych ty pów danych, o czym przekonamy się później, a ponadto w bibliotekach, które mamy do dys pozycji w Visual C++ 2005, zdefiniowanych jest wiele dodatkowych typów danych. W tej chwili poprzestaniemy na typach danych dostępnych w C++ ISO/ANSI. Typy fundamen talne dzielą się na trzy kategorie: typy przechowujące liczby całkowite , typy przechowujące liczby niecałkowite , zwane liczbami zmiennopozycyjnymi. oraz typ void, który określa pusty zbiór wartości lub brak typu .
Zmienne calkowite Jak już mówiłem, zmienne typu i nteger (całkowite) mogą przechowywać tylko liczby cał kowite . Liczba graczy w meczu jest liczbą całkowitą (przynajmniej na początku gry) . Wiemy już, że zmienne typu całkowitego deklarujemy za pomocą słowa kluczowego i nt. Zmienne tego typu zajmują cztery bajty pamięci komputera i mogą przechowywać zarówno dodatnie, jak i ujemne wartości. Dolny i górny limit wartości typu całkowitego odpowiada minimal nej i maksymalnej liczbie binarnej ze znakiem, która może być rerrezentowana za pomocą 32 bitów. Górna granica dla zmiennej typu całkowitego wynosi 2 3 -l, czyli 2 147483647, a dolna to --{2 31) , czyli -2 147 483 648. Poniżej znajduje się przykładowa definicja zmiennej całkowitej :
int t oeCount = 10; W Visual C++ 2005 istnieje też słowo kluczowe s hort , które również służy do definiowania zmiennych całkowitych, ale zajmujących tylko dwa bajty pamięci. Słowo kluczowe short jest równoznaczne z short in t . Zmienne typu short (całkowite krótkie) można deklarować następująco:
short feetPerPerson = 2; short int feetPerYard = 3; zmienne są tego samego typu, gdyż s hort i s hor t i nt oznaczają to samo. tutaj obu form , aby pokazać sposób ich użycia, ale w praktyce należy zdecydować się na jedną metodę i konsekwentnie ją stosować. Najczęściej wybierana jest krótsza - short.
Obie
powyższe
Użyłem
Rozdział 2.•
W C++
Dane. zmienne i działania aryimetyczne
81
dost ępny
r ównie ż zapisa ć
jest jeszcze jeden typ całk ow ity - long (całkowity długi), który można jako l ong i nt. Poniżej znajduj ą s i ę przykłady deklarowania zmiennych typu
l ong: long bigNumber = lOOOO OOL: long largeValue = OL; Powyższe
instrukcje dekl aruj ą zmienn e bigNumber i l argeValue o wa rtości ac h początko wych 1000000 i O. Litera L znajdująca się na końcu k ażdego literału informuje, że są to liczby cał kowite typu l ong. Można w tym celu również użyć małej litery l, ale jest ona często mylona z cyfrą l. Literały całkowite bez dołączonego L są typu i nt .
W kodzie nie m ożna s toso wać spacji w dużych liczbach. W tekście ale w programie musi to już być 12345.
m ożna napisać
12 345,
Zmienne całkowite zadeklarowane jako l ong w Visual C++ 2005 zajmuj ą cztery bajty pamięci i mogą mieć wartość od - 2 147483 648 do 2 147483 647, czyli mają taki sam zakres wartości jak zmienne typu i nt.
W innych kompilatorach zmienne typ u 70ng (który jest równoznac zny z 70ng i nt) m ogą nie być identyczne z i nt. Należy o tym pamiętać, planując kompilację swoich pro gramów w innych środowiskach. Aby kod był w pełni przenośny, nie m ożna nawet zakładać, że typ i nt zajmuje cztery bajty (np. w starszych 16-bitowych wersjach Visual C++ zmienna typu int z ajm owała tylko dwa bajty).
Znakowe Iypy danych Typ danych char służy do dwóch celów . Określa on jednobitow ą zmienną, której można użyć do przechowywania liczb całko witych z określonego zbioru lub pojedynczego znaku ASCII (ang . American Standard Code for 1nformation Exc hange). Kody znaków ze zbioru ASCII znajduj ą się w dodatku B. Zmienną typu char definiujemy w na stępujący sposób:
char lett er Powyższa
~
'A' ;
nazwie letter i inicjalizuje ją wartością początkową tylko z jednej litery podajemy w pojedynczych cudzysłowach, a łańcuchy znaków w podwójnych. Łańcuch znakó w to szereg wartości typu char zgrupowanych w jeden c i ąg , zwany tablicą. Do tablic i ł ańcuchów znaków wrócimy jeszcze w rozdziale 4. 'A' .
instrukcja deklaruje
zmienną o
Zauważmy, że wartości składające się
Ze wzgl ędu na fakt , że litera " A" w ASCII jest reprezentowan a przez dobrze mogliśmy zapisać n aszą instrukcję następująco :
char let t er = 65 ;
li czbę
65 , to równie
II Równoznaczne z A.
Instrukcja ta spowoduje taki sam rezultat jak poprzednia. Liczby w zmiennych znakowych mogą mieć rozmiar od - 128 do 127.
całkowite
przechowywane
82
Visual C++ 2005. Od podslaw Pamiętaj, ż e
standard C++ ISO/ANSI nie wymaga, aby typ char reprezentował j edno bajtowe liczby całkowite ze znakiem. Czy typ char ma reprezen to wać liczby całkowite ze znakiem, należące do zbioru od -128 do + 127, czy liczby calkowite bez znaku od Odo 255, zależy wyłącznie od twórcy kompilatora. Należy o tym pamiętać podczas przenoszenia kodu C+ + do innego ś ro dowis ka. Typ wchar_t oznacza typ wide character. Zmienne tego typu przechowują dwubajtowe kody znakowe o wartościach z przedziału 0- 65 535. Poniżej znajduje się przykład definicji zmien nej typu wchar_t:
wchar t letter = L' Z':
II Zmienna przechowują c a 16-bit owy kod znak owy.
Powyższa
instrukcja definiuje zmienną 1et t er, która jest zainicjalizowana 16-bitowym kodem litery "Z". Znajduj ąc a s i ę z przodu wielka litera L informuje kompilator, że jest to 16-bitowy kod znakowy.
Do inicjalizacji zmiennych znakowych Ci innyc h typów całkowitych) możem y także używać wartości szesnastkowych, które oczywiśc ie są prostsze w u życ iu, gdy kod y znaków mam y podane w systemie szesnastkowym (heksadecymalnym). Liczba szesnastkowa zapisywana jest przy użyc iu standardowego systemu szesnastkowego - za pomocą cyfr od O do 9 oraz liter A - F (lub a - f) reprezentujących liczby od 10 do 15. Z przodu zaw sze dodaje s i ę znaki Ox (lub OX) w celu odróżnienia od wartości dziesiętnych . A zatem aby u zyskać wynik identyczny z poprzednim, ostatnią instrukcję możemy zapisać następująco:
cha r let t er = Dx4 l :
II Równoznaczne z A.
Nie zapisuj liczb całkowitych z wiodącym zerem. Kompilator potraktuje je jako ósemkowe (base 8) - wartość 065 w systemie dz i esi ętnym b ędzie wynosiła 53.
wartości
Warto także pamiętać , że w systemie Windows XP dostępne j est narzędzie Tablica znaków, które pozwala zlokalizować znaki dowolnego fontu dostępnego na komputerze. Pokazuje kod szesnastkowy danego znaku i podpowiada, jak go wprowadzi ć z klawiatury. Narzędzie to dostępne jest w menu Start/Akcesoria/Narzędz ia systemowe.
Modyfikatory typU integer Zmienne jednego z typów i nt eger - char, i nt , short lub Ionq - domyślnie przechowują warto ś ci całkow ite ze znakiem , a więc można ich używać do przechowywania zarówno warto ści dodatnich, jak i ujemnych. Jest to możliwe , ponieważ zakłada się, że mają one domyślny modyfikator typu si gned. W związku z tym w każdym miejscu, gdzie napisaliśmy i nt lub l onq, równie dobrze mogliśmy napisać si gned i nt lub s i gned l ang. Możemy również określić
przypadku
będzie
signed va lue
~
to
-5:
typ zmiennej za pomocą samego s i gned i nt . Na przykład:
oznaczać
II Równ oznaczne z signed in/o
słowa
kluczowego s i gned. W takim
Rozdzial2. • Dane, zmienne i działania aryimetyczne Zapis taki nie jes t często spotykany i ja osob iście wo lę jest czytelniejszy.
używać
83
i nt, który sprawia , że program
Wartości, które można przechowywać w zmiennej typu cha r, zawierają się w zakre sie od - 128 do + 127, czyli takim samym jak dla zm iennej typu signed char. Poza tym typy char i signed char są różn ymi typami i nie należy zakłada ć , że to to samo. Jeśli masz pewność, że nie będzie konieczności przechowywania wartości ujemnych w danej zmiennej (je śli np. zapisujemy liczbę przejechanych w c i ągu tygodnia kilometrów), to jej typ m ożemy określi ć jako unsigned:
unsi gned lang mileage = OUL: W tym przypadku minimalną wartością zmiennej mi l eage jest zero, a m aksymalną 32_ liczba 4 294 967 295 (czyli 2 1). Porównaj tę li czbę z maksym alną warto ś cią typu signed long - - 2 147483648. Bit, który był użyty do określenia znaku liczby, w typie un si gned jest wykorzystany jako część wartości. W konsekwencji zmienna typu unsigned ma większy zasięg warto ś ci dodatnich, ale nie może przechowywać wartości ujemnych. Zauważ , że do stałych bez znaku dołączana je st litera U(lub u). W powyższym przykładzie dołączyłem także L, aby zaznaczyć, że stała jest typu l onq. Zarówno L, jak i U mogą być pisane wielką lub małą lite rą. Kolejno ś ć nie gra tutaj roli, choć dobrze jest konsekwentnie stosować jeden sposób określania taki ch wartości. Słowa kluczowego unsigned W takim przypadku zmienna Pamiętaj, ż e
można także uży ć będzie typu
samodzielnie do
okre ślenia
typu zm iennej .
unsi gned i nt.
si gned oraz unsi gned to sło wa kluczow e i nie
można używać
ich jako nazw
zmi ennych.
Typ logiczny Zmienne logiczne mogą mieć tylko jedną z dwóch wartości : true lub false. Typem logicznej zmiennej jest bool - nazwany od twórcy algebry boolowskiej, George'a Boole'a. Typ bool zaliczany jest do typów całkowitych. Zmienne logiczne nazywane są także czasami zmiennymi boolowskimi. Wykorzystywane są one do przechowywania wyników testów , które mogą być albo true albo fal se - np . czy jedna wartość jest równa drugiej, czy nie. Nazwę
zmiennej logicznej
można zadeklarować za pomocą następującej
instrukcji:
baal testResult : Oczyw i ście ,
podczas deklaracji
możemy także inicjalizować
zmienne logiczne:
baal calarIsRed = tr ue : Wartości TRUf i FAL5f są powszechnie używane ze zmiennymi o typa ch num erycznych. a w szczególn ośc i int. Jest to pozostałość po czasach, gdy nie było j eszcze implem entacji zmiennych logicznych w C++ i do reprezentacji wartości logicznych wykorzystywane były
84
Vilillal C++ 2005. Od podstaw zmienne typu in t . Wartos ć Ow takim przypadku traktowana jest jako f a lse, a każda inna jako true. Symbole TRUf i FA L5f są wciąż używane w bibliotece MFC. gdzie reprezentują odp owiednio wartos ć niezerową oraz O. Zauważ, że TRUf i FAL5f (pisane wielkimi literami) nie są słowami kluczowymi w C++ - są one tylko symbolami zdefiniowany mi w obrębie biblioleki MFC Należy równieżpamiętać, że TRUf i FAL5f nie są prawidłowymi warto ś ci am i logicznymi. Ni e należy zolem mylić t r ue z TRUf.
Typy zmiennopoZYCyjne Wartości, które nie są liczbami całkowitymi , przechowywane są jako liczby zmiennopozy cyjne. Mogą być one reprezentowane jako wartości dziesiętne (np . 112,5) lub z wykładnikiem (np. l, l25E2), gdzie 'część dziesiętna jest mnożona przez liczbę dziesięć podniesioną do p otęgi podanej po literze "E ". Zatem nasza przykładowa liczba 112,5 to: 1,125'10 2 = 112,5. Stała zmiennopozycyjna musi zawierać kropkę o d d z i e l aj ąc ą ułamek dziesiętny lub wykład nik (albo j edno i drugie). Jeżeli napiszemy li czbę bez żadn ego z tych znaków. otrzymamy wartość całkowitą .
Zmienną zmiennopozycyjną można określić
szym
za
pomocą słowa
kluczowego doub l e, jak w
poniż
przykładzi e:
double in to mm = 25 .4: Zmienna typu doubl e zajmuje osiem bajtów pamięci i przechowuje wartości z dokładno ś c ią do około 15 miejsc Fao przecinku. Zbiór przechowywanych w artoś ci jest znacznie w iększy i wynosi od l,7 xlO- os do 1,7 xl0 30s. Jeżeli
nie planujemy wykonywać obliczeń z dokładnością do 15 miejsc po przecinku i nie potrzebujemy używać tak olbrzymich liczb, to możemy użyć słowa kluczowego f l oat w celu zadeklarowania zmienn ych zmiennopozycyjnych zajmujących tylko cztery bajty. Na przykład :
fl oat pi
=
3.14159f:
Powyższa
instrukcja deklaruje zmienną pi o wartości po czątkowej 3 . 14159f. Litera f na koń cu oznacza, że j est to stała typu fl oat . Gdyby śmy nie wpisali tej litery, to nasza stała byłaby typu doub l e. Zmienne deklarowane jako f loat mają dokładnoś ć do około siedmiu miejsc po prze cinku i przechowują wartości ze zbioru od 3,4x 10-3s do 3,4 x 103s. W standardzie C++ ISO/ANSI został zdefiniowany jeszcze typ zmiennoprzecinkowy l ong double, który w Visual C++ 2005 ma zaimplementowany taki sam zbiór wartości i dokład noś ćjak typ doubl e. W niektórych kompilatorach typ l ong double odpowiada 16-bitowej wartości zm iennopozycyjnej o znacznie większej dokładności i szerszym zakres ie możliwych wartości w porównaniu z typem doubl e.
Rozdzial2. • Dane. zmienne i działania arytmetyczne
85
Podstawowe typy danych wC++ 180/AN81 Poniższ a
tabela zawiera pod sum owanie wszystk ich pod stawowych typów danych C++ ISO/ANSI oraz zakres obsługiwanych przez nie wartości w Visual C++ 2005:
Rozmiar wbajtach
Typ
Zakres wartości
bool
t r ue lub f al se
char
Dom yślnie możn a
taki sam jak dla si gned char : -128 do + 127. Opcjo nalnie char n ad a ć taki sam zakres j ak uns ign ed char.
s i gned char
-128do+127
uns i gned char
Odo 255
wc har t
2
Odo 65 535
short
2
-32 768 do 32 767
unsigned short
2
Odo 65535
i nt
4
-2 147483648 do 2 147483647
unsi gned i nt
4
Odo 4 294 967 295
l ong
4
-2 147 483 648 do 2 147 483 647
unsi gned l ong
4
Odo 4 294 967 295
fl oat
4
±3,4 ' 1O±38 z dokladno ści ą do okola 7 miej sc po przecinku
doubl e
8
± I,7' 1O±308 z
dokł adności ą do około
15 miej sc po prze cinku
l ong doubl e
8
± 1,7'1 O±30 8 z
dokładnoś c ią
15 miejsc po przecinku
do
około
Literał, Do tej pory wielokrotnie już i n icja li z ow ał e m zmienne konkretnym i warto ściami . W C++ ustalone wartoś ci jakiegokolwiek typu nazywają się Iiterałami. Literał to wartość określonego typu, a więc wartoś ci 23,3 .14159,9 .5f oraz true są przykładami odpowiednio literałów typów i nt , doubl e, flo at oraz boa l. Literał "Samuel Beckett " jest przykładem literału będącego łań cuchem znaków (łańcuchom bliżej przyjrzymy się dopiero w rozdziale 4.). W tabeli na następ nej stronie znajduje s ię podsumowanie literałów różny ch typów. Choć
dla
literału
nie
można określi ć
początkowe wartoś ci ,
typu sho rt lub unsi gned short , to kompilator zaakceptuje typu i nt, dla zmiennych tych typów , pod warunkiem się w zakresie typu zmiennej.
które
że wartość literału mieści
Literałów często używa się
są literałami
w program ach do wykonywania obliczeń. Mogą to być na przykład konwer sji, takie jak 12 przy przeliczaniu stóp na cale czy 25,4 przy przeliczaniu cali na milimetry, albo łańcuch stanowiący komunikat o błędzie . Powinno s ię jednak unikać uży wan ia literałów liczbowych w programach, kiedy ich znaczenie nie jest oczywiste. Nie każdy musi wiedzieć, że kiedy używamy liczby 2,54, to odpowiada ona liczbie centymetrów w calu .
wartoś ci
86
Visual C++ 2005. Od podstaw
Typ
Przykład
char, signed char lub unsigned cher
"A", "Z", "8",
wchar t
LilA", L"Z" , L Il8 ", L"*"
int
- 77, 65, 12345, Ox9FE
unsi gned int
IOU,64000U
long
- 77L, 65L, 12345L
unsigned long
5UL, 999999999UL
flo at
3.14f, 34.506f
double
1.414, 2.71828
long double
1.414L,2.71828L
bool
true, false
Iileralu "*"
Lepiej jest zadeklarować zmienną o odpowiedniej stałej wartości - można ją na przykład nazwać InchesToCentimeter s. Za każdym razem, gdy używamy tej zmiennej w kodzie , jej prze znaczenie jest oczywiste. Jak nadać zmiennej stałą wartość, dowiemy się w dalszej części rozdziału.
Deliniowanie synonimów typÓW danych Słowo kluczowe typedef pozwala na zdefiniowanie własnej nazwy dla istniejącego już typu danych. Za jego pomocą standardowy typ l ong i nt możemy nazwać na przykład Bi gOne s:
typedef long i nt Bi gOnes; II Definiowanie nazwy BigOn es jako nazwy typu. Powyższa
temu
instrukcja definiuje Bi gOnes jako dodatkowy określnik dla typu l ong i nt . Dzięk i jako long i nt za pomocą następującej instrukcj i:
zmienną mynum możemy zdefiniować
BigOnes mynum
=
OL : II Definiowanie zmiennej typu long int.
Pomiędzy powyższą deklaracją
Równie dobrze
a tą używającą wbudowanej nazwy typu nie ma
żadnej różnicy .
moglibyśmy napisać:
long i nt mynum = OL; II Defini owan ie zmiennej typu fong int,
Rezultat będzie identyczny. W ten sposób, przy użyciu dwóch okre ślników typu w obrębie jednego programu, można zadeklarować różne zmienne, które będą miały ten sam typ. na fakt, że słowo kluczowe typedef służy do tworzenia synonimów typów, może jest ono niepotrzebne - ale tak nie jest. Później dowiesz się, że odgrywa ono bardzo ważną rolę w upraszczaniu skomplikowanych deklaracji , gdyż umożliwia zdefiniowanie pojedynczej nazwy do reprezentowania zawiłych specyfikacji typu. Sprawia to, że kod staje się o wiele bardziej czytelny.
Ze
względu
się wydawać, że
Rozdział
2.• Dane. zmienne i działania arylmelyczne
87
Zmienne ookreślonych zbiorach wartości Czasami będziesz potrzebować zmiennych mogących przyjmować wartości z okre ślonego zbioru, do których można się odwoływać za pomocą etykiet - na przykład nazwy dni tygo dnia czy miesięcy. W C++ dostępne jest specjalne narzędzie do tego celu, zwane wylicze niem (lub enumeracją) . Weźmy jeden z wymienionych przykładów - zmienna, która potrafi przyjmować odpowiednie wartości w zależności od dnia tygodnia. Jej definicja może wyglą dać następująco:
enumTydzien{pon . wt. sr .
CZW.
pia. sa . nd} tenTydzien:
Powyższa
instrukcja deklaruje typ wyliczeniowy o nazwie Tydzien oraz zmienną t enTydzi en egzemplarzem typu wyliczeniowego Tydz i en, który może przybierać tylko stałe war tości ze zbioru podanego w nawiasach klamrowych . Próba przypisania do tenTydzi en czego kolwiek spoza podanego zbioru spowoduje błąd. Symboliczne nazwy pomiędzy nawiasami nazywają się argumentami typu wyliczeniowego. W rze czywistości każda nazwa dnia zosta nie automatycznie zdefiniowana jako reprezentacja stałej wartości w postaci liczby całkowitej . P ierwsza nazwa na liście , pan, ma wartość O, wt - l itd. będącą
Jedną
ze stałych wyliczeniowych sposób:
można przypisać jako wartość zmiennej
tenTydzi en w
nastę
pujący
t enTydzien = czw: Zauważ, że stałej
wyliczeniowej nie trzeba kwalifikować za pomocą nazwy enumeracji . War zmiennej ten Tydzi en będzie wynosiła 3, ponieważ stałym symbolicznym, zdefiniowanym przez wyliczenie, domyślnie przyp isywane są kolejne wartości typu i nt, rozpoczynając od zera.
tość
Standardowo każdy następny argument jest większy od poprzedniego o jeden . chcemy rozpocząć wyliczanie od wybranej wartości, to możemy napisać:
enum Tydz ien {pan = l . wt . sr .
CZW.
Jeśli
jednak
pia. sa. nd} tenTydzien:
St ałe
wyliczeniowe w powyższym przykładzie będą miały wartości od l do 7. Argumenty nie nawet mieć unikalnych wartości. Możemy na przykład pan i v/t przypisać wartoś ć l za pomocą instrukcji: muszą
enumTydzien {pan ~ l . wt
=
l . sr . czw. pia. sa . nd} t enTydzien:
Jako że zmienna t enTydzi en jest typu i nt , zajmuje cztery bajty kie inne zmienne typu wyliczeniowego. Kiedy mamy już
zdefiniowanąformę
wyliczenia, to
pamięci,
podobnie jak wszyst
możemy zdefiniować inną zmienną:
enum Tydzien nastepnyTydzien : Powyższa
instrukcja definiuje zmienną nastepnyTydzien jako wyl iczenie, które może przy z poprzedniego wyliczenia. Możemy także pominąć słowo kluczowe enum
bierać wartości
i
powyższe wyrażenie zapisać następująco :
Tydzien nastepny t ydzi en:
88
Visual C++ 2005. Od podstaw Jeśli
chcemy, możemy przypisać określone wartości do wszystkich argumentów wyliczenia. na przykł ad zdefiniować takie wyliczenie:
Możemy
enum Interpunk cja {przecinek = ',', wykrzyknik =
'I',
pytajnik = '?'} rzeczy:
W powyższym wyrażeniu dla zmiennej rzeczy zdefiniowaliśmy wartości jako liczbowe ekwi walenty odpowiednich symboli. Z tablicy znaków ASCII w dodatku B wynika, że podane symbole w zapisie dziesiętnym mają odpowiednio kody 44,33 i 63. Jak widać, wartości nie muszą występować w porządku rosnącym. Jeżeli któremuś elementowi nie nadamy żadnej wartości, to zostanie mu nadana o jeden większa od poprzedniej, tak jak w naszym drugim przykładzie z dniami tygodnia. Typ wyliczenia możemy pominąć, jeżeli nie będziemy zmiennych tego typu . Na przykład :
później
potrzebowali
definiować
innych
enum {pon, wt , sr , czw , pia. so. nd} t enTydzien. na st epnyTydzien. zeszlyTydzien; W powyższej instrukcji mamy trzy zmienne, które mogą przyjmować wartości od pan do nd. Jako że typ wyliczenia nie został podany, nie możemy się do niego odwoływać. Zauważ, że dla tego wyliczenia nie możemy już zdefiniować żadnych innych zmiennych, ponieważ nie mogli byśmy powtórzyć definicji. Próba zrobienia tego potraktowana by była jako próba ponownego zdefiniowania wartości od pan do nd, ajest to niedozwolone.
Określanie typU stałych
wyliczeniowych
Stałe wyliczeniowe domyślnie mają typ int, ale możemy określić go w sposób jawny, dodając dwukropek oraz nazwę typu po nazwie wyliczenia w deklaracji. Stałym wyliczeniowym można nadać dowolny typ całkowity ze znakiem lub bez: short, int, 10n9 lub char albo typ logiczny , Dzięki temu wyliczenie sposób:
reprezentujące
dni tygodnia
moglibyśmy zdefiniować
w
następujący
enum Tydzien : char{ poni edzialek, wtorek, sroda , czwa rtek . piate k, sobota, niedzie la}: W tym wyliczeniu stałe będą typu c ha r , a pierwsza z nich będzie miała wartość O. Jednak nadając stałym typ char , prawdopodobnie wolelibyśmy je inicjalizowa ć jawnie w następujący sposób:
enum Tydzi en
char{ poniedzialek=' p' , v~ o r e k ~ · w' . sroda='s ', czwa rtek='c' . pi at e k~ 'p' , sobota='s ' , niedziel a= ' n'} :
W obecnej postaci wartości stałych trochę lepiej odzwierciedlają to, co przechowują, chociaż nie rozróżniają one takich dni jak s roda i sobota czy poniedzialek i piatek. Takie same war tości dla różnych stałych nie stanowią problemu, ale wszystkie nazwy muszą być oczywiście unikalne, Poniżej
mamy
enum Sta te
przykład
wyliczenia ze
bool { On
~
stałymi
true, Off=fal se} :
typu bool :
Rozdział 2.•
Ze
Dane. zmienne i działania arytmetyczne
89
względu
byśmy
na fakt, że On ma wartość początkową true, Off przybierze wartość fa l se. Gdy podali więcej stałych wyliczeniowych, to ich wartości zmieniałyby się na przem ian.
Podstawowe operacje wejścia-wyjścia Na temat operacji wejścia-wyjścia powiemy sobie tylko w odniesieniu do natywnego C++ . Nie jest to takie trudne - wręcz przeciwnie - ale do programowan ia dla Windowsa nie będziemy tej wiedzy potrzebować. Operacje wejścia-wyjścia w C++ skupiają się wokół koncepcji strumienia danych , które możemy wprowadzać do strumienia wyjściowego i pobie ra ć ze strumienia wejściowego. Dowiedzieliśmy się już, że do standardowego strumienia wyj ściowego C++ ISO/ANSI wysyłającego dane do wiersza poleceń na ekranie odwołujemy się za pomocą słowa kluczowego cout . Odpowiadający mu strumień wejściowy przyjmujący dane z klawiatury to ci n.
Wprowadzanie danych zklawiatury Dane z klawiatury przyjmujemy za pomocą strumienia wejściowego ci n przy użyciu operatora pobierania » . Aby pobrać dwie wartości typu i nteqer - numl i num2 - możemy posłużyć się następującą instrukcją:
cin
»
numl
»
num2:
Operator pobierania » wskazuje kierunek, w którym płyną dane - w tym przypadku ze strumienia ci n do każdej z podanych dwóch zmiennych . Wszelkie wiodące białe znaki są pomijane, a pierwsza wartość typu i nt, którą wprowadzimy z klawiatury, zostanie przypisana do zmiennej numl. Dzieje się tak, gdyż instrukcja wejściowa wykonywana jest od lewej do prawej. Wszelkie białe znaki występujące po zmiennej numl zostaną zignorowane, a druga wartość typu całkowitego, którą wprowadzimy z klawiatury, zostanie przypisana do zmiennej num2. Należy jednak pamiętać, że pomiędzy poszczególnymi wartościami musi wystąpić jakaś przerwa, aby można je było odróżnić . Operacja wprowadzania strumienia danych kończy się w momencie naciśnięcia klawisza Enter - program kontynuuje wówczas działanie, przecho dząc do następnego wyrażenia. Oczywiście, jeśli wprowadzimy nieprawidłowe dane, spowo dujemy błąd, ale zakładam, że zawsze wprowadzasz je prawidłowo! Liczby zmiennopozycyjne są wczytywane z klawiatury w taki sam sposób jak liczby cał kowite i można je oczywiście mieszać . Dane ze strumienia wejściowego i operacje automa tycznie radzą sobie ze zmiennymi i danymi jednego z typów podstawowych. Na przykład w poniższych instrukcjach:
int numl = O. num2 ~ o:
double fact or = 0.0:
cin » numl » ulamek » num2 :
ostatni wiersz wczyta liczbę całkowitą do zmiennej numl, następnie liczbę zmiennopozycyjną do zmiennej ul amek oraz liczbę całkowitą do zmiennej num2.
90
Visual C++ 2005. Od podstaw
Wysyłanie
danych do wiersza poleceń
Widzieliśmy już, jak wysyła s ię dane do wiersza poleceń, ale chciałbym do tego zagadnienia jeszcze na chwilę powrócić. Wypisywanie danych na ekranie działa w sposób uzupełniający do wprowadzonych danych . Jak wiemy, strumień wyjściowy nazywa się cout i do przesyłania do niego danych używamy operatora wstawiania «. Operator ten wskazuje również kierunek przepływu danych. Użyliśmy go już do wysłania danych spomiędzy cudzysłowów. Proces wy syłania wartości zmiennej zademonstruję na przykładzie prostego programu.
~ Wysyłanie danych do wiersza poleceń Zakładam, że
potrafisz już utworzyć nowy pusty projekt, dodać do niego nowy plik źródłowy oraz skompilować go do wykonywalnej postaci . Poniżej znajduje się kod, który należy wpisać do pliku źródłowego po utworzeniu projektu o nazwie Cw2_02: IICw2_02.cpp
II Ćwicze n ie wysyłania dany ch na wyjście.
#i ncl ude using std: :cout: using std' :endl: int main() (
5678 : II Rozpocznij w nowym wierszu. II Wyślij dwie wartości. II Zakończ na nowym wierszu . II Wyjdź z programu.
Jak to działa Pierwsza instrukcja w ciele funkcji main () deklaruje i inicjalizuje dwie zmienne: numl i num2. mamy dwie instrukcje wyjścia, z których pierwsza przenosi kursor do nowego wiersza. Jako że instrukcje wyjścia są wykonywane od lewej do prawej, to druga z nich wyświetla wartość zmiennej numl przed wartością zmiennej num2. Następnie
Po skompilowaniu i uruchomieniu tego programu otrzymamy
następujący
wynik:
12345678 Wynik jest poprawny, ale niezbyt pomocny. Pomiędzy poszczególnymi wartościami potrzebna jest co najmniej jedna spacja . Domyślnie strumień wyjściowy tylko wysyła cyfry, nie dodając żadnych spacji oddzielających poszczególne wartości, co umożliwiłoby ich rozróżnienie. W tej postaci nie mamy możliwości określenia, gdzie kończy się jedna liczba, a gdzie zaczyna druga.
Rozdział 2.
• Dane, zmienne i działania arytmetyczne
91
Formatowanie wysylanych danych Problem braku spacji w wynikach można bardzo łatwo rozwiązać, wstawiając dwiema wartościami. Aby tego dokona ć, należy poniższy wiersz:
cout
«
num1
«
num2;
II
Wyślij
dwie
spację pomiędzy
war/oś ci ,
zastąpić następującym:
cout
«
num1
«
' , «
nu m2 :
II
Wyślij
dwie
war/ości.
Oczywiście gdybyśmy
mieli kilka wierszy wyników, które chcemy wyrównać w kolumnach, nie wiemy, z ilu cyfr będzie składać się każda wartość. W takiej sytuacji możemy posłużyć się tak zwanym manipulato rem. Służy on do modyfikowania sposobu obsługi danych wysyłanych do (lub otrzymywa nych ze) strumienia.
to
potrzebowalibyśmy trochę większych możliwości, ponieważ
Manipulatory zdefiniowane są w pliku nagłówkowym , aby więc z niego skorzy stać , musimy dodać odpowiednią dyrektywę #i ncl ude. Teraz skorzystamy z manipulatora set wrn), który spowoduje wyrównanie wysłanych danych do prawej w polu o szerokości n spacji . set w(6) spowoduje zatem, że następna wysłana wartość zostanie zaprezentowana w polu o szerokości sześciu spacji. Sprawdźmy, jak to wygląda w praktyce.
~ Uzywanie manipulatorów Aby
uzyskać pożądany
wynik, możemy
zmienić
nasz program w
następujący
sposób:
II Cw2_03 .cpp
II Ćwiczenie wysyłania danych na wyjście.
#include #include using std: :cout: usi ng std : :endl : usi ng st d: :setw: i nt mainO (
int num1 ~ 1234 , num2 ; 5678: cout « endl : cout « setw(6) « num1 « setw(6J « num2 : cout « end l , return O:
II Wyślij dwie war/ości. II Rozpo cznij w nowym wierszu. II Wyjdź z programu.
Jak to działa Zmiany w stosunku do poprzedniej wersji programu to dodanie dyrektywy #i ncl ude dla pliku nagłówkowego , deklaracja usi ng dla nazwy set w z przestrzeni nazw st d oraz wstawienie manipulatora set w( ) do strumienia wyjściowego przed każdą wartością, dzięki
92
Visual C++ 2005. Od podstaw czemu są one prezentowane w polach o szerokości rezultat z oddzielonymi od siebie dwiema liczbami:
sześciu
spacji. W wyniku otrzymujemy
1234 5678 Zauważmy, że
manipulator setw() działa tylko na pojedyncze wartości wyjściowe występujące po nim w strumieniu. Manipulator musi bezpośrednio poprzedzać każdą wartość, którą chcemy zaprezentować w polu o określonej szerokości w strumieniu wyjściowym. Jeśli użyjemy go tylko raz, to będzie miał zastosowanie tylko do tej wartości, która występuje po nim. Wszystkie pozostałe wartości zostaną wysłane w tradycyjny sposób. Możemy to spraw dzić, usuwając z kodu drugi przykład zastosowania setw(6) oraz jego operator wstawienia. bezpośrednio
KOIlowanie znaków specjalnych Pisząc łańcuch
znaków umieszczony w podwójnych cudzysłowach, możemy do niego wstawić specjalne znaki, zwane symbolami zastępczymi. Ich nazwa wzięła się stąd, że pozwalają one na wstawianie do łańcuchów znaków, których normalnie wstawiać tam nie można, zastępując je odpowiednimi symbolami. Kod znaku rozpoczyna się od znaku lewego ukośnika \, który informuje kompilator, że następny znak należy potraktować w specjalny sposób. Na przykład znak tabulacji ma postać \ t - kompilator rozumie, że litera t reprezentuje tabulację w łańcu chu, a nie prawdziwą literę "t". Spójrzmy na dwie poniższe instrukcje wyjściowe:
cout cout
endl endl
« «
« «
"To są dane wyjściowe."; "\tTo są dane wyjściowe po znaku tabulacji.
Rezultat ich działania
To
są
To
będzie następujący:
dane wyjściowe.
są dane wyjściowe po znaku tabulacji.
Sekwencja \ t w drugim pierwszego tabulatora.
wyrażeniu spowodowała wcięcie wysyłanego
tekstu do pozycji
W rzeczywistości, zamiast używać słowa kluczowego endl, jako znaku nowego wiersza można kodu xn. Tak więc powyższe instrukcje moglibyśmy równie dobrze zapisać w następujący sposób:
użyć
cout cout
« «
"\nTo są dane wyjściowe."; "\n\tTo są dane wyjściowe po znaku tabulacji.
Tabela na następnej stronie zawiera spis najbardziej przydatnych kodów znaków specjalnych. Oczywiście, jeśli
chcemy umieścić w łańcuchu znak lewego ukośnika lub podwójny cudzy jako znak, który ma być jego częścią, to musimy użyć odpowiedniego kodu (symbolu zastępczego). W przeciwnym przypadku lewy ukośnik zostanie zinterpretowany jako początek innego kodu, a podwójny cudzysłów jako wyznacznik końca łańcucha. słów
Kodów znaków specjalnych
można także używać
do inicjalizacji zmiennych typu char. Na
przykład:
char Tab
~
'\t'; II Inicjalizacja za
pomocą
znaku tabulacji.
Rozdział 2.
Kod
Przeznaczenie
\a
odtwar zanie
\n
nowy wiersz
\'
pojedynczy c u d z ys łów
\\
lewy uk o śnik
\b
backspace
\t
znak tabulacji
\"
podwójny c u dzys łów
\7
znak zapytania
Ze
• Dane. zmienne i działania arytmetyczne
93
dźw ię k u
względu
rału
na fakt, że lit er ały są otaczane pojedynczymi c udzysłow am i, w celu podania lite znakowego będ ąc e go pojedynczym cud zy sł owem musimy u ży ć kodu - ' \ ' , .
~ Używanie kodów znaków specjalnych Poni żej
znajduj e się pro gram, w któ rym wyk orzystan o niektóre kody znaków specjalnych z powyższej tabeli: II Cw2_04.cpp
II Używan ie symboli zastępczyc h.
#inc l ude #include usi ng std: :cout ; int ma i n()
{ char newl i ne = " vn " : II Sy mbol zas tępczy znaku nowego wiersza.
cout « newl i ne: II Rozpocznij w nowym wiersz u.
cout « "\ "We\ ' 11 make aur escapes i n sequence\". he sai d . " :
cout « "\ n\ tThe pr ogr am\ ' s over . i t\'s t i me t o make a beep beep. \ a\a ";
cout « newl i ne: II Rozpocznij w nowym wierszu . II Wyjdź z programu. re turn O;
Po skompilowaniu i uruchomien iu tego programu otrzy mamy
następuj ący
rezult at:
-We' l l make aur escapes i n sequence- , he sai d . The program 's over. i t ' s t i me tak e ma ke a beep beep.
Jak lo działa Pierwszy wiers z w funkcji mai n( ) definiuje zm i enn ą newl i ne i inicjal izuje ją za p om ocą zako dowanego znaku nowego wiersza. Dzi ęki temu zamiast s łowa kluczoweg o endl możem y uży wać
newl ine.
94
Visual C++ 2005. Od podstaw Po wysłaniu newl i ne do strumienia cout wysyłamy łańcuch , w którym użyte zostały zako dowane znaki podwójnego i pojedynczego cudzysłowu . Dla pojedynczych cudzysłowów nie musimy tutaj używać kodowania, gdyż ł ańcu ch otoczony je st c ud zysłowa m i podwójnymi, dzięki czemu kompilator rozpozna je j ako zwykłe znaki pojedynczego cudzysłowu, a nie znacznik końca łańcucha. Natomiast dla podwójnych cudzysłowów w tym łańcuchu musimy zastosować kodow anie . Łańcu ch rozpoczyna się od zakodowanego znaku nowego wiersza, po którym następuje zakodowany znak tabulacji , dzięki czemu wy słany wiersz zostanie wcięty . Na końcu łańcucha znajdują się jeszcze dwa zakodowane znaki powodujące odtworzenie dźwięku, a więc po uruchomieniu programu powinniśmy usł yszeć podwójny odgłos z głośnika komputerowego.
Wykonywanie obliczeń wC++ W tej chwili zaczynamy rzeczywiście coś robić z wprowadzanymi danymi . Wiemy już , jak proste operacje wejścia-wyj ś cia. Teraz przejdziemy do częś ci związanej z przetwa rzaniem danych w programie w C++. Prawie ws zystkie zagadnienia związane z liczeniem w C++ są całkowicie intuicyjne, a więc będzie to dla nas bułk a z masłem .
wykonać
Instrukcia przypisania Do tej pory
widzieliśmy już
instrukcje przypisania kilka razy. Taka typowa instrukcja
wygląda
następuj ąco:
calosc = czescl
+
czesc2
+
czesc3:
Instrukcja przypisania pozwala na oblic zenie wartości wyrażenia znajdującego si ę po pra wej stronie znaku równości - w tym przypadku sumy wartości zmiennych czescl, czesc2 i czesc3- i zapisanie wyniku w zmiennej , której nazwę podajemy po lewej stronie - w tym przypadku jest to ca l osc. W tej instrukcji ca l osc je st sumą swoich części i niczym więcej. Zauważ , że
instrukcja jak zawsze zako ńczon a j est ś redn ikiem .
Możemy również tworzyć powtarzające się
a
~
b
=
przypi sania, jak na
przykład :
2:
Powyższa
a, tak
że
instrukcja oznacza przypisanie zmiennej b wartości 2, a następnie wartości b zmiennej na końcu obie zmienne mają tę samą warto ść 2.
Typy Ivalue i rvalue Lvaluc to coś, co odnosi się do adresu w pamięci i nazywa s i ę tak, ponieważ każde wyrażenie , którego wynikiem jest l val ue, może pojawić się po lewej stronie znaku równoś ci (ang. lefi) w instrukcji przypisania. Większość zmiennych j est typu l val ue, ponieważ okre ślają one
Rozdział 2.
• Dane, zmienne i działania arytmetyczne
95
miejsce w pam i ęc i . Jak się jednak później przekonamy, istnieją też zmienne, które nie są tego typu i nie mogą p oj aw i ć się po lewej stronie instrukcji przypisania, ponieważ ich wartości zo stały zdefiniowane j ako stałe . Zm ienne a i b p oj awiaj ące s i ę w poprzedn im przykładz ie są typu l va l ue. Natomiast wynik wyra żen i aa - b nie, po n ieważ nie okre ś la on adres u w p am i ęc i , gdzie warto ść ta mogłaby być przechowywana. Wy nik wyraże nia, który nie jest typu l val ue, nazywany jest r valu e.
Wiedza na temat typu 7va 7ue będzie nam s ię czasami przydawała w różnych częśc iach - często najmniej spodziewanych - a więc warto ją sobie przyswoić.
książki
Działania
arytmetyczne
Podstawowe operatory arytmetyczne , którymi dysponujemy, to operatory dodawan ia, odejmo wania , mnożenia i dzielenia. Reprezentowane są one odpow iednio przez symbole +, - , * oraz l . Sposó b ich działa nia jest dokładn ie taki, jakiego moglibyśmy s ię spodziewać, z wyjątkiem operatora dzielenia, który ma pewne odchylenia od normy , kiedy ma do czynienia ze zm ien nym i całkowitymi lub s tałymi, o czym s ię niebawem przeko namy . Przy użyc iu tych operato rów możemy pisać instrukcje pod obne do po niższej:
placaNet t o
=
godziny * stawk a - potracenia :
Wyrażenie to najpierw p omnoży wartości zmiennych godzi ny i stawka , a n a s tęp n i e od ilo czynu odejmie wartość zmiennej potra ceni a. Operacje mnożenia i dzielenia, jak można się spodziewać, wykonywa ne są przed dodawa niem i odejmowaniem. Na temat kolejności wyko nywania poszczególnych operatorów w wyrażeni ach będziemy jeszcze mówić w dalszej części tego rozdziału . Wyn ik całego działania godzi ny * st awka - potraceni a zostanie zapisany w zmiennej pl acaNetto.
Znak minusa, u żyty w ostat niej instrukcji , ma dwa operandy - odejm uje on wartość swo jego prawego operan du od wartości lewego. Nazywa się to operacją dwój kową, gdyż w grę wchodzą dwie wartości . Znak min usa może być także używany tylko z jednym operandem w celu zmiany znak u wartości, do której został zastosowany. W takim przypadku nazywa s i ę on jednoargumentowym znakiem minus. Po niższe p rzykła dy i l ustrują u życ i e operatora -:
int a =
o:
i nt b = -5: a = - b; II Zmienia znak operandu.
W powyższym przykładzie zmiennej a zostanie przypisana mentowy znak minus zmienia znak wartości operandu b. Zauważ, że
wartość
+5,
p o ni eważ
jednoargu
przypisywanie nie jest tym samym co równania znane nam z lekcj i algebry w szkole Jego celem jest określenie czynności do wyko nania, a nie proste stwierdzenie faktu. Wyraże nie po prawej stron ie operatora przypisania j est obliczane i wynik zostaje zapisany w l va l ue - zazwyczaj jest to zmienna , która znajduje się po lewej stronie . śred n i ej .
Spójrzmy na następuj ąc e
wyrażenie :
96
Visual C++ 2005. Od podstaw liczba = liczba
+
1;
Oznacza ono "dodaj l do bieżącej wartości przechowywanej w zmiennej l i czba, a następnie zapisz rezultat w tej samej zmiennej l i ezba". Jako normalne wyrażenie algebraiczne pozba wione byłoby ono sensu.
~ Ćwiczenie podstawowych działań arytmetycznych Podstawowe operacje arytmetyczne prze ćwiczymy sobie , obliczając , ile standardowych rolek tapety potrzeba nam do wytapetowania pokoju. Program wykonujący takie obliczenia przed stawiony jest na poni ższym listingu: II Cw2_05.cpp
II Oblicza nie liczby rolek po trzebnyc h do wytapetowa nia p okoju.
#include using std; ;cout;
using std : .ci n:
using st d: :endl;
int main() {
double height = 0.0. width double peri met er = O.O;
~
0.0. length
~
0.0;
II Wym iary pokoju.
II Obwód po koju.
const double rol lwidth ~ 53.0 ; const do uble rolllength ~ 10 .0*100.0:
II Szerokość standardowej rolki. II Długoś ć standardow ej rolki.
int st rips_per_roll = O; i nt strips_reqd = O: i nt nro11 s = O:
II Liczba pasków w rołce. II Liczba po trzebnych pasków. II Całko wita liczba rolek.
cout « endl « " Wpro wa d ź cin » height ;
II Przejście do nowego wiersza. wys o kość
pokoju w centymet rach: ".
cout «endl « " W p r owa d ź dł u g o ś ć i ci n » length » width:
II Przejś cie do nowego wiersza . s z e ro k o ś ć
st ri ps_per_roll = rolllength / height : perimeter = 2.0*(lengt h + widt h) ; strips_reqd = perimeter / roll wi dth :
w centymet rach:
u •
II Sprawdzanie liczby pas ków w rolce. II Obliczanie obwodu po koju. II Obliczanie ca łkowit ej liczby II potrzebnych pas ków tap ety. II Oblicza nie liczby rolek.
cout « endl « "Do wyt apetowani a tego pokoju potrzebujesz " « nrol l s « " rolek tapety . " « endl : return O:
Rozdział2.
• Dane. zmienne i działania arytmetyczne
97
Jeśli
nie je ste ś mistrzem klawiatury, to prawdopodobnie podczas pierwszej kompilacji otrzy masz kilka komunikatów o błędach. Po zlikwidowaniu literówek wszystko będzie działało bez zarzutów. Kompilator zgłosi także kilka o strzeżeń , ale nie przejmuj się nimi - upewnia się tylko, że wiemy, co robimy. Powód pojawiania się komunikatu o błędzie za chw il ę wyjaśnię .
Jak to działa Jedną
z rzeczy wyj aśn ij my sobie już na wstępie - nie b iorę odpowiedzialności za ewentualne braki tapety po wyliczeniach za pomocą tego programu! Jak si ę przekonasz, wszystkie błędy w obliczaniu liczby rolek spowodowane są sposobem działania C++ oraz odpadami , których nie da się uniknąć podczas przyklejania tapety - zazwyczaj 50 procent! Instrukcje z powyższego listingu przejrzymy sobie wiersz po wiersz u, zatrzymując się na chwi lę przy bardziej inte resuj ącyc h , nowych lub nawet ekscytujących właściwościach . Instruk cje pojawiające się przed rozpoczęciem funkcji ma in( ) są nam już bardzo dobrze znane, a więc ich tłumaczenie pomijam. Na początek warto powiedzie ć kilka słów na temat układu programu. Po pierwsze, instrukcje zawarte w ciele funkcji mai n() są wcięte , dzięki czemu łatw iej jest ocenić jego rozmiar. Po drugie, różne grupy instrukcji są od siebie oddzie lane pustym wierszem w celu zaznaczenia, że stanow ią grupy spełniające jakieś okre ślone funkcje. Wcinanie instrukcji jest podstawową techniką tworzenia układu kodu programów w C++. Jak się przekonasz, technika ta jest stoso wana w celu wizualnego wyróżnien ia logicznych bloków programu.
Modyfikator const Na samym początku ciała funkcji mai n() znajduje się blok deklaracji zmiennych używanych w programie . Instrukcje te s ą nam j uż bardzo dobrze znane, z wyjątkiem dwóch, które zawie rają pewne nowe właściwo ści : cons t daubl e ro11 width = 53.O: II Szero koś ć s tandardowej rolki. const daubl e ro11 1engt h = 10.0*100. O: II Długoś ć standa rdowej rolki). Każ da z nich rozpoczyna się od nowego s łowa kluczowego canst . Jest to modyfikator typu , który informuje, że zmienne nie tylko s ą typu daubl e, ale również są stałymi. Ze względu na fakt, że poi nformowali śmy komp ilator, że są to stałe, będzie on spraw dzał, czy któraś z in strukcji nie próbuje zmienić ich wartości . Je ś li tak , zgło si kom unikat o błędz ie . Zmienna zadeklarowana jako canst nie je st typu l val ue, a więc nie może występować po lewej stronie operatora przypisania. Możn a
to sp rawdz i ć , dodając w dowolnym miejscu po deklaracj i zmiennej ral l widt h wyrażenie podobne do tego p o n i żej : ra11wi dth
=
O:
Po dodani u tego kodu prog ram u nie b ę d z i e ' e r r o r C3 8 92 : ' r o l l wi d t h '
można skompilować,
a kompi lator
: you ca n n ot a ssig n to a v ariable t ha t
zgłosi błąd
i s c on s t " .
98
ViSUiII C++ 2005. Od podstaw w programie za pomocą sło wa kluczowego const je st bardzo gdy mamy zamiar używ ać ich wielokrotnie. Jednym z powodów, dla których lepiej je st deklarować stał e , niż u żywać c ałej masy literałów , j est fakt, że ich przezna czenie m o ż e nie b yć wystarczająco oczywi ste. Na przykład w a rtość 42 może o d no s ić się do dłu go ści ży c ia, do wsze ch świat a lub do c ze g oś jeszc ze innego, ale użycie st ał ej zmi ennej o nazw ie moj Wi ek o warto ś ci 42 wszystk o wyj aśnia . Drugim pow odem jest fakt , że j eśli zajdzie potrz eba zmienienia wartośc i takiej zmi enn ej, to wystarczy z m ie nić j ej defin i cj ę w pliku źró dłowym , a dok onane zmi any będ ą automatycznie widoczne w całym programie . Techniki tej
Defini owanie
stały ch używanych
u żyte czn e , z właszcza
b ęd ziem y używ a ć doś ć c zęsto.
Wyrażenia
wdeliniciach stałych
S tała
zm ienna rol l ength jest inicjalizow ana za p omoc ą wyrażenia arytmetyczn ego (lO. 0* 100. O). D zi ęki m ożl iwości użyci a wyrażeń aryt metycznych do inicjalizowa nia sta ły ch zmien nych nie musim y samod zielnie o b l i czać ich warto ści . Ponadto mog ą one by ć o wiele łatw iej sze do zrozumienia, tak jak w tym przypadku - wyrażeni e 10m razy 1OOcm jest o wiele j aśni ej sze , niż gdy byś my napi sal i po prostu 1000. Kompilator dokładn i e obl iczy w art o ści stałych . Natom iast gdyby śmy zro bili to sami, to - w za leżnośc i od naszych możliwo ści matema tycznych - istni eje pewien s topień ryzyk a wy stąpien i a pom yłki . Do inicjalizacji zmiennej można użyć dowolnego wyrażenia, włącznie z obiektami const , które Tak wi ęc je żeli j est to przydatne w naszym programi e, powierzchni ę stan dardo wej ro lki tapety m o żem y z adeklarować na stępuj ąc o:
już definiowali śmy.
~s t dou ble rolla rea = rol lwldth*rolllength ;
---~-------------------
Instrukcj a ta musi zostać umieszczona po deklaracji dwóch użytych w niej zmi ennych, ponie wszystkie zmienne pojawi aj ąc e się w wyrażen i u ini cj alizuj ącym stałą zmi enn ą muszą być wcześ niej przedstawione kompilatorowi. w aż
Wprowadzanie danych IJO programu Po deklaracji kilku zmi ennych typu i nt eqer następne cztery instrukcje danych wprowadzan ych za pom ocą klawi atury :
cout « end l « "W p rowadź ci n » helght;
cin
»
pokoju w centymetrach : ". II Przejście do nowego wiersza.
" Wpr owadź d ł ugo ś ć
l engt h
przyjm owani e
II Przejśc ie do nowego wiersza . wysoko ś ć
cout « end l «
ob sługuj ą
»
i
s z ero k ość
w centymetrac h. ".
widt h;
Najpierw wysłali śmy tekst na wyjście, w którym poprosiliśmy o podanie wym aganych danych , a następn i e wczyt ali śm y te dane za p om o cą ci n, który j est standardowy m strum ien iem wej śc iowy m. Jako pierwsz ą pobrali śmy wys oko ś ć pok oju , a następnie jego długo ść i s zerokoś ć. W prog ramie skierowanym do użytku dodaliby śmy j eszcze kontrolę poprawn o ś ci danych oraz sprawdze nie, czy maj ą one se ns, ale do tego mam y j eszcze zbyt mało wiedzy!
Rozdział 2.
• Dane. zmienne i działania arytmetyczne
99
Obliczanie wyniku Liczbę
rolek tapety potrzebną do wytapetowania pokoju o podanych wymiarach obliczamy za instrukcji:
pomocą czterech
str ips_pe r_roll ~ roll lengt h / height ; perimete r ~ 2.0* (lengt h + width ): stri ps_reqd = perimeter / rol lwidth: nrol l s = st rips reqd / stri ps per rol l :
II Sprawdzanie liczby p ask ów w rolce. II Obliczanie obwodu p okoju. II Obliczani e ca łkowi tej liczby II potrzebnych p ask ów tapety . II Obliczanie liczby rolek.
Pierwsza instrukcja oblicza liczbę pasków tapety o długości odpowiadaj ącej wysoko ści pokoju , ze standardowej rolki, dzieląc długość rolki przez wysokość pokoju. A zatem jeżeli pokój ma 2,44 m wysoko ści , to 1000 dzielimy przez 244 , co daje nam wynik w przybli żeniu 4,09 . Jest tutaj jednak pewna rzecz, o której należy pamiętać . Zmienna prze chowująca wynik - str i ps-per -roll - została zadeklarowana jako typ i nt , a wi ęc może przechowywać tylko liczby całkowite. W wyniku tego wszystkie liczby z ułamkiem zostaną zaokrąglone do najbliższej liczby całkowitej , w tym przypadku do 4, i to właśnie ta wartość jest przechowywana w zmiennej . Jest to tak naprawdę taki wynik , jakiego byśmy tutaj chcieli, gdyż mimo że kawałki tapety można powklejać pod oknem lub nad drzwiami, to jednak przy obli czaniu się je pomija.
jaką możemy otrzymać
Konwersj a jednego typu na inny nazywa się rzutowaniem. W naszym przypadku jest to rzutowanie niejawne, gdyż w kodzie nie jest wyraźnie zaznaczone, ż e operacja taka jest wymagana - kompilator musi taką decyzję podjąć samodzielnie. Dwa ostrzeżenia , które otrzymaliśmy podczas kompilacji, informują nas o tym , że podczas konwersji typów mogą zostać utracone pewne dane. Podczas u żywania mechanizmu niejawnego rzutowania trzeba zawsze uważać. Kompilator nie zawsze zgłasza ostrzeżenie w takich przypadkach, a przypisując wartość jednego typu do zmiennej , której typ ma mniejszy zbiór możliwych do przechowywania danych, zawsze tra cimy jakąś ich część . Jeśli z mechanizmu rzutowania niejawnego skorzystamy w programie przypadkowo , to może to być trudnym do odnalezienia błędem. Jeśli nie mo żna takiego przypisania uniknąć, to można poinformow ać o tym kompilator w sposób jawny w celu pokazania, że nie jest to przypadek. Dokonujemy tego za pomocą rzutowania jawnego wartości znajdującej się po prawej stronie przypisania na typ i nt . Dzięki temu nasze wyrażenie wyglądałoby następująco:
stri psper ron
=
st atic_cast(ro l llengt h / height) ; II Oh licz licz b ę paskó w II w rolce.
stat i C_ cast z
wyrażeniem
w nawiasie po prawej stronie jawnie informuje kompilator, chcemy przekonwertować na typ i nt. Mimo że nadal tracimy jej część ułamkową, to kompilator zakłada, że wiemy, co robimy, i nie zgłosi ostrzeżenia. Więcej na temat stati c_cast<>() i innych typów rzutowania jawnego dowiemy się z dalszej części że wartość wyrażenia
rozdziału.
Zwróć uwagę
na sposób obliczania obwodu pokoju w następnej instrukcji. W celu pomnożenia sumy długości i szerokości przez dwa operację dodawania umieściliśmy w nawiasie. Zapew niamy w ten sposób, że dodawanie zostanie wykonane na początku , a następnie wynik zostanie
100
Visual C++ 2005. Od podstaw pomnożony
przez 2.0, dz ięki czemu otrzymamy właściwą wartość obwodu. Nawiasy są potrzebne, gdyż wyrażenia w nich zawarte obliczane są zawsze na początku. Jeśli w nawiasach znajdują się zagnieżdżone nawiasy, to obliczane są one w kolejności od najbardziej wewnętrz nego do najbardziej zewnętrznego . Trzecia instrukcja, obliczająca w ymaganą do pokrycia pokoju liczbę pasków tapety, jest podobna w działaniu do pierwszej. Wynik je st zaokrąglony do najbliższej liczby całkowitej, ponieważ ma być przechowywany w zmiennej całkowitej - st ri psJ eqd. Nie jest to d okładnie to, czego byśmy chcieli . Najlepiej byłoby , aby wartoś ć tę z aokrąglić, ale tego nie potrafimy jeszcze robić . Możesz do tego wróci ć i poprawić to po przeczytaniu następnego rozdziału . Ostatnie wyrażenie arytmetyczne oblic za liczbę potrzebnych rolek, dzieląc liczbę potrzeb nych pasków (i nteger) przez liczbę pasków w rolce (także i nt eger). Jako że dzielimy przez siebie dwie liczby całkowite, wynik także musi być całkowity , a reszta z dzielenia odrzucona . Musielibyśmy tak zrobić, nawet gdyby zmienna nro11 s była typu zmiennopozycyjnego. War tość całkowita będąca rezultatem wyraż enia zostałaby przekonwertowana na typ zmienno pozycyjny przed zapisaniem jej do zmiennej nro11s. Otrzymany wynik jest dokładnie taki sam, jak gdybyśmy zaokrąglili liczbę zmiennopozycyjnądo najbliższej liczby całkowitej . A le to nie jest to, czego my chcemy, awięc jeśli chcemy tego użyć , to musimy to poprawić .
Wyświetlanie Wyniki
wyniku obliczeń są wyświetlane
za
pomocą następującej
instrukcji :
cout « endl « "Do wyt apet owani a tego pokoj u pot rzebujesz " «
«
nrol ls
«
"
rolek tapety . "
endl :
Jest to prosta instrukcja wyjściowa, którą podzieliliśmy na trzy wiersze. Najpierw wysyła znak nowego wiersza, następnie łańcuch znaków : "Do wytapetowania tego pokoju potrzebujes z", potem wstawiona zostaje wartość zmiennej nro11s, a na koniec łańcuch "rolek tapety". Jak wi dać , instrukcje wyjścia w C++ są bardzo proste. Program ret urn
kończy się
po wykonaniu
poniższej
instrukcji:
o:
Wartość zero jest wartością zwracaną i w tym przypadku zostaje ona zwrócona do systemu operacyjnego. Więcej na temat wartości zwracanych dowiesz się w rozdziale 5.
Obliczanie reszty W poprzednim przykładzie zauważyliśmy, że w wyniku dzielenia dwóch liczb całkowitych otrzymuje się wynik z usuniętą resztą z dzielenia. W ten sposób, dzieląc 11 przez 4, otrzy mamy wynik 2. Jako że reszta z dzielenia może być czasami bardzo ważna (kiedy na przykład dzielimy ciastka pomiędzy dzieci), w C++ dostępny jest specjalny operator %. Przy jego użyciu możemy napisać następujące instrukcje, które rozwiążą nasz problem z ciasteczkami:
Rozdział 2.
• Dane, zmienne i działania arytmetyczne
101
int reszta = O. ci ast ka = 19. dZleci = 5: reszt a = ciast ka %dzieci ; Zmienna reszta będzie miała wartość 4 - tyle wynosi reszta z dzielenia 19 przez 5. Aby obli czyć , ile ciastek dostanie każde dziecko, należy posłużyć się zwy kł ym operatorem dzielenia , jak poni żej :
each = ciastka I dzieci:
Modyfikowanie zmiennei Często
zachodzi konieczność zmodyfikowania istniejącej już w artośc i zmiennej (np. trzeba ją lub podwoić) . Aby zwiększyć zmienną o nazwie cou nt, możemy użyć n astępuj ącej instrukcji :
zw i ększyć
count = count + 5; Dodaje ona po prostu 5 do bieżącej wartości przechowy wanej w zmiennej count i wynik zapi suje z powrotem w tej zmiennej . Jeśli więc zmienna count po c z ątkowo miała w arto ść 10, to teraz ma już 15. To samo
wyrażenie możemy także zapisać
w krótszy sposób:
count += 5: Instrukcja ta mówi: .P obierz warto ś ć zmiennej count, dodaj do niej 5 i wynik zapisz z powro tem do tej zmiennej ". W podobny sposób możemy u żywać również innych oper atorów. Na przykł ad :
count *= 5: Instrukcja ta pomnoży bieżącą wartość zmiennej count przez 5 i wynik zapisze z powrotem do tej zmiennej . Ogólnie rzecz bi orąc , instrukcje można pisać według następującego schematu:
1s op= ps; W schemacie tym op oznacza jeden z poniżs zy ch operatorów:
*
+
«
»
&
>
Pi ęć
│
pierwszych z powyższych operatorów już znamy , a pozo stałe (które są operatorami prze i logicznymi) poznamy jeszcze w tym rozdziale. l s oznacza wszystko to, co mo że pojawi ć s ię po lewej stronie instrukcji, i zazwyczaj (chociaż nie zawsze) jest nazwą zmiennej . ps oznacza wszystko , co mo że pojawi ć się po prawej stron ie instrukcji. s unięc ia
Ogólna forma instrukcji jest równoznaczna z l s = l s op (ps);
poniższą:
102
Visual C++ 2005. Od podstaw Dzięki będzie
wstawieniu ps do nawiasu prawym operandem op.
Oznacza to, ż e
wyrażenie
to zostanie obliczone jako pierwsze, a wynik
możemy napi sać taką in strukcję :
a/ = b +c : i jest ona równoznaczna z:
a = a / (b +c) :
A zatem
wartość
a zostanie podzielona przez
sumę
b i c, a wynik z powrotem zapisany do a.
Operatory inkrementacji idekrementacji Wprowadzimy teraz dwa niezwykłe operatory arytmetyczne, zwane operatorami inkremen tacji i dekrementacji. Kiedy zaczniemy na poważne posługiwać się językiem C++, stwier dzimy, że operatory te są niezwykle przydatne. Są to operatory jednoargumentowe, których używamy do zwiększania lub zmniejszania wartości zmiennych przechowujących liczby cał kowite. Zakładając na przykład, że zmienna count je st typu i nt, poni ższe trzy instrukcje są jednoznaczne: count = count + l : count
+~
l ; ++count ;
Każda z nich zwiększa wartość zmiennej caunt o jeden. Ostatnia instrukcja, w której wyko rzystany został operator inkrementacji, jest najbardziej zwięzła.
Operator inkrementacji nie tylko zmienia wartość zmiennej, do której został zastosowany, ale w wyniku jego działania także powstaje wartość. A zatem użycie operatora inkrementacji w celu zwiększenia warto ści zmiennej o jeden może wystąpić jako część bardziej skompli kowanego wyrażenia. Je żeli zwiększamy wartość zmiennej za pomocą operatora ++, jak w ++count , wewnątrz innego wyrażenia, to jej wartość zostanie najpierw zwiększona o jeden, a następnie tak zwięks zona wartość zostanie użyta w dalszych oblic zeniach. Przypuśćmy na przykład, że zmienna caunt ma wartość 5 i że zdefiniowaliśmy zmienną typu i nt o nazwie ta ta l . Napiszmy następującą instrukcję: t otal = ++count + 6; Wynikiem jej
zmiennej cou nt do 6, a więc wartość całego 12 i liczba ta zostanie zapisana jako wartość zmiennej ta t a l .
działania będzie zwiększenie wartości
wyrażenia będzie wynosiła
Do tej pory wstawialiśmy operator inkrementacji przed nazwą zmiennej . Jest to tak zwana forma przedrostkowa tego operatora. Może on również mieć formę przyrostkową, czyli znajdować s i ę po nazwie zmiennej , do której został zastosowany. W zależności od użytej formy efekt jest nieco inny . Wartość zmiennej , do której stosujemy operator inkrementacji, zostanie zwiększona tylko wtedy, gdy została ona użyta w jakimś kontekście . Cofnijmy na przykład wartość zmiennej count z powrotem do 5 i przepiszmy naszą instrukcję w następujący sposób: tot al = count ++ + 6;
Rozdział 2.•
Dane. zmieniłe i działania arytmetyczne
103
Zmiennej t ata l zosta nie przyp isana wartość 11, ponieważ wartoś ć poc zątkowa zmiennej caunt jest tutaj użyta do obliczenia warto ści wyra żenia prze d zwięks zeniem j ej o jeden . Instrukcja tajest równoznaczna z dwiema poniższymi: t ota l = count + 6; ++count : Takie nagromadzenie znaków + jak w naszym przykładzie może prowadzić do ni ep oroz u m i e ń . Og ólnie rzecz biorąc , taki spos ób stosowania operatora inkrementacji jak w poprzednim przykładz ie nie jest zbyt dobry. O wie le lep iej byłoby napi sać : total = 6 + count++: M ając inst rukcję taką jak
a++ + b lub a+++b, moż na się łatwo pogubi ć , co ma zos tać wyko nane lub co zrob i kompi lator. Obie te instrukcje oz naczają to samo, ale w tej drugiej możliwe, że mie liśmy na myśl i a + ++b, co da j uż inny wyn ik - o jeden większy n i ż poprzednie dwie . Dokładnie
takie same zasady jak do operatora inkrementacj i maj ą zastosowanie do operatora Jeżel i na przykład zmienna ca unt ma warto ść początkową 5, to po wyko dekreme ntacj i: naniu instru kcji: -- o
t otal = --count + 6: zmienna t ata l t otal
=
będzie m iał a w artość
10, nato miast instrukcja :
6 + count - -:
na 11. Oba operatory stoso wane są zazwyczaj do liczb całkow ityc h, w szcze w pętlach , o czym przekonamy się j uż w nas tępny m rozdziale. P óźni ej dowiemy s i ę, że opera tory te mogą być stosowane także do innych typów danyc h, a zwłaszcza do zmien nych przec howującyc h adresy.
ustawi
tę wartość
gó l ności
~
Operator przecinkowy
Operator przecinkowy pozwala na podanie kilku wyrażeń w miej scu , gdzie normal nie ty lko j edn o. Najł atwiej jest to zrozumieć na przy kładzie :
p oj aw ić się
II Cw2_06.cpp
II Ćw iczen ie zast osowania opera tora prz ecinka.
#incl ude usi ng st d: .cout : usi ng st d . rendl : int mai n( )
« "j est wa r t o ś ć osta t niego wy raż em a po prawej: "
« num4 :
może
104
Visual C++ 2005. Od podstaw cout
«
end l ;
ret urn O;
Jak to dziala Po skompilowaniu i uruchomieniu tego programu otrzymamy War t o ś c i ą
szeregu
wy r a ż e ń
jest
wa r t o ś ć
następujący rezultat:
osta t niego wyrazeni a po prawej ; 30
Kod ten jest bardzo prosty. Zmiennej num4 została przypisana wartość ostatniego z trzech przy Nawiasy w tym przypisaniu są konieczne. Gdybyśmy je pominęli , to pierwsze wyrażenie oddzielone przecinkiem od pozostałych miałoby postać :
pisań .
num4 = numl = l a w wyniku czego
wartość
Oczywi ś cie wyrażenia
zmiennej num4 wyniosłaby 10.
oddzielane przecinkami nie instrukcje:
mus zą b yć
przypisaniami. Równie dobrze
mogliby śmy napisać na stępujące
long num l = l , num2 = l a, num3 = 100 , num4 num4 = (++numl, ++num2, ++num3 ) ;
~
O:
Rezultatem tego przypisania będzie zwięks zen ie wartości zmiennych numl, num2 i num3 o jeden, a następnie ustawienie wartości zmiennej num4 na wartoś ć ostatniego wyrażenia, czyli l al. Przykład ten ma na celu zaprezentowanie sposobu działania operatora przecinka , ale nie jest wzorem dobrego stylu programowania.
Koleiność wykonywania obliczeń Do tej pory nie mówiłem nic na temat kolejności obliczeń wykonywanych podczas wyzna czania w artości wyrażenia. Ogólnie jest ona podobna do tej, której uczymy się w szkole na lekcjach matematyki, ale w C++ istniej e trochę więcej operatorów. Aby zrozumieć , co się z nimi dzieje, musimy przyjrzeć się dokładniej mechanizmowi języka C++ stosowanemu do określan ia tej kolejności . Mechanizm ten nazywa si ę priorytetem operatorów.
Priorytety operatorów Jest to mechanizm , który ustawia w zadanej kolejności priorytety operatorów . W wyrażeniach operatory o najwyższym priorytecie wykonywane są na początku , następnie wykonywane są operatory o najwyższym po nich priorytecie i tak dalej aż do operatorów o prioryteci e najniż szym . P oni żej znajduje się tabela priorytetów operatorów C++:
reinterp ret _cas t sizeof new delete . . .typeid .* (jednoargumentowy) ->*
lewa
* / %
lewa
+ -
lewa
«
»
lewa
< <= > >= I ~
lewa lewa
&
lewa lewa
>
lewa
&&
lewa
»
lewa
?
(operator warunkowy)
prawa prawa lewa
Tabela zawiera wiele operatorów, których jeszcze nie znamy, ale do końca książki będziemy znać je wszystkie. Umieściłem je wszystkie w tabeli , dzięki czemu w razie potrzeby zawsze będzie można do niej wrócić i sprawdzić priorytet jednego operatora w stosunku do innego . Operatory o najwyższym priorytecie znajdują się na samej górze tabeli. Operatory znajdujące się w tej samej komórce mają taki sam priorytet. Jeżeli w wyrażeniu nie ma nawiasów, to operatory o takim samym priorytecie wykonywane są w kolejności określonej przez łączność . A zatem jeżeli łączność jest lewa, to najpierw wykonywany jest operator znajdujący się po lewej stronie, przechodząc coraz dalej w prawą. Oznacza to, że wyrażenie takie jak a + b + C + d zostanie obliczone, tak jakby było zapisane (( (a +b) + c) + d ), ponieważ binarny + ma łączność lewą. Zauważ, że w przypadku operatorów posiadających zarówno formę jednoargumentową (działa z jednym operandem), jak i dwuargumentową (działa z dwoma operandami), ta pierwsza ma zawsze wyższy priorytet i dzięki temu wykonywana jest zawsze wcześniej .
106
Visual C++ 2005. Od podstaw Kolejność
wykonywania operatorów można zawsze zm ienić za pomocą nawiasów. Ze na fakt, że w C++ dostępnych jest tak wiele operatorów, czasami trudno się połapać, co ma pierwszeństwo przed czym. Dobrym pomysłem jest w takim przypadku zastosowanie nawiasów. Dodatkowym plusem takiego podejścia jest fakt, że nawiasy zwiększają czytelność kodu.
względu
Typy zmiennych irzutowanie Obliczenia w C++ mo gą być wykonywane przy użyciu w artości tego samego typu. Kiedy napiszemy wyrażenie zaw i e raj ące zmienne lub stałe różnych typów, to kompil ator dla każdej z takich operacji musi dokonać konwersji jednego z operandów, aby pasował do drugiego. Proces ten nazywa się rzutowaniem. Je żeli na przykład chcemy dodać liczbę typu doubl e do liczby typu i nteger, to liczba i ntege r najpierw zostanie przekonwertowana na typ doubl e, a dopiero potem zostanie wykonane działanie dodawania. Oczywiście sama zmienna, która zawiera rzutowaną wartość, nie jest zmieniana. Kompilator przechowa przekonwertowaną war tość w pamięci tymcza sowej i zostanie ona usunięta po zako ńc ze n i u wykonywania obliczeń . Wybór operandu, który zostanie przekonwertowany, jest uzależniony od pewnych reguł. Każde rozbija się na kilka operacji pomiędzy dwoma operandami. Na przykład wyrażenie 2*3-4+5 zostanie podzielone na następujący szereg działań: 2*3 da w rezultacie 6, 6-4 wynosi 2 i na koniec 2+5 da nam wynik 7. A zatem zasady dotyczące rzutowania operandów, tam gdzie to konieczne, muszą być zdefiniowane tylko w kwestiach dotyczących par operandów. Dla każdej pary operandów różnego typu stosowane są poniższe zasady w podanej kolejno ści. Gdy kt óraś z zasad odnosi się do określonej sytuacji to jest ona stosowana. wyrażenie
Zasady rzutowania operandów 1.
Jeśli
2.
Jeśli
3.
Jeżeli
jeden z operandów jest typu long doubl e, to drugi przekonwertowany na ten typ. jeden z operandów jest typu doubl e, to drugi na ten typ.
też
też
zostanie
zostanie przekonwertowany
jeden z operandów jest typu fl oat , to dru gi zostanie prze konwertowany na ten typ .
4. Typy char, s ig ned cha r , unsi gned cha r, short i unsig ned s hort konwertowane są
na typ i nt.
5. Typ wyliczeniowy konwertowany jest na pierwszy z typów i nt, uns i gned i nt , l ong lub uns i gned l ong, który
6.
Jeśli
7.
Jeśli
elementów wyliczenia.
jeden z operandów jest typu uns i gned l ong, to drugi konwertowany jest na ten typ .
są
8.
mo że pomieści ć liczbę
jeden operand jest typu Io nq, a drugi typu uns i gned i nt , to oba operandy konwertowane na typ unsi gned lo ng.
Jeśli
jeden z operandów jest typu l onq, to drugi konwertowany jest na ten sam typ.
Rozdział 2.•
Dane. zmienne i działania arytmetyczne
107
Na pierwszy rzut oka zasady te wydają s ię bardzo skomplikowa ne, ale ogó lna zasada j est taka, że typ o mniejszym zakresie wartości konwert uje s ię na typ o większy m zakres ie. Zwiększa to prawdopodob ieństwo , że b ędzi emy w stanie prze ch ować wynik. Dz i ałan ie tych zasad m ożem y wypróbować na hipotetyczn ym wyrażeni u . P rzypuśćmy , że mamy kilka deklaracj i zmiennych:
dou ble val ue = 31 .0;
i nt count = 16 :
flo at ma ny = 2.0f:
char num = 4:
Przypuś ćmy t akże , że
dysponujemy
p on i ż s zym
val ue = (value - count) *(count - num)!many Możemy
z niego instrukcj i.
wywnioskować ,
jakich
+
przypadkowym
wyrażenie m
arytmetycznym:
num!many:
rzu to wań
dokona komp ilator podczas wykonywania
Pierwsza operacja polega na obliczeniu wartości wy raże n ia (va l ue - count ), Zast osowanie ma tutaj re guła 2., w myśl której wartość zmiennej count zosta nie przekonwertowana na typ doubl e, a zwrócony wynik b ęd z i e tego właś n ie typu, czy li 15. O. N as tępnie
przechodzimy do obliczania wartości wyraże nia (count - num). W tym przypadku pierwsza zasada, która ma zastosowanie , to zasa da num er 4. A zatem zmie nna numzostanie prze konw ertowana z typu char na typ i nt i w wyniku otrzymamy li c zb ę całkowi tą 12.
Nas tępne
obliczanie dotyczy p owyż s zych dwóch wyników - liczby typu doubl e 15 oraz liczby 12. Tutaj zastos owanie ma reguła numer 2 - liczba 12 zostanie przekonwert owana na 12 . O, a n a stępni e zwrócony zosta nie wynik typu doubl e 180. O.
całkowi tej
Wynik ten musimy teraz pod z i eli ć przez wartość zmiennej many. Tutaj ponownie zastosowa nie ma r e guł a num er 2. W art o ś ć zmiennej many zos ta nie przekon wert owana na typ doubl e przed wygenerowaniem wyniku tego samego typu o w a rto ś c i 90. N as tępni e
ob licza na jest w arto ś ć wyraż en i a num/ many, gdzie zastosowanie ma reguł a num er 3, która powoduje powstanie wartości 2 . Of typu fl oat, będącej wynikiem konwersji zmiennej numz typu char na typ fl oa t.
Na zakończe nie wartość typu doubl e 90. Ojes t dodawana do w a rto ś c i typu fl oat 2 . Of . W tym przypadku stosujemy reguł ę 2. Po przekonwertowan iu 2 . Of na 2 .Odo zmiennej val ue zostaje zapisany wyni k 92 .O. Po tych wszystkich
wyjaś nie niac h powinn iś my mie ć już
ogó lne rozeznanie .
Rzutowanie winstrukcjach przypisania Jak j uż przekona liśmy się w p rzykład zi e Cw2_05.cpp, rzutowanie niejawne można spowodo w ać poprzez napisanie po prawej stronie przy pisa nia wyrażenia o innym typ ie n iż zmienna po lewej . Może to spowo dować zmianę wartości i utrat ę danych. Je śl i przypiszemy na przy kład w artoś ć typu f l oat lub doubl e do zmie nnej ty pu i nt lub l ong, to utracimy część uł am kow ą tych wartości (można utraci ć nawet więcej , j eż el i zmien na typu zmien nopozycyj nego przekracza zasięg wa rtoś c i prze widzianych dla typu i nteger).
108
Visual C++ 2005. Od podstaw Na
przykład
po wykonaniu
poniższego
fragmentu kodu:
int number = o;
float decimal = 2.5f ;
number = decimal ;
wartość zmiennej number będzie wynosiła 2. Zauważ literę f na końcu stałej wartości 2. 5f. Informuje ona kompilator, że jest to liczba zmiennopo zycyjna typu si ngle. Bez litery f do myślnie byłaby to liczba typu doubl e. Każda s t a ł a zawierająca czę ść dziesiętną jest typu zmiennopozycyjnego. Jeśli nie chcesz, aby była ona typu doubl e, to musisz dodać literę f. Takie samo znaczenie m iałaby tutaj wielka litera F.
Rzutowanie jawne W przypadku wyrażeń zawierających wartości różnych typów podstawowych kompilator automatycznie dokona rzutowania tam, gdzie jest ono potrzebne . Ale jeśli chcemy, to możemy także taką operację wymusić za pomocą rzutowania jawnego. W celu rzutowania wartości wyrażenia na okre ślony typ posługujemy się następującą instrukcją: static_cas t ( wyra żen i e )
Słowo kluczowe st at i c_cast oznacza, że rzutowanie je st sprawdzane w sposób statyczny, a więc podczas kompilacji programu. Po uruchomieniu programu nie będzie już sprawdzane, czy zasto sowanie rzutowania jest bezpieczne. Później , kiedy będziemy zajmować się kla sami, spotkamy się ze słowem kluczowym dynami c_cast, które powoduje, że konwersja jest sprawdzana dynamicznie, czyli podczas wykonywania programu . Istniejąjeszcze dwa rodzaje rzutowania: const _cast do usuwania stanu stało ści wyrażenia oraz re i nt erpr et _cast , które jest rzutowaniem bezwarunkowym, ale na razie nie będziemy s i ę nimi zajmować.
Efektem powyższego rzutowania statycznego jest konwersja wartości wyrażenia exp ressi on do typu podanego w nawiasach ostrych. Jako express i on mo żna wstawić cokolwiek - od pojedynczej zmiennej po złożone wyrażenie zawierające wiele zag n i eżd żo n y c h nawiasów . Poniżej
znajduje
s ię
szczególny przypadek
użycia
double value1 = 10.5: dou ble value2 = 15.5: i nt whole number = stat ic cast (val uel )
+
sta t i c_cast<>( ):
sta tl c cast(va l ue2);
Wartością inicjalizującą zmiennej whole_number jest suma całkowitych czę ści warto ści zmien nych val ue l i val ue2, a więc są one przekonwertowane w sposób jawny na typ i nt . Dzięki temu zmienna ta przyjmie wartość 25. Rzutowanie nie wpływa na warto ści przechowywane w zmiennych val ue1 i va l ue2, które nadal będą wynosić odpowiednio 10.5 i 15.5. Wartości 10 i 15 są tylko tymczasowo przechowywane do użycia w obliczeniach , a po ich zakończeniu usuwane z pamięci . Mimo że każde z tych rzutowań powoduje utratę danych, kompilator zakła da, że wiemy, co robimy, skoro stosujemy rzutowanie jawne.
Poza tym, jak już pi sał em w przykładzie Cw2_05.cpp odno szącym się do przypisań z różnymi typami, zawsze można poinformować, że wiemy, iż rzutowanie jest konieczne, poprzez zrobie nie go jawnym:
Rozdział 2.•
Dane. zmienne i działania arytmetyczne
109
st r tpsperj-ol l = stat ic_castCro111ength I hei qht ) : IISprawdź liczbę paskó w II w rolce.
Rzutowanie jawne można stosować z dowolnych wartości numerycznych na dowolne inne wartości numeryczne, ale trzeba zawsze być świadomym możliwości utraty informacji . Jeśli na p rzykład dokonamy rzutowania wartości typu fl oat lub doub l e na typ l onq, to w wyniku konwersji utracimy część ułamkową liczby, a co za tym idzie, jeżeli liczba była mniejsza od l , to otrzymamy w wyniku O. Przy rzutowaniu z typu doubl e na typ f lo at strac imy na precyzji , ponieważ zmienna typu fl oat ma precyzję tylko siedrniocyfrową, a doubl e aż piętnastocyfrową. Nawet rzutowanie pomiędzy typami i nteger niesie ze sobą ryzyko utraty danych, w zależności od zastosowanych wartości. Na przykład wartość typu l ong może być zbyt duża, aby można ją było przechowywać w zmiennej typu short , a więc rzutowanie z typu l ong na short może prowadzić do utraty danych. Ogólnie rzecz biorąc, w miarę możliwości powinno się unikać rzutowania. Jeżeli okaże się , w swoim programie potrzebujesz wielu rzutowań, to prawdopodobnie został on źle zapro jektowany. Należy w takim przypadku przejrzeć jeszcze raz jego strukturę oraz sposoby wybierania typów danych i w miarę możliwości zlikwidować lub przynajmniej zredukować że
liczbę rzutowań.
Rzutowanie wstarym stylu Przed wprowadzeniem do C++ rzutowania stat i c_cast <>() (i pozostałych typów rzutowania: const_cast-c-r ), dynami c_cast <>( ) oraz rei nterpret _cast<>( ), o których będziemy jeszcze mówić) rzutowanie
jawne wyniku
wyrażenia na
inny typ
było
zapisywane
następująco:
Ctyp_do_kt órego_ma_nastąplć_ko n wersJaJwyrażen ie
Wynik liczbę
wy raż e n i a jest rzutowany na typ podany w nawiasie. Na pasków w rolce moglibyśmy zapisać następująco :
str i ps per roll = Ci nt )( ro11 1ength I heiqht ) :
II Oblicz
przykład instrukcję obliczającą
li czb ę pasków w
rolce.
Istnieją cztery typy rzutowania i każdego z nich można dokonać za pomocą starej składni. Ze względu na to kod, w którym wykorzystane jest rzutowanie starego typu, jest bardziej podatny na błędy - nie zawsze jest jasne, co mieli śmy na myśli, i możemy otrzymać inny wynik, niż się spodziewaliśmy. Mimo że rzutowanie w starym stylu jest jeszcze dość często spotykane (nadal jest częściąjęzyka i z powodów historycznych można j e spotkać w bibliotece MFC), to gorąco zachęcam do stosowania rzutowania tylko w nowym stylu .
Operatory bitowe Operatory bitowe traktują operandy jako szer eg bitów, a nie wartości numeryczne. Można ich używać tylko z typami całkowitymi, a więc : sho rt, i nt, l ong, si gned char i char oraz wer sjami tych typów bez znaku. Operatory bitowe są użyteczne w programowaniu sprzętu, gdzie status urządzenia reprezentowany jest przez szereg indywidualnych znaczników (to znaczy, że każdy bit w bajcie może określać status innego aspektu urządzenia), lub w każdej innej
110
Visual C++ 2005. Od podstaw sytu acji, w której zachodzi potrzeba upakowania zestawu znaczników typu włączon y- wyłą czony w jednej zmiennej. Sposób ich d z iałania pozn amy przy okazji s zczegółow ego om awia nia operacji wejścia-wyjścia, gdzie pojedyncze bity używ ane są do kontrolowania ró żn ych opcj i ob sługi dan ych . Istni eje
s z eść
operatorów bitowych: bitow y Ok
& bitowy AND
>
- bitow y NOT
» prze sun i ęc ie w prawo
Poniżej w yj aśniam
spos ób
A
bitowy
wyłączny
aR
« przesuni ęc i e w lewo
działani a każdego
z nich.
Opera10r bilowy AND Bito wy operator AND (&) jest operatorem binarnym, który łączy odpowiadające sobie bity w jego ope randach w okre ślony sposó b. Gdy oba bity maj ą w artość I, to zwracana jest warto ś ć l, w przeciwnym przypadku zwracana w arto ś ć to O. Efekt działania operatora binarnego cz ęs to pokazywany jest za pomoc ą tak zw anej tabeli prawdy. Pokazuje ona, jaki byłby wynik przy użyciu różnych kombinacji operandów. Tab ela prawdy dla operatora &przedstawia s ię następująco: Bitowy AND
O
O
o
1
O
O
Wynikiem łączeni a każdej kombinacji wiersza i kolumny za p omocą operatora &je st pod ana w punkcie ich przecięcia . Prze śl ed źmy na przykładzie , jak to d ziała:
char let t erl ~ 'A' , lett er2 = ' Z' . resul t result ~ let t erl &let t er2: Aby
~
wartość
O:
zobaczyć ,
co si ę dzieje, musimy spoj rzeć na wzory bitowe. Literom "A" i ,;Z" odpowia szesnastkowe Ox4] i Ox5 A (Kody ASCII pod ane zo stały w dod atku B). Sposób operatora bitowego AND na te dwie wartoś c i poka zany zo stał na rysunku 2.8.
daj ą wartości działania Mo żem y
to potwierdzić , sprawdzając , jak odpowiadaj ące sobie bity łączą s ię za pom ocą & w tabel i prawdy. Po przypisaniu otr zymamy wyn ik Ox40, co odpowiada znakowi @. na fakt , że operator & daje w wyniku zero, gd y ob a bit y m aj ą wartość zerow ą, go używać do ustawiania w zmi ennej niechcianych bitów na zero. Dokonujemy tego, tw orząc tak zwaną maskę i łącząc ją z oryginalną zmi enn ą za pomo cą operatora &. M askę tworzym y poprzez o kreś l e n i e wartości jeden, tam gd zie chcemy iachować bit , i zero tam , gdzie chcemy bit u stawi ć na zero . W wyniku łączenia maski z inną warto ści ą całkowitą otrzy mamy bity zerow e w miejscach , gdzie u stawili śmy bity zerowe w masce, oraz takie same war to ś ci jak oryginalny bit w zmiennej , tam gdz ie w masce jest bit o wartości jeden. Przypuśćmy,
Ze
w zględu
możn a
~
Rozdział 2.
• Dane. zmienne i działania arytmetyczne
111
Rysunek 2.8
letter1 : Ox41
letter2 : ox5A
result: ox40
o
1
o
o
o o o
1
1
1
i& l& i& i& &i i& &i &i !o ! !o ! !!o ! !o i i i i i ii l J l JT rr J o o o o o 1
01
o
1
r
że
mamy z m ie nn ą l etter typu char , z której chcemy u sun ąć cztery bity wysokie i zach ować cztery bity niskie. M ożn a tego łatwo d okona ć , tworz ąc m a s k ę OxOF i łącz ąc j ą z wart o śc i ą zmiennej l etter przy uży ciu operatora &:
letter
=
l et t er &OxDF :
Lub bardziej zw i ęź le :
letter &= OxOF : Je żeli w arto ść
zmiennej char wyno s iła Ox4l , to po wykonaniu p owyż szy ch instrukcji otrzy mamy wynik OxO l. Operacja ta zo st ał a przedstawi ona na rysunku 2.9. Bity zerowe w masce powoduj ą, ż e odp owi adające im bity w zmiennej l etter zostają usta wione na zero, a bity o wartośc i jeden w masce powoduj ą, że od p owiad aj ące im bity w zmien nej zos tają zac howane w swojej oryg ina lnej postaci.
W podobny sposób za pom ocą maski OxfD możemy za c hować cztery bity wysokie i wyzerować cztery bity niskie. A zatem w wyniku poni żs zej instrukcji w arto ś ć zmiennej l etter zmieni się z Ox4l na Ox40:
letter &= OxFO:
Bitowy operator sumy logicznej Bitowy operator sumy logicznej OR ( I) , czasami nazyw any a lternatyw ą bitow ą, wiąże odpo wi ad aj ąc e sobie bity w tak i spos ób, że w wyniku otrzymuj emy w arto ść j eden, j e ż eli jeden z operandów ma warto ś ć je den, i zero, je żel i oba operandy m aj ą w artość zero. Tabela prawdy dla tego operatora przedstawia się następująco: Bitowy OR
O
O
o
l
112
Visual C++ 2005. Od podstaw
Rysunek 2.9
letter: ox41
ma sk:OxOf
result: oxoi
o
1
o
o
i& &ff& l& '!o !o Jo !o ffff - - - -
Jo J'l r o o o
o
00
ff f
1
t
& & & &
! !! ! ff ff J! ! 1
1
1
1
.o
o
o
1
Przećwic zmy na pr zykładzie , jak można ustawić poszczególne znaczniki upakowane w zmien nej typu c ałk owitego . Przypuśćmy , że mamy zmienną o nazwie styl e typu sho rt , która za wiera 16 jednobitowych znaczników. Załóżmy, że chcemy u stawi ć poszczeg ólne znaczniki w tej zmienn ej . Jednym sposobem jest zdefiniowanie warto ś ci , które można następnie powią zać z operatorem OR w celu włączenia określonych bitów . Aby u stawi ć ostatni bit po prawej, m ożn a zd e fi n i ow ać:
sho rt vredraw Aby
u stawi ć
~
OxO l;
drugi bit od prawej , zmienną hredraw można zd e fin i o wać w
sho rt hred raw
=
następujący
sposób :
Ox02;
A zatem aby w zmiennej sty le u stawić dwa ostatnie bity po prawej na l,
można posłużyć się
następuj ąc ą i nst ru kcją:
style
~
hredraw I vredraw;
Wynik tej instruk cji pokazany jest na rysunku 2.10 . Jako
że
operacj a przy
u życiu
wartość jeden, łączenie
bity
operatora OR daje wynik jeden, jeżel i któryś z dwóch bitów ma dwóch zmiennych za pomocą tego operatora daje wynik , w którym oba
są wł ąc zone .
C zęs to
zostać
zachodzi potrzeba ustawienia znaczników w zmiennej bez zmiany innych, które mogły ustawione już gdzie ś indziej. Można tego łatwo dokonać za pomoc ą poniższej instrukcji;
style
I~
hred raw I vredraw ;
Instrukcja ta ustawi dwa ostatnie (po prawej stronie) bity zmiennej sty l e na l , a pozo stałe pozostawi bez zmian.
Rozdział 2.
hredraw:oxoz
• Dane. zmienne i działania arytmetyczne
o o o o
00 o o ·
o o o o
on on on on
on on onon
on on on on
rrlr
on on aR on
l l l l i i i i = : ;: = =
l l l l i i i i = = = ::;:
lo lo lo lo i i i
lo lo lo l1 i i i i = = ::;: =
IIi l l l l l
., o o o o
vredraw:OxOl
ł
style:Ox03
!ł !
o o o o
o o o o
!.! !! o o o o
r I'rII
o o o o
113
o o 1 o
II r l !o !o ł1 !1
Rvsunek 2.10
BitoWY operator różnicy symetrycznej Bitowy operator różni cy symetrycznej (ang. Exclusive DR; A) ma podobne dzi ałani e do opera tora alternatywy, ale daje wynik zero, gdy oba operandy m ają w artość jeden. W zwi ązku z tym j ego tabela prawdy przed stawia s i ę następuj ąco: Bitow yEOR
O
O
O O
Spój rzmy na wynik wykonania poni ższej instrukcji przy nych co w przypadku operat ora AND: result = letter1
A
użyci u
tych samych
warto ści
zmien
l et t er2;
Operacj ę tę możemy przedstawić następuj ąco :
l et t er1 01 00 0001 let t er2 0101 lala
Wynik
dział an i a
operatora EOR jest n a st ępuj ący :
resul t 0001 101 1 Wartość
zmiennej result zostaje ustawi ona na Oxlb lub -
w zapisie
d zie siętnym
-
na 27.
Operator ma do ść zaskakuj ąc ą właściwoś ć . Przypuśćmy , że mamy dwie zmienne znakowe: fi rst o warto śc i A i l ast o warto ś ci Z, którym odpowiadają w arto ści binarne 0100 0001 i 0101 lala. W wyniku poniż szych instruk cj i: A
114
Visual C++ 2005. Od podslaw f i rst l ast : I/Wynik fi rslto 00011011. l ast A ~ fi rst : II Wynik last to 0100 0001.
f i rst l ast : II Wynik first to 0101 1010.
A=
A=
zmienne te zamienią się wartościami , nie korzystając z żadnej Działa to ze wszystkimi wartościami typu całkowitego .