background image

Użycie zmiennych 

  

background image

Przegląd zagadnień 

 

 

Podczas definicji algorytmu było wspomniane pojęcie dane, czyli coś co 
przetwarza, na czym pracuje algorytm. Dane w przypadku programu 
komputerowego nazywamy zmiennymi. Zmienną w pewnym uproszczeniu 
można zdefiniować jako pewien obszar pamięci (ciąg bitów), do którego można 
się odwołać przy pomocy pewnej nazwy, nadanej temu obszarowi przez 
programistę. Przy pomocy nazwy zmiennej, lub krócej zmiennej, możemy 
"manipulować" (zmieniać, pobierać wartość) bitami obszaru pamięci 
reprezentowanym przez zmienną. Przy tych "manipulacjach" wykorzystujemy 
pewne instrukcje zwane operatorami. 

Po skończeniu tego modułu studenci powinni: 

 

Potrafić definiować zmienne. 

 

Znać podstawowe operatory w języku C#. 

 

background image

 Definicja zmiennej 

 

 

Definiując zmienną oprócz jej nazwy, czyli identyfikatora zmiennej, musimy 
podać jej typ

1

. Typ określa: 

 

liczbę bajtów zajmowanych przez zmienną, 

 

sposób interpretacji bitów zmiennej, 

czyli można powiedzieć, że typ definiuje zbiór wartości, jakie może 
przyjmować zmienna. Typ również określa zbiór operacji, jakie możemy 
przeprowadzać na zmiennej. 

W tej części modułu studenci poznają: 

 

Dostępne typy w języku C#. 

 

Sposób definicji zmiennej. 

 

Dopuszczalne identyfikatory. 

oraz nauczą się 

 

Nadać zmiennej żądaną wartość. 

 

Wypisać wartość zmiennej na ekranie. 

 

Kopiować wartość zmiennej do zmiennej innego typu. 

                                                        

1

 W wersji C# 3.0 zostają wprowadzone typy domniemane, gdzie nie podajemy 

nazwy typu w sposób jawny, ale kompilator na podstawie jak inicjalizujemy 
zmienną jest w stanie określić jej typ. 

background image

Wspólny system plików 

 

 

Wspólny system plików (Common Type System - CTS) - określa w jaki sposób 
środowisko uruchomieniowe (CLR) definiuje i używa typy oraz jak nimi 
zarządza. Dostarcza również zorientowany obiektowo model oraz definiuje 
reguły, które muszą być stosowane we wszystkich językach programowania, 
których używane są do tworzenia oprogramowania na platformę .NET. Reguły 
te pozwalają częściom programu napisanych w różnych językach 
współpracować ze sobą. Mówiąc prościej, nasz program napisany w C#, może 
używać typów zdefiniowanych np. w bibliotece napisanej w Visual Basic-u. 

Wszystkie typy w języku C#, możemy podzielić na dwie rozłączne kategorie: 

 

Typy wartości 

 

Typy referencyjne 

Obie kategorie typów zostaną dokładnie omówione w dalszej części rozdziału. 

Uwaga: 
W języku C# wszystkie typy dziedziczą po klasie Object. Pojęcie 
dziedziczenia jest dokładnie omówione w kursie "Programowanie obiektowe". 

background image

Typy wbudowane 

 

 

Język C# dostarcza pewien zbiór typów wbudowanych. Typy te są 
reprezentowane przez zarezerwowane wyrazy - słowa kluczowe. Każdy z 
typów wbudowanych ma swój odpowiednik (alians) w przestrzeni nazw 
System. Typy wbudowane możemy podzielić na następujące kategorie: 

 

Typy wartości 

o  typ logiczny: bool 

o  typy numeryczne 

  typy całkowite: sbyte, byte, short, ushort, int, uint, 

long, ulong, char 

  typy rzeczywiste: float, double 

  typ rzeczywisty o dużej precyzji: decimal 

 

Typy referencyjne:  

o  object,  

o  napisy: string 

W poniższej tabeli zostały opisane wszystkie typy wbudowane. Zostało podane 
słowo kluczowe identyfikujące typ, nazwa typu w przestrzeni nazw System, 
liczba bajtów zajmowanych przez zmienne danego typu oraz przedział 
dopuszczalnych wartości. 

background image

 

Słowo 

kluczowe 

Alians 

Liczba 
bajtów 

Przyjmowane wartości 

bool 

Boolean 

true lub false 

sbyte 

SByte 

od -128 do 127 

byte 

Byte 

od 0 do 255 

short 

Int16 

od -32768 do 32767 

ushort  UInt16 

od 0 do 65535 

int 

Int32 

od -2147483648 do 2147483647 

uint 

UInt32 

od 0 do 4294967295 

long 

Int64 

od -9223372036854775808 

 do 9223372036854775807 

ulong 

UInt64 

od 0 do 18446744073709551615 

char 

Char 

od 0 do 65535 

typ znakowy (Unicody) 

float 

Single 

±1.5 × 10e−45 do ±3.4 × 10e38 

pojedyncza precyzja (7 cyfr) 

double  Double 

±5.0 × 10−e324 to ±1.7 × 10e308 

podwójna precyzja (15-16 cyfr) 

decimal  Decimal 

12 

±1.0 × 10e−28 to ±7.9 × 10e28 

(28-29 cyfr) 

object  Object 

typ podstawowy dla wszystkich innych 

typów 

string  String 

Napis - dowolny ciąg znaków 

 

Wybór typu dla zmiennej jest determinowany przez jej zastosowane, czyli 
żądane wartości. W przypadku typów reprezentujących liczby rzeczywiste 
oprócz wielkości przedziału (jak duże liczby), bardzo ważna jest również 
precyzja - ilość cyfr znaczących. Tylko skończoną ilość liczb możemy 
zakodować na skończonej ilości bajtów.  

background image

Deklaracja zmiennych 

 

 

Przed użyciem zmiennej musimy ją zadeklarować, czyli podać jej typ i nazwę 
np.: 

 

int x; 

Powyższa linijka rezerwuje cztery bajty pamięci (tyle zajmuje typ int) i 
nadaje temu obszarowi pamięci w naszym programie nazwę x. 

Uwaga: 
Kolejność deklaracji jest ważna tylko przy deklaracji zmiennych lokalnych, 
czyli deklaracji w obrębie bloku metody. W przypadku deklaracji zmiennych 
jako pól klasy, dostępne one są w całym bloku klasy, zarówno przed jak i po 
deklaracji. Podobnie jest z przestrzenią nazw. Nazwa typu zdefiniowanego 
bezpośrednio w bloku przestrzeni nazw lub bloku klasy jest dostępna w całym 
bloku przestrzeni nazw lub bloku klasy. Można powiedzieć, że przestrzeń nazw 
nie jest liniowa. 
Zmienne możemy deklarować tylko w bloku metody, tzw. zmienne lokalne 
oraz w bloku klasy (struktury), tzw. pola klasy (struktury). W języku C# nie ma 
zmiennych globalnych, czyli deklarowanych bezpośredni w bloku przestrzeni 
nazw lub poza jakimkolwiek blokiem. 

Można deklarować wiele zmiennych w pojedynczej deklaracji. Poszczególne 
nazwy zmiennych oddzielamy przecinkami. Przykład deklaracji trzech 
zmiennych typu double: 

 

double a,b,c; 

W miejscu deklaracji zmiennej lub zmiennym również możemy nadać wartość. 
W tym celu po nazwie zmiennej umieszczamy znak równości i następnie 

background image

podajemy wartość zmiennej (literał lub wyrażenie, którego typ jest zgodny z 
typem zmiennej):  

 

int p =10; 

 

int q = 2*p, r = 4; 

Uwaga: 
Literały i wyrażenia zostaną omówione w dalszej części tego modułu. 

Nazwy, które możemy nadawać zmiennym, czyli ich identyfikatory, muszą 
spełniać następujące reguły: 

 

Nazwa może składać się z ciągu liter, cyfr i znaku podkreślenia. Nazwa 
nie może zawierać, więc takich znaków jak np.: spacja, *, +. !. 

 

Nazwa nie może zaczynać się od cyfry, czyli niedopuszczalna jest 
deklaracja: 
 

int 1x; 

natomiast następująca deklaracja jest poprawna: 
 

int x1; 

 

Nazwa nie może być słowem kluczowym. Słowa kluczowe są to 
wyrazy zastrzeżone dla danego języka programowania. W języku C# 
występują następujące słowa kluczowe: 

abstract 

event   

 

new 

 

struct 

as 

 

explicit 

 

null   

switch 

base   

extern  

 

object  

this 

bool   

false   

 

operator 

throw 

break   

finally 

 

out 

 

true 

byte   

fixed   

 

override 

try 

case   

float   

 

params  

typeof 

catch   

for 

 

 

private 

uint 

char   

foreach 

 

protected 

ulong 

checked 

goto   

 

public  

unchecked 

class   

if 

 

 

readonly 

unsafe 

const   

implicit 

 

ref 

 

ushort 

continue 

in 

 

 

return  

using 

decimal 

int 

 

 

sbyte   

virtual 

default 

interface 

 

sealed  

volatile 

delegate 

internal 

 

short   

void 

do 

 

is 

 

 

sizeof  

while 

double  

lock   

 

stackalloc 

else   

long   

 

static 

enum   

namespace 

 

string 

 

Istnieją wyrazy w języku C#, które stają się słowami kluczowymi 
dopiero w pewnym kontekście. Należą do nich: 

get 

 

 

partial 

 

 

set 

value   

 

where   

 

 

yield

 

 
Visual Studio przy domyślnych swoich ustawieniach wszystkie słowa 
kluczowe oznacza kolorem niebieskim. 
Uwaga: 
Można używać słów kluczowych jako identyfikatorów stosując prefiks 
@: int @if;. Znak @ nie jest częścią identyfikatora. Sposób ten 
jest mocno niezalecany i stosuje się go, gdy łączymy program, z 
bibliotekami napisanymi w innych językach, w których występują 
identyfikatory będące słowami kluczowymi języka C#.

 

background image

 

Nazwa musi być unikalna w danym bloku kodu. W odróżnieniu od 
języka C++, w bloku zagnieżdżonym nie można przesłaniać 
identyfikatorów z bloku nadrzędnego: 

 

... 

 

int x; 

 

... 

 

 

 

double x;   //błąd, ta sama nazwa 

 

 

... 


 
ale 
 

 

... 

 

int x; 

 

... 



 

... 

 

double x;  //OK, inny blok 

 

... 


Uwaga:  
Od te reguły występują pewne wyjątki. Np.: w klasie można 
zadeklarować zmienną o danym identyfikatorze (blok klasy), a 
następnie w metodzie klasy użyć ponownie tego identyfikatora dla 
nowej zmiennej (blok metody jest zagnieżdżony w bloku klasy). 

Istnieje też szereg wskazówek, co do tworzenia identyfikatorów. 
Nieprzestrzeganie ich nie powoduje błędów. Stosowanie się jednak do nich 
świadczy o dobrym stylu i może ułatwić późniejszą analizę.  

 

Stosuj identyfikatory mówiące, do czego służy zmienna. Nazwa 
powinna mieć konkretne znaczenie. 

 

Zawsze używaj formatu PascalCase lub formatu camelCase przy 
tworzeniu nazw. W formacie PascalCase każdy wyraz, z których 
składa się identyfikator, rozpoczynamy wielką literą 
np.:WriteLine, ReadLine, Console, SByte. Formatu 
PascalCase używamy dla nazw typów, stałych nazwanych, 
właściwości, przestrzeni nazw. 
W przypadku formatowania camelCase pierwszy wyraz będący częścią 
identyfikatora piszemy małą literą, pozostałe rozpoczynamy wielką 
literą. np.: loopCountMax. Formatu camelCase używamy dla nazw 
zmiennych lokalnych, parametrów funkcji. 

 

Unikaj znaku podkreślenia. 

 

Nie używaj notacji węgierskiej. W notacji węgierskiej w prefiksie była 
zawarta informacja o typie zmiennej. 

 

Unikaj skrótów i akronimów. Jeżeli już używamy skrótów, powinny 
być one powszechnie znane i rozumiane. 

background image

 

Stosujemy w miarę możliwości nazwy anglojęzyczne. Szczególnie jest 
to ważne przy tworzeniu bibliotek.  

Więcej na temat konwencji stosowanych przy tworzeniu nazw można znaleźć w 
MSDN pod tematem: “Naming Guidelines” oraz na stronach www: 

http://home.comcast.net/~lancehunt/CSharp_Coding_Standards.pdf

http://www.idesign.net/idesign/download/Idesign Csharp Coding Standard.zip

 

 

background image

Literały 

 

 

Literał jest to część kodu źródłowego, która reprezentuje konkretną wartość 
danego typu. Może służy na przykład do nadawania zmiennym żądanych 
wartości. 

 

Do oznaczenia wartości typu logicznego używamy wyrazów true 
(prawda) oraz false (fałsz) np.:  
 
 

bool isHeight = true; 

 

Do określania wartości liczb całkowitych możemy użyć systemu 
dziesiętnego lub szesnastkowego. W przypadku systemu dziesiątkowego 
wartość zapisujemy tak jak w matematyce: 
 
 

int heiht = 234; 

 

int debt = -23;   

//wartość ujemna 

 
W przypadku systemu szesnastkowego przed ciągiem cyfr szesnastkowych 
umieszczamy 0x. Do oznaczenia brakujących cyfr szesnastkowych 
używamy liter: a, b, c, d, e, f. 
 
 

long weight = 0x2a; 

//42 w dziesiętnym 

 
Samemu literałowi jest przyporządkowany pierwszy z typów int, uint, 
long albo ulong w którym dana wartość jest reprezentowana. Możemy 
również w sposób jawny określić typ literału przez dodanie sufiksu: 
u - uint albo ulong, gdy w typie uint się nie mieści, 
l - long albo ulong, gdy w typie long się nie mieści 
ul, lu - ulong, np.: 

background image

 

long depth = 23l; 

Wielkość liter w przypadku sufiksów nie ma znaczenia 
Uwaga: 
Gdy wartość literału jest poza zakresem typu ulong generowany jest błąd 
kompilatora. 

 

Stałe rzeczywiste możemy wyrażać: 

o  przy pomocy znaku kropki: 

 
double x = 3.54; 
double y = .34; 
double z = -3.0; 

stosując tzw. postać naukową: 
 
double x = 354e-2; 
double y = 3.4e-1; 
double z = -0.03e2; 
 
gdzie np.: 354e-2 = 354 * 10 

-2

 

używając sufiksów 
 
double a = 2d; 
float b = 4.4f; 
decimal c = 6m; 
 
Wielkość liter w przypadku sufiksów nie ma znaczenia. 

Literałom rzeczywistym bez dodanego sufiksu przyporządkowany jest typ 
double. 
W przypadku literałów rzeczywistych, gdy wartość literału nie ma 
dokładnej reprezentacji w danym typie, ale mieści się w zakresie 
dopuszczalnych wartości danego typu, jest zaokrąglana. W przypadku, gdy 
wartość literału jest poza zakresem dopuszczalnych wartości dla danego 
typu rzeczywistego, generowany jest błąd kompilatora. 

 

Stałe znakowe reprezentują pojedynczy znak i zwykle zawierają dany znak 
umieszczony w apostrofach. 
 
char c = 'a', d = '1'; 
 
Wewnątrz apostrofów możemy również umieścić pewną sekwencję znaków, 
która reprezentuje pojedynczy znak. Sekwencja ta rozpoczyna się od znaku 
lewego ukośnika (backslash). Poniżej umieszczono dopuszczalne sekwencje 
znaków:  
Sekwencja 

Znak 

Nazwa znaku 

\' 

apostrof 

\" 

cudzysłów 

\\ 

lewy ukośnik (backslash) 

\0 

 

null 

\a 

 

sygnał dźwiękowy 

\b 

 

cofnięcie o jeden znak 

\f 

 

nowa strona 

\n 

 

nowy wiersz 

\r 

 

powrót karetki 

\t 

 

tabulacja pozioma 

background image

\v 

 

tabulacja pionowa 

Ponadto można skorzystać z szesnastkowej sekwencji znaków (hexadecimal 
escape sequence), która jest poprzedzona znakami \x oraz sekwencji w 
kodzie Unicode (Unicode character escape sequence), która jest 
poprzedzona znakami \u. W obu przypadkach podajemy szesnastkowy 
kod Unicode żądanego znaku.  
 
char c='\x4d'; 

//można też c = '\x004d'; 

char d = '\u004d'; 
 
Uwaga: 
W języku C# sekwencja w kodzie Unicode (Unicode character escape 
sequence) może rozpoczynać się od znaków \U po którym należy umieścić 
ciąg składający się z ośmiu cyfr szesnastkowych. Znaki o kodach z 
przedziału U+10000 do U+10FFFF nie są dozwolone w literałach 
znakowych i napisowych. Znaki o kodzie powyżej 0x10FFFF nie są w ogóle 
wspierane w języku C#. 

 

Literał napisowy jest ciągiem znaków ujętym w cudzysłów: 
 
string s = "Dowolny napis"; 
 
Jest to tzw. regularny literał napisowy. Może on zawierać zero lub więcej 
znaków, ale nie może być dzielony na dwie i więcej linii oraz nie może 
zawierać znaku " i pojedynczego znaku \. Może natomiast zawierać 
sekwencje znaków rozpoczynających się od lewego ukośnika, które zostały 
opisane przy literałach znakowych. Polecenie: 
 
Console.WriteLine("\"Pan Tadeusz\""); 
 
spowoduje pojawienie się na ekranie: 
 
"Pan Tadeusz" 
 
Natomiast po wykonaniu polecenia: 
 
Console.WriteLine("Cześć!\nTu Twój komputer."); 
 
Na ekranie pojawi się napis w dwóch liniach: 
 
Cześć! 
Tu Twój komputer. 
 
W C# istnieją również literały napisowe dosłowne (verbatim-string-literal). 
Różnią się od regularnych literałów napisowych tym, że przed cudzysłów 
otwierający wstawiamy znak małpy @. 
 
string s = @"Dowolny napis"; 
 
W literałach napisowych dosłownych znak lewy ukośnik nie ma żadnego 
specjalnego znaczenia. Polecenie: 
 
Console.WriteLine(@"Cześć!\nTu Twój komputer."); 
 
spowoduje pojawienie się na ekranie: 
 

background image

Cześć!\nTu Twój komputer. 
 
Jeżeli chcemy uzyskać cudzysłów " w literale napisowym dosłownym, 
należy użyć dwóch znaków cudzysłów "". Polecenie 
 
Console.WriteLine(@"""Pan Tadeusz"""); 
 
spowoduje pojawienie się na ekranie: 
 
"Pan Tadeusz" 
 
Literały napisowe dosłowne mogą rozciągać się na wiele linii. 

Do deklaracji zmiennej można dodać modyfikator const. Otrzymujemy w ten 
sposób stałą nazwaną, często nazywaną po prostu stałą. 
 
const int SpeedLight = 300000; 

//km/s 

 
Wartość stałych nazwanych musi być podana w miejscu deklaracji i później jej 
nie można zmieniać. Wartość wyrażenia inicjalizującego stałą nazwaną jest 
obliczana w czasie kompilacji. Wyrażenie zatem nie może zawierać odwołania 
do zmiennych. Może natomiast zawierać odwołania do innych stałych.  
Przykładami stałych zdefiniowanych w bibliotece .NET są: 
 
System.Math.PI; 

//liczba pi 

System.Math.E; 

//podstawa logarytmu naturalnego 

 
Zastosowanie stałych nazwanych, zamiast bezpośrednio literałów, ułatwia 
zrozumienie i analizę programu. Program staje się bardziej czytelny.  

Uwaga: 
Stała nazwana zdefiniowana jako pole klasy jest automatycznie polem 
statycznym tej klasy. 

background image

Pobieranie i wypisywanie wartości zmiennych 

 

 

W programie niektóre wartości zmiennych muszą być wprowadzone przez 
użytkownika programu. W aplikacjach konsolowych wykorzystuje się do tego 
najczęściej metodę ReadLine klasy Console. Metoda ta udostępnia dane 
wprowadzone przez użytkownika w formie napisu - zmiennej typu string. 
Napis trzeba zamienić, przekonwertować, na wartość żądanego typu. Można 
wykorzystać do tego metody klasy Convert: ToInt32, ToBoolean, 
ToDecimal... 

Czyli aby pobrać od użytkownika wartość liczby rzeczywistej należy napisać 
następujący kod: 

 

string s = Console.ReadLine(); 

 

double x = Convert.ToDouble(s); 

lub krócej: 

double x = Convert.ToDouble(Console.ToString()); 

W celu wypisania wartości zmiennej na ekranie możemy użyć metody Write 
lub WriteLine w następujący sposób: 

Console.WriteLine(nazwaZminnej); 
Console.Write(nazwaZminnej); 

Często gdy wypisujemy wartość zmiennej, łączymy to z pewnym opisem. 
Metoda Write i WriteLine umożliwia również wypisanie wartości kilku 
zmiennych w pojedynczym wywołaniu metody. Załóżmy, że mamy zmienne:  
x = 10, y = 20, z = 30. Plecenie: 

Console.WriteLine("x={0}, y={1}, z={2}",x,y,z); 

background image

spowoduje wypisanie na ekranie: 

x=10, y=20, z=30 

Z powyższego przykładu widać, że znaki {index} zostały zastąpione 
wartością odpowiedniej zmiennej. Index wskazuje numer pozycji argumentu, 
którego wartość należy wstawić w danym miejscu. Argumenty indeksujemy od 
zera.  

Uwaga: 
Gdy wartość indeksu jest większa lub równa liczbie argumentów zgłaszany jest 
wyjątek. 

Gdy chcemy wypisać znak nawias klamrowy otwierający {, musimy podać 
dwa nawisy klamrowe otwierające {{, aby wyświetli znak nawias klamrowy 
zamykający }, należy podać dwa nawisy klamrowe zamykające }}. 

W celu zademonstrowania wprowadzania i wypisywania wartości zmiennych 
napisz program obliczający sumę dwóch liczb rzeczywistych. Gotowy program 
jest dostępny w katalogu Kurs\Demo\Modul2\Modul2.sln projekt 
Dodawanie, gdzie Kurs jest katalogiem gdzie skopiowano pliki kursu 

1.  Uruchom Visual Studio 

2.  Utwórz aplikację konsolową o nazwie: Dodawanie 

3.  W metodzie Main napisz następujący kod: 

static void Main(string[] args) 

 

double x, y, suma; 

 

Console.Write("Podaj x: "); 

 

x = Convert.ToDouble(Console.ReadLine()); 

 

Console.Write("Podaj y: "); 

 

y = Convert.ToDouble(Console.ReadLine()); 

 

suma = x + y; 

 

Console.WriteLine("{0}+{1}={2}", x, y, suma); 

 

Console.ReadKey(); 

4.  Zbuduj i uruchom program. 

5.  Jako wartość zmiennej x wprowadź: 

2.5 ENTER 
Prawdopodobnie program został przerwany. Został zgłoszony wyjątek. 
Spowodowane jest to tym, że metody klasy Convert przy zamianie 
wykorzystują domyślnie informacje o formatowaniu liczb, dat, godziny, 
znaku symbolu dziesiętnego itp. z ustawień systemu (Panel Sterowania, 
Opcje regionalne i językowe). W przypadku, gdy wszystkie formaty 
ustawione są dla Polski, symbolem dziesiętnym jest przecinek. 
Uwaga: 
Tak naprawdę ustawienia regionalne (formatowanie liczb, daty) zawarte są 
we właściwościach bieżącego wątku 

background image

(Thread.CurrentThread.CurrentCulture) i można je 
modyfikować w programie, czyli mogą być niezależne od ustawień 
systemowych. 

6.  Z menu Debug wybierz pozycję Stop Debugging

7.  Uruchom program ponownie i wprowadź wartości zmiennych w 

odpowiednim formacie. 

Wypisywaną wartość można poddać formatowaniu. Uzyskuje się to przez 
dodanie kilku znaków między nawiasy klamrowe. Oto postać ogólna:  

 

{index[,n][:symbol]} 

index – jak już wspominano, numer argumentu który należy wypisać. 

n – liczba pozycji (miejsc), które zajmuje dana wartość. Brakujące miejsca 
uzupełniane są spacjami. Wartość dodatnia oznacza wyrównywanie do prawej, 
ujemna do lewej. 

symbol - pewna litera oznaczająca sposób formatowania liczb. Po literze może 
wystąpić liczba z przedziału od 0 do 99 oznaczająca precyzję. Dostępne litery: 

•  C lub c – dodawany jest symbol waluty 

•  D lub d – format tylko dla liczb całkowitych. Precyzja określa z ilu 

cyfr składa się liczba. Gdy liczba składa się z mniejszej ilości cyfr 
brakujące miejsca uzupełniane zerami z lewej strony. 

•  E lub e – liczba jest wyświetlana w notacji naukowej - postać 

wykładnicza. Jedna cyfra zawsze poprzedza znak dziesiętny. 

•  F lub f - liczba jest konwertowana do postaci stałopozycyjnej (fixed-

point). 

•  G lub g - liczba jest konwertowana do najbardziej zwięzłej postaci 

(notacja naukowa lub stałopozycyjna) 

•  N lub n - wstawiany jest separator tysięcy. 

•  X lub x - format tylko dla liczb całkowitych. Liczba jest wyświetlana w 

systemie szesnastkowym. 

•  P lub p - wartość liczby jest mnożona przez sto i dodawany jest znak 

procentu. 

•  R lub r - gwarantuje, że po skonwertowaniu liczby do napisu (stringu) i 

późnie wykonaniu konwersji odwrotnej (napisu do liczby) otrzymamy 
tą samą wartość numeryczną. 

Więcej informacji można znaleźć w MSDN Library pod tematem "Standard 
Numeric Format Strings". 

Przykłady zastosowania formatowania można znaleźć w programie 
Kurs\Demo\Modul2\Modul2.sln projekt Formatowanie, gdzie 
Kurs jest katalogiem gdzie skopiowano pliki kursu. 

W podobny sposób, możemy tworzyć napisy przy pomocy metody Format 
klasy String: 

string s; 
s = String.Format("{0} + {1} = {2}", 2, 2, 2+2); 

background image

Zmienna s będzie zawierała następujący napis: 2 + 2 = 4. 

background image

Typ wartości 

 

 

Jak wspominano wcześniej w tym module, każdy typ należy do jednej z dwóch 
kategorii typów: typy wartości lub typy referencyjne. 

Do typów wartości należą: 

 

Typy wbudowane numeryczne(byte, sbyte, short, ushort, int, uint, long, 
ulong, char, float, double, decimal). 

 

Typ wbudowany bool (logiczny). 

 

Typy wyliczeniowe (typ ten zostanie omówiony w dalszej części tego 
modułu). 

 

Struktury - jest to typ definiowany przez użytkownika. Więcej o tym 
typie będzie w rozdziale 11 - "Struktury" 

Zmienne typu wartości bezpośrednio zawierają dane, dlatego też niektórzy 
nazywają typ ten typem bezpośrednim. Każda zmienna typu wartości 
reprezentuje oddzielny obszar pamięci, dlatego operacja na jednej zmiennej nie 
wpływa na drugą. Zmienne lokalne przechowywane w obszarze pamięci 
zwanym stosem. Z miejscem przechowywania i sposobem zarządzania tym 
obszarem związany jest czas życia zmiennej. Czas życia zmiennej możemy 
zdefiniować jako czas, przez który jest zarezerwowana pamięć dla zmiennej. 
Pamięć jest zarezerwowana dla zmiennej lokalnej od miejsca jej 
zadeklarowania do końca bloku, w którym została zadeklarowana. 


 

double x;  //początek "życia" zmiennej x 

 

... 

 

background image

 

 

... 

 

 

int y;   ////początek "życia" zmiennej y 

 

 

... 

 

 

//koniec "życia" zmiennej y 

 

... 

 

 

//koniec "życia" zmiennej x 

Uwaga: 
Zasada działania stosu zostanie omówiona dokładnie w rozdziale 11, natomiast 
pojęcie zmiennej lokalnej w rozdziale 8 tego kursu. 

Przed użyciem zmienna musi być zainicjalizowana - musi mieć nadaną wartość: 

int x; 
Console.Write(x);  

//Błąd kompilacji 

Zmienne typu wartości posiadają zawsze jakąś wartość, nie mogą być null.  

Uwaga: 
W wersji C# 2.0 dla wszystkich typów wartości wprowadzono pewną formę 
typu (nullable types), której zmienne mogą przyjmować wartości null (wartość 
nieokreślona). Typ ten uzyskujemy przez dodanie do końca nazwy typu 
wartości znaku zapytania ?. 

int? x; 
x = null;   

//OK 

int y; 

 

 

y = null;   

//Błąd kompilacji 

Typy nullable wprowadzono, aby ułatwić współpracę z bazami danych.  

 

background image

Typ wyliczeniowy 

 

 

Typ wyliczeniowy jest to typ definiowany przez użytkownika (programistę). 
Stosujemy go, gdy chcemy, aby zmienne tego typu mogły przyjmować wartości 
z określonego zestawu stałych. Definiuje się go przy pomocy słowa 
kluczowego enum, po którym występuje nazwa nowego typu, a następnie w 
nawiasach klamrowych podajemy nazwy symboliczne dopuszczalnych 
wartości, oddzielone przecinkami. Nazwy, jakie możemy nadawać typom 
wyliczeniowym oraz poszczególnym elementom, podlegają tym samym 
zasadom co identyfikatory zmiennych. Oto przykład definicji tego typu: 

enum PoryRoku {Wiosna, Lato, Jesien, Zima}; 

Domyślnie pierwszy element ma przypisaną wartość 0, wartość każdego 
kolejnego elementu jest większa o jeden od wartości poprzednika. Można 
również przypisać w sposób jawny wartości poszczególnym elementom np.: 

enum Kolory{czerwony=4, zielony, niebieski=7}; 

Element zielony ma w sposób niejawny przypisaną wartość 5.  

Wartości elementom typu wyliczeniowego mogą być nadawane w dowolnej 
kolejności, a nawet można im przypisać wartości jednakowe, gdy kilka symboli 
oznacza tę samą wartość.  

Uwaga: 
Typy wyliczeniowe, jak inne typy definiowane przez użytkownika (klasy, 
struktury), nie można definiować wewnątrz bloku metody. 

Oto prosty przykład użycia typu PoryRoku: 

PoryRoku sezon = PoryRoku.Wiosna; 

background image

Console.WriteLine("Ulubiona pora roku: {0}", sezon); 

Na ekranie zostanie wypisane: 

Ulubiona pora roku: Wiosna. 

Widać więc, że zamiast wartości liczbowej zmiennej zostanie wypisana wartość 
symboliczna. 

Przykłady zastosowania typu wyliczeniowego można znaleźć w programie 
Kurs\Demo\Modul2\Modul2.sln projekt PoryRoku oraz 
Konsola, gdzie Kurs jest katalogiem gdzie skopiowano pliki kursu. 
Konwersja wykorzystywana w projekcie PoryRoku jest opisana w dalszej 
części tego modułu. 

Uwag: 
Przy definicji typu wyliczeniowego można podać, jaki typ całkowity jest typem 
bazowym dla definiowanego typu wyliczeniowego. Typem bazowym może być 
dowolny tym całkowity poza typem char. 

enum PoryRoku : byte {Wiosna, Lato, Jesien, Zima}; 

Przy tworzeniu nazwy typu wyliczeniowego, podobnie jak w przypadku nazw 
innych typów, stosuje się format PascalCase. 

Stosowanie typu wyliczeniowego, podobnie jak stałych nazwanych czyni nasz 
kod bardziej czytelnym. Oprócz tego: 

 

Zapewnia, że zmiennym są przypisane odpowiednie wartości. 

 

W środowisku Visual Studio ułatwia pisanie kodu dzięki 
automatycznemu uzupełnianiu nazw (IntelliSense). 

background image

Typ referencyjny 

 

 

Drugą kategorią typów są tak zwane typy referencyjne. Do typów 
referencyjnych zaliczamy: 

 

Typy wbudowane string i object 

 

Klasy 

 

Interfejsy 

 

Delegacje 

 

Tablice 

Klasy, interfejsy oraz delegacje zostaną dokładnie omówione w kursie 
"Programowanie obiektowe". Tablice zostaną omówione w rozdziale szóstym i 
siódmym tego kursu.  

Zmienne typów referencyjnych zawierają odwołanie, nie zawiera bezpośrednio 
danych. Dane (obszar pamięci) do których odwołuje się zmienna nazywamy 
obiektem. Zmienne, które nie odwołują się do żadnego obiektu, posiadają 
wartość null, nie mylić ze zmiennymi niezainicjalizowanymi. Często stosuje 
się pewien skrót myślowy i zmienną nazywa się obiektem danego typu. Obiekty 
przechowywane są na w obszarze pamięci, który nazywa się zarządzą stertą. 
Dwie zmienne danego typu referencyjnego mogą odwoływać się do tego 
samego obiektu, więc operacja na jednej zmiennej może zmieć dane innej 
zmiennej.  

Obiekty tworzy się przy pomocy słowa kluczowego new, chociaż istnieją 
pewne uproszczenia składni np. typ string. Przykład utworzenia obiektu 
klasy Random, która reprezentuje generator liczb pseudolosowych. 

background image

Random r;   

 

//deklaracja zmiennej 

//r.Nex(0,101);   

//błąd kompilatora, zmienna 

 

 

 

 

//niezainicjalizowana 

r = null;   

 

//inicjalizacja wartością null 

r = new Random();  

//utworzenie obiektu klasy 

 

 

 

 

//Random 

int i = r.Next(0,101); //losowanie liczby całkowitej  
 

 

 

 

//z przedziału <0;100> 

Uwaga: 
Użycie zmiennej referencyjnej o wartości null powoduje generację wyjątku w 
czasie działania programu. 

Oczywiście zmienną możemy zainicjalizować w miejscu deklaracji: 

Random r = new Random(); 

Na zmienną r stosując skrót myślowy można powiedzieć, że jest obiektem 
klasy Random. 

Poniższy kod: 

string s1 = "Ala ma kota"; 

string s2 = s1; 

można przedstawić graficznie w następujący sposób: 

 

Czas życia obiektu jest zarządzany przez proces automatycznego odzyskiwania 
pamięci (garbage collection). Nie jesteśmy wstanie określić dokładnie miejsca 
w programie, kiedy pamięć zajmowana przez obiekt zostanie zwolniona, czyli 
kiedy obiekt zostanie usunięty z pamięci. Możemy być jednak pewni, że proces 
automatycznego odzyskiwania pamięci nie usunie obiektu, jeżeli istnieje 
przynajmniej jedna zmienna, która odwołuje się do danego obiektu. 

Ala ma kota 

Obiekt 

Stos 

Zarządzana sterta 

s1 

s2 

background image

Konwersja typów 

 

 

Skopiowanie wartości zmiennej do zmiennej innego typu nazywamy 
konwersją. Konwersja oczywiście nie jest możliwa między dowolnymi dwoma 
typami. W języku C# istnieje szereg konwersji standardowych. 

Uwaga: 
W języku C# dla typów użytkownika może definiować własne metody 
konwersji. Szerzej o tym jest napisane w kursie "Programowanie obiektowe". 

Konwersje standardowe możemy podzielić na: 

 

Konwersje niejawne. 

 

Konwersje jawne. 

Konwersja niejawna zachodzi automatycznie. Programista nie musi jej 
oznaczać: 

int x = 10; 

long y = x;  

//konwersja z typu int do typu long 

W przypadku konwersji niejawnej nigdy nie ma utraty wartości, może być tylko 
utracona precyzja - dokładność. Można ją porównać do przelewania zawartości 
pojemnika o małej objętości do pojemnika o dużej objętości. Konwertować 
niejawnie można z typu "małego" do typu "dużego". "Duży" typ zawiera 
wartości typu "małego". Poniższa tabela przedstawia standardowe konwersje 
niejawne w języku C#. 

background image

 

Do 

sbyte 

short, int, long, float, double, decimal 

byte 

short, ushort, int, uint, long, ulong, float, double, decimal 

short 

int, long, float, double, decimal 

ushort 

int, uint, long, ulong, float, double, decimal 

int 

long, float, double, decimal 

uint 

long, ulong, float, double, decimal 

long, ulong 

float, double, decimal 

float 

double 

char 

ushort, int, uint, long, ulong, float, double, decimal 

 

Konwersje jawną można porównać do przelewania z dużego naczynia do 
małego. Przelewając ryzykujemy, że część płynu może się nie zmieścić w 
małym naczyniu i się rozleje. W przypadku konwersji jawnej zachodzi, więc 
obawa o utratę wartości. Programista musi poinformować, że dokonuje tej 
konwersji świadomie. Konwersję jawną zapisujemy przy pomocy operatora 
konwersji: 

short s =300; 
//byte b = s; 

//błąd, musi być konwersja jawna 

byte b = (byte)i;  

//OK 

Console.WriteLine(b); 

Na ekranie zostanie wypisane: 

44 

Została utracona wartość liczby. Chcąc kontrolować takie sytuacje można użyć 
polecenia checked. 

checked { 
 

int n = int.MaxValue; 

 

Console.WriteLine(++n); 

 

 

 

// OverflowException  

lub operatora checked 

int m = int.MaxValue; 
int n = checked(m+1);  // OverflowException 
short s= 300; 
byte b = checked((byte)s);   // OverflowException 

Wyraz checked powoduje, że w czasie wykonania programu jest 
kontrolowane, czy nie nastąpiło przepełnienie. Wystąpienie przepełnienia 
powoduje rzucenie wyjątku. Wyjątki zostaną przybliżone w następnym 
rozdziale. 

background image

Przełącznik kompilatora /checked+ domyślnie sprawdza przepełnienie. 
Domyślną opcją kompilatora jest /checked-, wyłączenie sprawdzania 
przepełnienia. Przy włączonej opcji kompilatora sprawdzenia przepełnienia, 
można ją wyłączyć przy pomocy słowa unchecked. Stosuje się je w 
identyczny sposób jak słowo checked. 

Uwaga: 
checked i unchecked dotyczą tylko liczb całkowitych. 

Literały rzeczywiste traktowane są jako typ double, więc następujący kod 
powoduje błędy kompilatora: 

float f = 4.2; 
decimal d = 2.4; 

Należy to zapisać to: 

float f = (float)4.2; 
decimal d = (decimal)2.4; 

lub krócej 

float f = 4.2f; 
decimal d = 2.4d; 

Kopiując wartość zmiennej typu wyliczeniowego do zmiennej typu całkowitego 
i dokonując konwersji odwrotnej, również musimy stosować konwersję jawną,. 

enum PoryRoku {Wiosna, Lato, Jesien, Zima}; 
... 
int i = 2; 
PoryRoku poryRoku = (PoryRoku)i; 
int j = (int)poryRoku; 

Uwaga: 
Podczas konwersji nie jest sprawdzane, czy dana wartość całkowita ma swoją 
reprezentację w danym typie wyliczeniowym - nie jest zgłaszany żaden błąd, 
ani nie ma generacji żadnego wyjątku.  

W języku C# istnieje jeszcze jedna standardowa konwersja - opakowanie 
(boxing). Opakowanie wartości polega na niejawnym przekształceniu typu 
wartości w typ object. 

int ilosc = 10; 
object obj = i;   

//opakowanie 

W wyniku operacji opakowania na zarządzanej stercie tworzona jest instancja 
obiektu, do której jest dowiązana zmienna obj. Wartość zmiennej ilosc została 
skopiowana do obiektu obj. Zmienna iosc oraz obiekt obj są niezależne. Zmiana 
wartości obiektu obj nie wpływa na wartość zmiennej ilosc. 

Operacja odwrotna do opakowania - rozpakowanie musi być wywoływana 
jawnie. Kompilator musi być poinformowany, jaki typ wartości ma uzyskać z 
obiektu na zarządzanej stercie. Podczas wykonywania rozpakowania następuje 
sprawdzenie, czy instancja obiektu zawiera wartość żądanego typu. Jeżeli jest 
tak w istocie, to wartość zostanie rozpakowana. W przeciwnym wypadku 
zostanie zgłoszony wyjątek - InvalidCastException. Więcej informacji 
na temat wyjątków można znaleźć w następnym rozdziale.  

int ilosc = 10; 
object obj = i;   

//opakowanie 

background image

int ilosc2 = (int)obj;  

//rozpakowanie 

 
double d = (double)obj; 

//wyjątek 

 

background image

Operatory 

 

 

Dla wbudowanych typów danych w językach programowania wprowadza się 
pewną liczbę prostych, standardowych operacji. Operacje te wyrażone są przy 
pomocy ciągu znaków, które nazywamy operatorami. Ciąg znaków składa się 
najczęściej z pojedynczego znaku lub dwóch znaków. Przykładem operatora 
jest znak równości = - operator przypisania. Oznacza on skopiowanie wartości 
zmiennej lub wyrażenia znajdującego się po prawej stronie do zmiennej 
znajdującej się po lewej stronie znaku równości. Pojęcie wyrażenie, 
występujące w poprzednim zdaniu, oznacza ciąg operatorów i argumentów. 
Wyrażenie może dawać w wyniku pewną wartość i powodować efekty 
uboczne. Argumentem może być identyfikator zmiennej, literał, wywołanie 
metody, nazwa typu lub inne wyrażenie. Wyrażenie może składać się tylko z 
pojedynczego argumentu - identyfikatora zmiennej, literału, wywołania 
metody. 

Po skończeniu tej części modułu studenci będą: 

 

Znali operatory występujące w języku C#. 

 

Potrafili budować wyrażenia i obliczać ich wartość. 

Uwaga: 
Dla typów definiowanych przez użytkownika można przeciążyć, zdefiniować 
własną wersję większości operatorów. Temat przeciążenie operatorów jest 
omawiany w kursie "Programowanie obiektowe". 

background image

Predefiniowane operatory w C# 

 

 

Omawiając operatory podzielimy je na grupy. 

 

Operatory arytmetyczne - oznaczają proste działania matematyczne. Do 
operatorów arytmetycznych zaliczamy: + (dodawanie), - (odejmowanie), * 
(mnożenie), / (dzielenie), % (reszta z dzielenia). Jako argumenty mogą 
przyjmować wartość (zmienną) dowolnego typu numerycznego.. 
 
double x = 20, y = 10; 
double z = x + y; 

 

//z = 30 

z = x - y; 

 

 

//z = 10 

z = x * y; 

 

 

//z = 200 

z = x / y; 

 

 

//z = 2 

z = 7 % 3; 

 

 

//z = 1 

z = -7 % 3; 

 

 

//z = -1 

z = 7 % -3; 

 

 

//z = 1 

z = -7 % -3; 

 

 

//z = -1 

 
Uwaga: 
W przypadku dzielenie liczb całkowitych wynik jest również całkowity. 
 
z = 6 / 5; 

 

// z = 1 nie 1.2 

 
W przypadku liczb całkowitych oraz liczb typu decimal przy dzieleniu 
przez zero oraz reszty z dzielenia przez zero zgłaszany jest wyjątek. 
W przypadku dzielenia liczb typu float lub double przez zero, 
wynikiem jest nieskończoność (+ lub minus) lub wynik "nie jest liczbą".  
W przypadku dodawania, odejmowania, mnożenia licz całkowitych, jeżeli 
wynik przekracza zakres dopuszczalnych wartości danego typu, zachowanie 

background image

jest uzależnione od opcji kompilatora /checked (patrz temat "Konwersja 
typów" w tym rozdziale). W przypadku typów rzeczywistych, jeżeli wynik 
nie mieści się w zakresie dopuszczalnych wartości danego typu, wynikiem 
jest plus lub minus nieskończoność. Dla typu decimal przy przekroczeniu 
zakresu dopuszczalnych wartości rzucany jest wyjątek. OverflowException. 
Dokładny opis sposobu działania w sytuacjach kłopotliwych (zero i 
nieskończoność, dwie nieskończoności itp.) można znaleźć w specyfikacji 
języka C# w rozdziale 7.7 - C# Language Specification 1.2.doc. 
Uwaga: 
Operatory dodawania i odejmowania są również automatycznie dostępne dla 
typów wyliczeniowych. Wynikiem dodawania lub odejmowania dwóch 
wartości danego typu wyliczeniowego, jest wartość typu całkowitego 
bazowego dla danego typu wyliczeniowego. 

 

Operator konkatenacji - łączenia napisów +.  
W przypadku znaku dodawania, gdy po jego obu stronach występują 
wartości typu string oznacza on łączenie napisów, tworzony jest nowy 
obiekt reprezentujący połączone napisy. 
 
string s = "Ala ma "; 
string s2 = s + "kota"; 

//s2 = "Ala ma kota" 

 

Operatory relacyjne. 
Wynikiem ich działania jest prawda lub fałsz - typ logiczny.  
Dla typów numerycznych oraz typów wyliczeniowych mamy następujące 
operatory relacyjne: == (czy równe), != (czy różne), < (czy mniejsze), > 
(czy większe), <= (czy mniejsze lub równe), >= (czy większe lub równe) 
np. : 
 
bool b; 
int i =10, j =20; 
b = i > j; 

  //b = false 

 
Uwaga: 
W przypadku typów rzeczywistych należy pamiętać że: 
–∞ ==  –∞< –max < ... < –min < –0.0 == +0.0 < +min 
< ... < +max < +∞ == +∞ 
gdzie max oraz min są odpowiednio największą i najmniejszą wartością 
dodatnią danego typu rzeczywistego. 
 
W przypadku typów referencyjnych predefiniowane są operatory: == (czy 
równe), != (czy różne). Wersje predefiniowane tych operatorów sprawdzają 
czy zmienne odwołują się do tego samego obiektu (równość referencji), a 
nie czy obiekty mają tę samą wartość (równość wartości). Programista może 
zmienić znaczenie tych operatorów. Jest tak np. w przypadku typu string. 
Dla typu string operatory te porównują wartość nie referencje. W 
przypadku, gdy obie zmienne danego typu referencyjnego mają wartość 
null przyjmuje się, że są równe. 
Uwaga: 
Gdy chcemy porównywać napisy, możemy użyć metody 
string.Compare. Opertory <,>,<=, >= dla typu string nie są 
zdefiniowane. 
 
Operatory == (czy równe), != (czy różne) zdefiniowane są również dla typu 
logicznego. 

background image

 

Operatory przesunięcia << lub >> 
Są to dwuargumentowe operatory pracujące na argumentach typu 
całkowitego lub typów wyliczeniowych.  
 
x<<n; 

//przesunięcie w lewo 

x>>n 

//Przesunięcie w prawo 

 
n - określa ilość bitów przesunięcia. 
Uwaga: 
Do obliczenia rzeczywistej ilości bitów do przesunięcia, jeżeli x jest typu 
int lub uint, branych jest tylko pięć najmniej znaczących bitów n (n & 
0x1F), natomiast gdy x jest typu long lub ulong, branych jest sześć 
najmniej znaczących bitów n (n & 0x3F) 
 
W przypadku przesunięcia w lewo sposób obliczania wartości liczby po 
przesunięciu jest prosty. Zapisujemy liczbę w notacji dwójkowej. Następnie 
skreślamy n najbardziej znaczących cyfr dwójkowych (z lewej strony), 
gdzie n oznacza ilość bitów przesunięcia i dopisujemy n 0 z prawej strony. 
 
int x = 0x2f;    

//101111  

int y = x << 2; 

//10111100 

 
Uwaga: 
W przypadku liczb ze znakiem liczby kodowane są następująco. Najbardziej 
znaczący bit jest nazywany bitem znaku i jeżeli jest ustawiony do równania 
obliczającego wartość liczby zamiast liczby 1 wstawiamy -1. Zostanie to 
pokazane na przykładzie typu sbyte (osiem bitów): 
d7

(16)

 = 1101 0111

(2)

 = -1 * 2

7

 + 1 * 2

6

 + 0 * 2

5

 + 1 * 2

4

 + 0 * 2

3

 + 1 * 2

2

 +  

+ 1 * 2

1

 + 1 * 2

0

 = -128 +64 + 16 + 4 + 2 + 1 = -41 

 
int x = -1;     

// 0xffffffff  

int y = x << 1; 

// 0xfffffffe, y=-2 

 
W przypadku przesunięcia w prawo sytuacja jest bardziej skomplikowana. 
Dla liczb dodatnich skreślamy n najmniej znaczących bitów i z przodu 
dodajemy n zer. Dla liczb ujemnych również skreślamy n najmniej 
znaczących bitów, ale z przodu dopisujemy jedynki. 
Przesunięcie w lewo jest równoważne mnożeniu przez n-tą potęgę liczby 
dwa, natomiast przesunięcie w prawo jest równoważne dzieleniu przez n-tą 
potęgę dwóch. 

 

Operatory bitowe (logical operators): 
Do operatorów bitowych należ: & (koniunkcja), ^ (różnica symetryczna), | 
(alternatywa). ~ (negacja bitowa). Zasadę ich działania dla typów 
całkowitych oraz wyliczeniowych przedstawia poniższa tabela:  
 
x =  

1 1 0 0 

...(pozostałe bity) 

y =  

1 0 1 0 

...(pozostałe bity) 

x & y =  1 0 0 0 

...(pozostałe bity) 

x | y =  1 1 1 0 

...(pozostałe bity) 

x ^ y =  0 1 1 0 

...(pozostałe bity) 

~x = 

0 0 1 1 

...(pozostałe bity) 

 
Argumentami operatorów bitowych & (koniunkcja), ^ (różnica 
symetryczna), | (alternatywa) mogą być zmienne typu logicznego. Działanie 
ich jest następujące: 

background image

 
x =  

true   

false  

true   

false 

y =  

true   

true   

false  

false 

x & y =  true   

false  

false  

false 

x | y =  true   

true   

true   

false 

x ^ y =  false  

true   

true   

false 

 

 

Operatory logiczne (conditional logical operators) 
Do operatorów logicznych zaliczamy: && (iloczyn logiczny), || (suma 
logiczna) oraz ! (negacja logiczna). Argumentami tych operatorów mogą 
być wartości logiczne. 
Wyrażenie x && y zwraca wartość true, jeżeli x i y ma wartość true. 
Od wyrażenia x & y różni się tym, że wartość y jest obliczana tylko wtedy, 
gdy x ma wartość true. 
Wyrażenie x || y zwraca wartość true, jeżeli x lub y ma wartość 
true

. Od wyrażenia x | y różni się tym, że wartość y jest obliczana tylko 

wtedy, gdy x ma wartość false. 
Operator ! (negacja logiczna) zmienia wartość true na false i na 
odwrót. 
 
bool x = true; 
bool y = ! x;   

//y=false 

 
Do operatorów logicznych zaliczamy również operatory true oraz false. 
Wykorzystywane są przy przeciążeniu operatorów && oraz || i są poza 
zakresem tego kursu. 

 

Operatory inkrementacji (zwiększania o 1) i dekrementacji (zmniejszania o 
1). 
Oba operatory mają dwie wersje: przyrostkową oraz przedrostkową. Zasada 
działania zostanie pokazana na przykładzie 
 
int x = 10, y = 10; 
int z = x++; 
int v = ++y; 
 
Wartość zmiennych x, y, v po wykonaniu powyższego kodu będzie 11, 
natomiast wartość v będzie wynosić 10. Dzieje się tak, ponieważ wersja 
przyrostkowa x++ najpierw wstawia wartość zmiennej do wyrażenia, a 
następnie zwiększa jej wartość o jeden, natomiast wersja przedrostkowa 
(++y) najpierw zwiększa wartość zmiennej o jeden, a następnie zwraca jej 
wartość, już zwiększoną do wyrażenia. 
Dla operator dekrementacji będzie to wyglądało następująco: 
 
int a = 10, b = 10; 
int c =  a--;   

//c=10, a = 9 

int d = --b; 

 

//d=9, b=9 

 
Operatory te można stosować do wszystkich zmiennych typów 
numerycznych (int, char, double, decimal ...). 

 

Operatory przypisania. 
Wcześniej w tym rozdziale był używany operator przypisania 
(podstawienia) oznaczony pojedynczym znakiem równości =. Dla 
zmiennych typów wartości oznacza on skopiowanie wartości zmiennej lub 
wyrażenia znajdującego się po prawej stronie znaku równości, do zmiennej 

background image

znajdującej się po lewej stronie znaku równości. Dla zmiennych typów 
referencyjnych oznacza skopiowanie tylko odwołania. Do operatorów 
przypisania zaliczmy również: +=, -=, *=, /=, %=, &=, |=, 
^=, <<=, >>=
Znaczenie poszczególnych operatorów jest zdefiniowane poniżej. 
 
x += 2; 

x = x + 2; 

x -= 2; 

x = x - 2; 

x *= 2; 

x = x * 2; 

x /= 2; 

x = x / 2; 

x %= 2; 

x = x % 2; 

x &= 2; 

x = x & 2; 

x |= 2; 

x = x | 2; 

x ^= 2; 

x = x ^ 2; 

x <<= 2; 

x = x << 2; 

x >>= 2; 

x = x >> 2; 

 

 

Plus + i minus - jednoargumentowy.  
Operatory te są predefiniowane dla typów numerycznych i mają identyczne 
znaczenie jak w zapisie matematycznym. W przypadku operator + do 
wyrażenia wstawiana jest wartość jego argumentu, nie zmienia on wartości 
swojego argumentu. Operator - oznacza liczbę przeciwną. Operator - nie 
może być stosowany do zmiennych typu ulong, generowany jest błąd 
kompilacji. W przypadku argumentu typu uint, rezultat jest konwertowany 
do long.  

 

Operator dostępu do składowej kropka . . 
Znak kropki oddziela nazwę kontenera (nazwa przestrzeni nazw, nazwa 
klasy, nazwa struktury) od nazwy rzeczy zagnieżdżonej (nazwa 
podprzestrzeni, nazwa klasy, nazwa metody ...). Pełni podobną rolę jak znak 
ukośnika przy podawaniu ścieżki dostępu, np.: 
System.Collections.Generic; 
System.Console.WriteLine(); 

 

Wyrażenie warunkowe.  
Ogólna postać wyrażenia warunkowego jest następująca: 
 
warunek ? wyrażenie1 : wyrażenie2; 
 
Wartość wyrażenia warunkowego jest obliczany w następujący sposób. 
Jeżeli warunek jest prawdziwy to wartością całego wyrażenia 
warunkowego jest wyrażenie1, w przeciwnym wypadku wartością 
wyrażenia warunkowego jest wyrażenie2. W zależności od wartości 
warunku obliczane jest tylko wyrażenie1 albo wyrażenie2. Nigdy nie 
są obliczane oba wyrażenia. Poniżej zostanie przedstawiony kod obliczający 
wartość bezwzględną (moduł liczby) przy pomocy wyrażenia 
warunkowego: 
 
double x, modul; 
... 
modul = x < 0 ? -x : x; 
 
A

rgumentu warunek musi być typu logicznego. Natomiast wyrażenie1 i 

wyrażenie2 muszą być tego samego typu, albo między typami tych 
argumentów musi istnieć konwersja niejawna. 

background image

 

Tworzenie nowego obiektu - operator new. 
W przypadku wywołania operatora new dla typów referencyjnych, 
następuje alokacji pamięci dla obiektu i inicjalizacja pamięci (wywołanie 
metody zwanej konstruktorem).  
 
Ranodom r =new Random(); 

//utworzenie obiektu klasy Random 

 
Operator new możemy również używać do "tworzenia" zmiennych typów 
wartości. W przypadku typów wartości nie ma jednak dynamicznej alokacji 
pamięci. Wywoływana jest, podobnie jak dla typów referencyjnych, metoda 
inicjalizująca zmienną zwana konstruktorem.  
 
int i = new int();  //int i = 0; 
 
Uwaga: 
Więcej o metodzie zwanej konstruktorem można znaleźć w kursie 
"Programowanie obiektowe". 

 

Operator rzutowania () i operatory kontrolujące przepełnienie typów 
całkowitych checked i unchecked zostały opisane wcześniej w tym 
rozdziale przy omawianiu konwersji jawnych. 

 

Operator indeksowania [] zostanie dokładnie omówiony w rozdziale 
szóstym tego kursu. 

 

Operatory informujące o typie (as, is, sizeof, typeof) zostaną 
przybliżone w kursie "Programowanie obiektowe". 

 

Operatory operujące na wskaźnikach (adresach) mogą być używane tylko w 
kodzie niezarządzanym (unsafe context). Jest to tzw. kod niebezpieczny i 
jest poza zakresem tego kursu. 

 

background image

Właściwości operatorów 

 

 

Operatory (funkcje operatorowe) charakteryzują się pewnymi właściwościami. 
Należą do nich: 

 

liczba argumentów 

 

priorytet 

 

łączność 

 

typ argumentów 

Ze względu na liczbę argumentów operatory możemy podzielić na: 

 

operatory jednoargumentowe (unary operators), np.: inkrementacji ++, 
dekrementacji --, minus jednoargumentowy -, ... 

 

operatory dwuargumentowe (binary operators), np.: operatory 
arytmetyczne, przypisania, relacyjne... 

 

operator trójargumentowy (ternary operator), istnieje tylko jeden - 
wyrażenie warunkowe (? :) 

Priorytet operatorów to inaczej kolejność działań. W wyrażeniach 
zawierających wiele operatorów priorytet (precedence) kontroluje, w jakiej 
kolejności poszczególne operatory są "obliczane". Rozważmy prosty przykład: 
 
double x = 10, y = 5, z = 2; 
double a = x + y * z; 
 
Wartością zmiennej a będzie 20, a nie 30, ponieważ najpierw zostanie 
wykonane mnożenie, ma wyższy priorytet, a dopiero następnie dodawanie, 

background image

czyli identycznie jak w matematyce. Kolejność działań możemy zmieniać 
stosując nawiasy. W języku C# do ustalenia kolejności działań możemy 
stosować tylko nawiasy okrągłe, wielokrotnie je zagnieżdżając. 
 
double x = 10, y = 5, z = 2; 
double a = (x + y) * z; 

 

//a = 30 

double b = (2*(x+y) + z) * 3; 

//b= 96 

 
Kolejność obliczeń wartości zmiennej b jest następująca: 

 

Obliczamy wartość wyrażenia znajdującego się w najbardziej 
zagnieżdżonych nawiasach, czyli x+y. Po uproszczeniu otrzymujemy 
wyrażenie (2*15+z)*3. 

 

Obliczamy wartość wyrażenia w nawiasie. Ponieważ mnożenie ma 
wyższy priorytet, jest wykonywane najpierw. Po wykonaniu działań w 
nawiasie otrzymujemy wyrażenie 32*3, którego wartość wynosi 96 

Nawiasy okrągłe stosowane są nie tylko w celu zmiany kolejności działań, ale 
również, aby wyrażenie stało się bardziej czytelne.  
Poniższa tabela przedstawia operatory w kolejności od najwyższego priorytetu 
do najniższego. Operatory należące do tej samej kategorii mają ten sam 
priorytet. 

Kategoria 

Operatory 

Operatory o 
najwyższym priorytecie 

x.y - dostęp do składowej - kropka 
f(x) - wywołanie metody  
a[x] - operator indeksowania [] 
x++ - inkrementacja przyrostkowa 
x-- - dekrementacja przyrostkowa 
new, typeof, checked, unchecked 

Jednoargumentowe 
(unary) 

 

+, -, - operatory jednoargumentowe plus i minus 
! - negacja logiczna 
~ - negacja bitowa (dopełnienie do dwóch) 
++x - inkrementacja przedrostkowa 
--x - dekrementacja przedrostkowa 
(T)x - operator rzutowania 

Operatory 
multiplikatywne 

* - mnożenie 
/ - dzielenie 
% - reszta z dzielenia 

Operatory addytywne 

+ - dodawanie 
- - odejmowanie 

Operatory przesunięcia  <<, >> 

Relacyjne i 
sprawdzające typ 

<, >, <=, >= 
is, as 

Równości 

==, != 

Iloczyn bitowy 
(Logical AND) 

Różnica symetryczna 
(Logical XOR) 

background image

Suma bitow 
(Logical OR) 

Koniunkcja 
(Conditional AND) 

&& 

Alternatywa 
(Conditional OR) 

|| 

Wyrażenie warunkowe 

? : 

Operatory przypisania 

=, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |= 

 

Nasuwa się pytanie, co będzie, jeżeli w wyrażeniu występują operatory o tym 
samym priorytecie. Kolejność działań w takim wypadku jest ustawiana na 
podstawie właściwości zwanej łącznością operatorów. Rozważmy następujący 
przykład: 
 
double x = 10, y = 5, z = 2; 
double a = x - y - z; 
 
Do zmiennej a zostanie podstawiona wartość 3, ponieważ najpierw zostanie 
wykonane odejmowanie x-y, a następnie od powyższego wyniku odjęta 
zostanie wartość z. Działania są wykonywane od lewej do prawej strony. O tak 
działających operatorach mówi się, że są lewostronnie łączne. 
Rozważmy teraz inny przykład: 
 
double x = 10, y = 5, z = 2; 
double a = x = y = z; 
 
Wszystkie zmienna x, y, z, a, po wykonaniu tego kodu będą miały wartość 2, 
ponieważ przypisanie jest wykonywane od prawej do lewej strony. Czyli 
najpierw zostanie wykonane y = z, gdzie wartością tego wyrażenia jest wartość 
stojąca po prawej stronie znaku równości. Wartość wyrażenia y = z, czyli w 
tym przypadku 2, zostanie następnie przypisana do x. O tak działających 
operatorach mówi się, że są prawostronnie łączne.  
Do operatorów prawostronnie łącznych należą wszystkie operatory 
jednoargumentowe, operatory przypisania oraz wyrażenie warunkowe ( ? :). 
Natomiast do operatorów lewostronnie łącznych należą wszystkie operatory 
dwuargumentowe poza operatorami przypisania. 

Typ argumentów stojących obok operatora wpływa na jego znaczenie. I tak 
operator +, gdy stoją obok niego wartości numeryczne oznacza dodawanie, 
natomiast w przypadku, gdy stoją zmienne typu string, oznacza łączenie 
napisów (konkatenację). 
W przypadku operatorów działających na typach numerycznych należy zwrócić 
uwagę na proces zwany promocją typów. 
W przypadku operatorów jednoargumentowych: +, -, ~, gdy ich argumentem 
jest zmienna typu sbyte lub byte lub short lub ushort lub char, 
automatycznie jej typ jest konwertowany do typu int. Dodatkowo dla 
operatora - zmienna typu uint jest konwertowana do typu long. Wobec 
powyższego poniższy kod spowoduje błąd kompilator, niedozwolonej 
konwersji niejawnej. 
 
short x = 10; 
short y = +x; 

background image

 
W przypadku natomiast operatorów dwuargumentowych: +, –, *, /, %, 
&, |, ^, ==, !=, >, <, >=, <= 

regułę promocji można podać w 

następujących punktach, których kolejność ma znaczenie: 

1.  Jeżeli jeden argument jest typu decimal, drugi argument jest 

konwertowany do typu decimal, albo jest generowany bład kompilacji 
gdy konwercja niejawna jest niedozwolona (drugi argument jest typu 
double lub float). 

2.  W przeciwnym wypadku, jeżeli jeden argument jest typu double drugi 

argument jest konwertowany do typu double. 

3.  W przeciwnym wypadku, jeżeli jedne argument jest typu float drugi 

argument jest konwertowany do typu float. 

4.  W przeciwnym wypadku, jeżeli jeden argument jest typu ulong drugi 

argument jest konwertowany do typu ulong, albo jest generowany bład 
kompilacji gdy drugim argumentem jest liczba ze zankiem (sbyte, 
short, int, long). 

5.  W przeciwnym wypadku, jeżeli jeden argument jest typu long drugi 

argument jest konwertowany do typu long. 

6.  W przeciwnym wypadku, jeżeli jeden argument jest typu uint drugi 

argument jest typu sbyte, short lub int oba argumenty 
konwertowane są do typu long. 

7.  W przeciwnym wypadku, jeżeli jeden argument jest typu uint drugi 

argument jest konwertowany do typu uint. 

8.  W przeciwnym wypadku, oba argumenty konwertowane są do typu int. 

Wobec powyższego poniższy kod spowoduje błąd kompilator, niedozwolonej 
konwersji niejawnej: 
 
short x = 10, y = 10; 
short z = x + y; 

background image

Pytania sprawdzające 

 

 

1.  Ile bajtów zajmuje zmienna typu char w języku C#? 

 
Odp. 
Dwa bajty. 

2.  Czy w języku C# można używać niezainicjalizowanych zmiennych? 

 
Odp. 
Nie, Przed użyciem każda zmienna musi być zainicjalizowana. 

3.  W jakiej przestrzeni nazw znajduje się klasa Console? 

 
Odp. 
W przestrzeni nazw System. 

4.  Jak wywoływana jest konwersja jawna? 

 
Odp. 
Konwersję jawną wywołujemy przy pomocy operatora rzutowania - (typ). 

5.  Podaj wartości zmiennych, po wykonaniu następującego kodu: 

int x = 10, y = 5, z =20; 
int a = z - x * y; 
int b = x++; 
double c = 11 / y; 
 
Odp. 
x = 11, y = 5, z = 20, a = -30, b = 10, c = 2.0 

background image

Laboratorium 

 

 

Ćwiczenie 1 
Utworzenie programu, który zamienia (wymienia) wartości dwóch zmiennych. 
Algorytm ten po angielsku nosi nazwę Swap (zamiana). Jest to jeden z 
podstawowych algorytmów używany do budowy bardziej skomplikowanych 
programów. 

1.  Uruchom Visual Studio 

Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy 
następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005

2.  Utwórz nowy projekt 

a.  Z menu File wybierz New/Project... 

b.  W oknie dialogowym New Project określ następujące właściwości: 

i.  typu projektu: Visual C#/Windows  

ii.  szablon: Console Application  

iii.  lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\ 

iv.  nazwa projektu: Zamiana.  

v.  nazwa rozwiązania: Lab2 

3.  Wewnątrz metody Main napisz następujący kod: 

a.  Zadeklaruj trzy zmienne rzeczywiste a, b, tmp. Zmienna a i b są to te 

zmienne, między którymi będziemy wymieniać wartości, zmienna tmp 
jest zmienną pomocniczą: 

background image

 
double a, b, tmp; 

b.  Pobierz od użytkownika wartości zmiennych a i b: 

 
Console.Write("Podaj wartość zmiennej a: "); 
a = Convert.ToDouble(Console.ReadLine()); 
Console.Write("Podaj wartość zmiennej b: "); 
b = Convert.ToDouble(Console.ReadLine()); 

c.  Wymień wartości zmiennych a i b, przy pomocy zmiennej tmp. 

 
tmp = a; 
a = b; 
b = tmp; 

d. 

Wypisz wartości zmiennych po wymianie, a następnie zatrzymaj 
działanie programu: 
 
Console.WriteLine("a = {0}, b = {1}", a, b); 
Console.ReadKey(); 

4.  Skompiluj i uruchom program. 

 

Ćwiczenie 2 
Utworzenie programu, który oblicza wartość wyrażenia: 

 

 

 

1.  Dodaj do bieżącego rozwiązania nowy projekt 

a.  Z menu File wybierz Add/New Project... 

b.  W oknie dialogowym Add New Project określ następujące 

właściwości: 

i. 

typu projektu: Visual C#/Windows  

ii. 

szablon: Console Application  

iii. 

nazwa projektu: Wyrazenie. 

2.  Uczyń nowo utworzony projekt projektem startowym 

a.  Zaznacz projekt Wyrazenie  w okienku Solution Explorer i z menu 

kontekstowego wybierz Set as StartUp Project. 

albo, gdy rozpoczynasz laboratorium od tego ćwiczenia 

1.  Uruchom Visual Studio 

Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy 
następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005

2.  Utwórz nowy projekt 

a.  Z menu File wybierz New/Project... 

b.  W oknie dialogowym New Project określ następujące właściwości: 

)

1

(

3

4

2

z

y

x

v

background image

i.  typu projektu: Visual C#/Windows  

ii.  szablon: Console Application  

iii.  lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\ 

iv.  nazwa projektu: Wyrazenie.  

v.  nazwa rozwiązania: Lab2 

3.  Wewnątrz metody Main napisz następujący kod: 

a.  Zadeklaruj cztery zmienne rzeczywiste x, y, z, v.  

 
double x,y,z,v; 

b.  Pobierz od użytkownika wartości zmiennych x, y i z: 

 
Console.Write("Podaj wartość zmiennej x: "); 
x = Convert.ToDouble(Console.ReadLine()); 
Console.Write("Podaj wartość zmiennej y: "); 
y = Convert.ToDouble(Console.ReadLine()); 
Console.Write("Podaj wartość zmiennej z: "); 
z = Convert.ToDouble(Console.ReadLine()); 

c. 

Napisz zadany wzór z użyciem operatorów języka C#, wartość 
utworzonego wyrażenia wstaw do zmiennej v: 
 
v = (4*x-y)/(3*(z*z+1)); 

d. 

Wypisz wartości obliczonego wyrażenia, a następnie zatrzymaj 

działanie programu: 

Console.WriteLine("Wartość wyrażenia wynosi:  
 

¬{0}.", v); 

Console.ReadKey(); 

4.  Skompiluj i uruchom program. 

 

Ćwiczenie 3 
Program obliczający pole i obwód koła o zadanym promieniu 

 

1.  Dodaj do bieżącego rozwiązania nowy projekt 

a.  Z menu File wybierz Add/New Project... 

b.  W oknie dialogowym Add New Project określ następujące 

właściwości: 

i. 

typu projektu: Visual C#/Windows  

ii. 

szablon: Console Application  

iii. 

nazwa projektu: Kolo. 

2.  Uczyń nowo utworzony projekt projektem startowym 

a.  Zaznacz projekt Kolo w okienku Solution Explorer i z menu 

kontekstowego wybierz Set as StartUp Project. 

background image

albo, gdy rozpoczynasz laboratorium od tego ćwiczenia 

1.  Uruchom Visual Studio 

Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy 
następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005

2.  Utwórz nowy projekt 

a. 

Z menu File wybierz New/Project... 

b.  W oknie dialogowym New Project określ następujące właściwości: 

i.  typu projektu: Visual C#/Windows  

ii.  szablon: Console Application  

iii. lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\ 

iv. nazwa projektu: Kolo.  

v. nazwa rozwiązania: Lab2 

3.  Wewnątrz metody Main napisz następujący kod: 

a. 

Zadeklaruj zmienną rzeczywistą r.  
 
double r; 

b.  Pobierz od użytkownika długość promienia: 

 
Console.Write("Podaj długość promienia: "); 
r = Convert.ToDouble(Console.ReadLine()); 

c.  Zadeklaruj zmienne pole oraz obwod i odpowiednio je zainicjalizuj. 

We wzorach na obwód i pole skorzystaj ze stałej Math.PI. 
 
double pole = Math.PI * r * r; 
double obwod = 2 * Math.PI * r; 

d.  Wypisz obliczone wartości pola i obwodu koła z dokładnością do 

trzech miejsc po przecinku, a następnie zatrzymaj działanie programu: 
 
Console.WriteLine("Pole koła o promieniu {0} 
 

 

¬wynosi: {1:f3}.", r, pole); 

Console.WriteLine("Obwód koła o promieniu {0} 
 

 

¬wynosi: {1:f3}.", r, obwod); 

Console.ReadKey(); 

4.  Skompiluj i uruchom program. 

 

Ćwiczenie 4 
Program obliczający cenę brutto oraz podatek od podanej ceny netto.. 

 

1.  Dodaj do bieżącego rozwiązania nowy projekt 

a.  Z menu File wybierz Add/New Project... 

b.  W oknie dialogowym Add New Project określ następujące 

właściwości: 

background image

i.  typu projektu: Visual C#/Windows  

ii.  szablon: Console Application  

iii.  nazwa projektu: Podatek. 

2.  Uczyń nowo utworzony projekt projektem startowym 

a.  Zaznacz projekt Podatek w okienku Solution Explorer i z menu 

kontekstowego wybierz Set as StartUp Project. 

albo, gdy rozpoczynasz laboratorium od tego ćwiczenia 

1.  Uruchom Visual Studio 

Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy 
następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005

2.  Utwórz nowy projekt 

a.  Z menu File wybierz New/Project... 

b.  W oknie dialogowym New Project określ następujące właściwości: 

i. 

 typu projektu: Visual C#/Windows  

ii. 

 szablon: Console Application  

iii. 

lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\ 

iv. 

nazwa projektu: Podatek.  

v. 

nazwa rozwiązania: Lab2 

3.  Wewnątrz metody Main napisz następujący kod: 

a.  Zadeklaruj stałą symboliczną rzeczywistą o dużej precyzji o nazwie 

Vat 

i nadaj jej wartość 0,22.  

 
const decimal Vat = 0.22M; 

b.  Zadeklaruj zmienną rzeczywistą o dużej precyzji netto. 

 
decimal netto; 

c. 

Pobierz od użytkownika cenę netto: 
 
Console.Write("Podaj cenę netto: "); 
netto = Convert.ToDecimal(Console.ReadLine()); 

d.  Zadeklaruj zmienne podatek oraz brutto i odpowiednio je 

zainicjalizuj.. 
 
decimal podatek = Vat * netto; 
decimal brutto = netto + podatek; 

e. 

Wypisz obliczone wartości podatku i ceny brutto, dodając symbol 
waluty, a następnie zatrzymaj działanie programu: 
 
Console.WriteLine("Cena wynosi {0:C}, w tym  
 

¬kwota podatku: {1:C}.", brutto, podatek); 

Console.ReadKey(); 

4.  Skompiluj i uruchom program. 

background image

 

Ćwiczenie 5 
Program wyznaczający maksimum z dwóch liczb całkowitych przy pomocy 
wyrażenia warunkowego.. 

 

1.  Dodaj do bieżącego rozwiązania nowy projekt 

a.  Z menu File wybierz Add/New Project... 

b.  W oknie dialogowym Add New Project określ następujące 

właściwości: 

i.  typu projektu: Visual C#/Windows  

ii.  szablon: Console Application  

iii.  nazwa projektu: Maksimum. 

2.  Uczyń nowo utworzony projekt projektem startowym 

a.  Zaznacz projekt Maksimum w okienku Solution Explorer i z menu 

kontekstowego wybierz Set as StartUp Project. 

albo, gdy rozpoczynasz laboratorium od tego ćwiczenia 

1.  Uruchom Visual Studio 

Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy 
następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005

2.  Utwórz nowy projekt 

a.  Z menu File wybierz New/Project... 

b.  W oknie dialogowym New Project określ następujące właściwości: 

i.   typu projektu: Visual C#/Windows  

ii.   szablon: Console Application  

iii.  lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\ 

iv.  nazwa projektu: Maksimum.  

v.  nazwa rozwiązania: Lab2 

3.  Wewnątrz metody Main napisz następujący kod: 

a.  Zadeklaruj zmienne całkowite: a, b, max. 

 
int a, b, max; 

b. 

Pobierz od użytkownika wartości zmiennych a i b: 
 
Console.Write("Podaj pierwszą wartość: "); 
a = Convert.ToInt32(Console.ReadLine()); 
Console.Write("Podaj drugą wartość: "); 
b = Convert.ToInt32(Console.ReadLine()); 

c.  Wyznacz wartość maksymalną z liczb a i b: 

 
max = a > b ? a : b; 

background image

d.  Wypisz obliczoną wartość maksymalną, a następnie zatrzymaj 

działanie programu: 
 
Console.WriteLine("Wartość maksymalna wynosi:  
 

 

¬{0}.", max); 

Console.ReadKey(); 

4.  Skompiluj i uruchom program.