Tablice
Przegląd zagadnień
W module tym zostanie zaprezentowana pierwsza z struktur danych
omawianych w tym kursie - tablica. Tablice bardzo się przydają, gdy trzeba
wykonać szereg operacji na pewnej grupie zmiennych tego samego typu.
Po skończeniu tego modułu studenci powinni:
Widzieć, co to jest tablica.
Potrafić zdefiniować tablice w języku C#.
Potrafić korzystać z tablic.
Potrafić używać pętli foreach.
Definicja tablicy
Tablica jest ciągiem zmiennych tego samego typu, które będziemy dalej
nazywać elementami tablicy. Każdy element tablicy może być wybrany w
dowolnej kolejności i jest dostępny w tym samym czasie. Właściwość, że
tablica jest zbudowana z elementów tego samego typu, nazywamy
jednorodnością. Typ elementu nazywamy typem podstawowym tablicy.
Struktury danych, której wszystkie składowe są jednakowo dostępne,
określamy jako struktury o dostępie swobodnym (random access). Liczba
elementów tablicy jest stała. Nie może być zmieniana w czasie działania
programu i musi być podana w czasie jej tworzenia. Zmianę liczby elementów
tablicy jest pozorowana przez utworzenie nowej tablicy i skopiowanie
odpowiednich elementów tablicy źródłowej do nowo utworzonej tablicy.
Dodatkową właściwością wynikającą z implementacji jest ciągłość, czyli
elementy (zmienne) z których zbudowana jest tablica, zajmują ciągły obszar
pamięci.
Uwaga:
Ciągłość tablicy w przypadku tablicy, której typem podstawowym jest typ
referencyjny, nie pociąga za sobą ciągłości obszaru pamięci zajmowanej przez
obiekty danego typu. Występuje tylko ciągłość pamięci zajmowanej przez
zmienne - odwołania.
W celu wybrania pojedynczego elementu tablicy posługujemy się tzw.
indeksem.
Tworzenie tablic w C#
Zmienną typu tablicowego definiuje się przez podanie typu podstawowego
tablicy, następnie występują nawiasy kwadratowe, po których umieszcza się
nazwę zmienne tablicowej. Nazwa ta podlega tym samym regułom, co nazwy
zwykłych zmiennych, czyli może składać się z cyfr, liter, znaku podkreślenia;
nie może zaczynać się od cyfry; nie może być słowem kluczowym; musi być
unikalna w danym bloku kodu:
typ [] nazwa;
Typ tablicowy jest typem referencyjnym. Deklaracja zmiennej tablicowej nie
tworzy więc automatycznie tablicy - obiektu tablicy. Do utworzenia obiektu
tablicy używa się operatora new. Obiekt tablicy można utworzyć zarówno w
miejscu deklaracji zmiennej tablicowej:
typ [] nazwa = new typ[ilosc_Elementow];
jak również w dalszej części programu, po deklaracji zmiennej tablicowej:
typ [] nazwa;
...
nazwa = new typ[ilosc_Elementow];
Podczas definicji obiektu tablicowego musimy podać ilość elementów, z
których składa się tablica - wyrażenie ilosc_Elementow. Wartość
wyrażenie ilosc_Elementow musi być liczbą całkowitą większą lub równą
zero. Wartość ta nie musi być znana w czasie kompilacji, czyli wyrażenie
ilosc_Elementow może zawierać odwołanie do zmiennych
Przykłady definicji tablic:
1.
Tablica sześciu liczb rzeczywistych:
double [] liczby = new double[6];
2. Tablica n elementowa obiektów typu string, gdzie n jest liczbą podaną
przez użytkownika:
Console.Write("Podaj liczbę elementów tablicy: ");
uint n = Convert.ToUInt32(Console.ReadLine());
string [] napisy = new string[n];
W przypadku definicji tablicy, w pierwszy nawiasach kwadratowych nie wolno
umieszczać żadnych wyrażeń. Nawisy kwadratowe muszą występować między
nazwa typu a nazwą zmiennej. Poniższa linijki spowodują błąd kompilacji:
short [
3
] tab1 = new short[3];
short tab2
[]
= new short[3];
Uwaga:
Istnieje również możliwość alokacji bloku pamięci na stosie przy pomocy
słowa stackalloc. Więcej informacji na temat słowa kluczowego
stackalloc można znaleźć w MSDN Library
Tablice wielowymiarowe
W języku C# oprócz tablic jednowymiarowych, którą możemy wyobrazić sobie
jako wektor, istnieją również tablice wielowymiarowe. Tablicę dwuwymiarową
możemy przedstawić w postaci macierzy. Wymiar tablicy możemy określić
jako liczbę indeksów związanych z elementem tablicy. Przykładem tablicy
wielowymiarowej może być tablica zawierająca oceny różnych uczniów z
różnych przedmiotów, którzy uczęszczają do różnych klas w różnych szkołach.
Poszczególne indeksy w takiej tablicy będą związane z wyborem szkoły,
wyborem klasy oraz określeniem przedmiotu i ucznia.
Zmienną zawierającą odwołanie do tablicy wielowymiarowej deklarujemy
umieszczając przecinki w nawiasach kwadratowych. Wymiar tablicy będzie
równy liczbie przecinków plus jeden.
int [,] tab2;
//tablica dwuwymiarowa
int [,,] tab3;
//tablica trójwymiarowa
int [,,,] tab;
//tablica czteromiarowa
Do utworzenia obiektu tablicy wielowymiarowej, podobnie jak w przypadku
tablicy jednowymiarowej, używa się operatora new i można go utworzyć
zarówno w miejscu deklaracji zmiennej tablicowej:
typ [,] nazwa = new typ[wyrazenie1, wtrazenie2];
jak również w dalszej części programu, po deklaracji zmiennej tablicowej:
typ [,] nazwa;
...
nazwa = new typ[wyrazenie1, wyrazenie2];
Gdzie wyrazenie1 oraz wyrazenie2 określają rozmiar tablicy w
poszczególnych wymiarach, czyli liczbę elementów w poszczególnych
wymiarach.
Ilość elementów tablicy wielowymiarowej można uzyskać mnożąc przez siebie
rozmiary tablicy w poszczególnych wymiarach. W powyższym przykładzie
liczba wszystkich elementów tablicy jest równa iloczynowi:
wyrazenie1*wyrazenie2.
W języku C# istnieje również możliwość utworzenia tablicy nieregularnej, czyli
np. w przypadku tablicy dwuwymiarowej, takiej tablicy, która ma różną liczbę
elementów w poszczególnych wierszach.
Zmienną takiej tablicy tworzymy w następujący sposób:
typ [][] nazwa;
Powyższa instrukcja deklaruje zmienną tablicową, która może zawierać
odwołanie do tablicy jednowymiarowej, której elementy są tablicami. Czyli
tablica nieregularna w języku C# traktowana jest jako tablica jednowymiarowa,
której elementy są tablicami. Ponieważ jednak przy zmiennej tablicowej
nieregularnej może wystąpić wiele indeksów, będziemy mówili o wielu
wymiarach tablicy nieregularnej.
Obiekty tablic nieregularnych możemy również tworzyć w miejscu deklaracji
zmiennej tablicowej, jak i w dalszej części programu. W przypadku tworzenia
tablic nieregularnych rozmiar podajemy tylko dla pierwszego wymiaru. Podanie
rozmiaru dla większej ilości wymiarów powoduje błąd kompilatora.
typ [][] nazwa2 = new typ[2][];
Powyższa instrukcja tworzy tablicę dwuelementową, której elementami są
tablice. Tablice składowe, wiersze macierzy, tworzymy w następnych
instrukcjach.
nazwa2[0] = new typ[4];
nazwa2[1] = new typ[3];
Pierwszy wiersz macierzy, w wyniku wykonania powyższego kodu, będzie
miał cztery elementy, drugi natomiast trzy. Więcej na temat odwołania się do
poszczególnych elementów tablicy będzie przedstawione w dalszej części tego
modułu.
Można również łączyć definicję tablic regularnych z nieregularnymi np.:
double [][,] t1 = new double[2][,];
double [,][] t2 = new double[3,2][];
Inicjalizacja tablic
Podczas tworzenia tablicy (obiektu tablicowego), wszystkim jej elementom
przypisywana jest niejawnie wartość reprezentująca zero danego typu. Dla
typów liczbowych jest to 0, dla typu logicznego false, dla typów
referencyjnych null. W języku C# podczas tworzenia tablicy, można również
nadać własne wartości poszczególnym elementom tablicy. Jeżeli
zdecydowaliśmy się na ustawienie wartości elementów tablicy, musimy podać
wartości dla wszystkich elementów tablicy. Poszczególne wartości oddzielamy
przecinkami i umieszczamy w nawiasach klamrowych np.:
string [] zwierzeta = new string[3]{"lis", "lew",
"kot"};
Pierwszemu elementowi tablicy zostanie nadana wartość lis, drugiemu lew,
trzeciemu kot. W przypadku, gdy podczas tworzenia tablicy podajemy
wartości elementów tablicy, rozmiar musi być znany w czasie kompilacji - musi
być wartością stałą. Rozmiar można jednak pominąć, kompilator sam wyliczy
rozmiar:
string [] zwierzeta = new string[]{"lis", "lew",
"kot"};
Zapis utworzenia zainicjalizowanej tablicy można jeszcze bardziej uprościć,
pomijając część new typ[rozmiar]:
string [] zwierzeta = {"lis", "lew", "kot"};
W przypadku, gdy tablicę nie tworzymy w miejscu deklaracji zmiennej
tablicowej, ale w dalszej części programu, dopuszczalne są formy:
const int IloscZwierzat = 3;
string [] zwierzeta;
...
zwierzeta = new string[IloscZwierzat]{"lis",
"lew", "kot"};
oraz
string [] zwierzeta;
...
zwierzeta = new string[]{"lis", "lew", "kot"};
Poniższy zapis natomiast spowoduje błąd kompilatora:
string [] zwierzeta;
...
zwierzeta = {"lis", "lew", "kot"};
//błąd
Tablice wielowymiarowe można również inicjalizować. Wykonuje się to w
następujący sposób:
string [,] zwierzeta = {
{"kruk", "bocian", "orzeł"},
{"lis", "lew", "kot"},
{"pszczoła", "osa", "komar"}
};
// tablica 3x3
lub (z tym że przykład dla tablicy trójwymiarowej)
string [,,] zwierzeta;
...
zwierzeta = new string[,,]{
{{"kura", "gęś"}, {"orzeł", "sokół"}},
{{"pies", "kot"}, {"lew", "tygrys"} },
{{"pszczoła","jedwabnik"},{"osa","komar"}}
};
// tablica 3x2x2
W przypadku tablic regularnych oczywiście trzeba pamiętać o jednakowej
liczbie elementów w poszczególnych wymiarach
Tablice nieregularne tworzymy w następujący sposób:
string [][] zwierzeta = {
new string[]{"lew","tygrys"},
new string[]{"kruk", "sęp", "orzeł", "gil"},
new string[]{"osa"}
};
lub (z tym że przykład dla tablicy trójwymiarowej)
string [][][] zwierzeta;
...
zwierzeta = new string[][][]{
new string[][]{
new string[]{"pies", "kot","koń"},
new string[]{"tygrys"}
}
new string[][]{
new string[]{"kura", "gęś", "indyk"}
}
};
Jak widać w powyższym przykładzie, podtablice tablicy tablic, czyli składowe
tablicy nieregularnej, musimy tworzyć przy pomocy operatora new.
Korzystanie z tablic
Do pojedynczego elementu tablicy uzyskuje się dostęp przy pomocy operatora
indeksowania. W języku C# operatorem indeksowania są nawiasy kwadratowe
[]. W każdym wymiarze elementy tablicy indeksujemy od wartości zero do
rozmiaru danego wymiaru minus jeden. Czyli jeżeli utworzymy tablicę
jednowymiarową o trzech elementach:
char tab = new char[3];
to:
tab[0] - pierwszy element tablicy
tab[1] - drugi element tablicy
tab[2] - trzeci, ostatni element tablicy
Jeżeli w programie nastąpi odwołanie do nieistniejącego elementu tablicy, czyli
do elementu o indeksie mniejszym od zera albo o wartości indeksu większej lub
równej liczbie elementów w danym wymiarze, spowoduje to zgłoszenie
wyjątku IndexOutOfRangeException.
W przypadku tablic wielowymiarowych regularnych, aby uzyskać dostęp do
elementu tablicy stosujemy następującą notację:
int [,] tab1 = {{1,2,3},{4,5,6}};
tab1[0,0] = 10;
Console.WriteLine(tab1[1,1]);
//5
//tab[2][0] //nie ma takiego elementu
//byłby zgłoszony wyjątek
Dla tablic nieregularnych używamy następującą notację
int [][] tab2 = {
new int[]{1,2,3},
new int[]{4,5,6}
};
tab2[0][0] = 10;
Console.WriteLine(tab1[1][2]);
//6
//tab[1][3] //nie ma takiego elementu,
//byłby zgłoszony wyjątek
Uwaga:
W języku C# istnieje możliwość utworzenia tablicy, której dolny indeks jest
różny od wartości zero. Można to wykonać przy pomocy jednej z metod
CreateInstance klasy Array.
Właściwości tablic
O tablicach w języku C#, można powiedzieć, że są strukturami samo
opisującymi się. Przy pomocy nazwy zmiennej tablicowej, można uzyskać
informację na temat liczby jej wszystkich elementów, liczby wymiarów tablicy,
liczby elementów w poszczególnych rozmiarach.
Uwaga:
Informacje opisane powyżej możemy uzyskać przy pomocy właściwości lub
wywołania metody na rzecz jakiegoś obiektu tablicowego. Właściwości oraz
metody wywoływane na rzecz obiektu danej klasy zostaną dokładnie omówione
w kursie "Programowanie obiektowe".
W celu uzyskania informacji na temat liczby wymiarów korzystamy z
właściwości Rank.
int [] tab1 = new int[3];
Console.WriteLine(tab1.Rank);
int [,,] tab2 = new int[3,2,2];
Console.WriteLine(tab2.Rank);
Na ekranie zostanie wypisane:
1
3
W przypadku tablic nieregularnych, tablica jest traktowana jako tablica
jednowymiarowa, której elementami są tablice. Poniższy kod spowoduje, więc
wypisanie na ekranie wartości 1.
int [][][] tab3 = new int[4][][];
Console.WriteLine(tab3.Rank);
Właściwość Length oraz LongLength służą do otrzymania liczby
wszystkich elementów tablicy.
int [] tab1 = new int[3];
Console.WriteLine(tab1.Length);
int [,,] tab2 = new int[3,2,2];
Console.WriteLine(tab2.Length);
Na ekranie zostanie wypisane:
3
12
W przypadku tablic nieregularnych, podobnie jak wcześniej, tablica jest
traktowana jako tablica jednowymiarowa, której elementami są tablice.
Właściwość Length zawiera, więc liczbę podtablic. Poniższy kod spowoduje
wypisanie na ekranie wartości 2.
int [][]tab3 = new int[2][]{
new int[4], new int[7]};
Console.WriteLine(tab3.Length);
I oczywiście
...
Console.WriteLine(tab3[0].Length);
Console.WriteLine(tab3[1].Length);
spowoduje pojawienie się na ekranie:
4
7
W celu uzyskania liczby elementów w poszczególnych wymiarach korzysta się
z metody GetLength lub GetLongLength. Wymiary indeksujemy od
wartości zero:
int [,,] tab2 = new int[3,8,2];
Console.WriteLine(tab2. GetLength(0)); //pierwszy wym.
Console.WriteLine(tab2. GetLength(1)); //drugi wym.
Console.WriteLine(tab2. GetLength(2)); //trzeci wym.
Na ekranie zostanie wypisane:
3
8
2
Odwołanie się do nieistniejącego wymiaru spowoduje zgłoszenie wyjątku
IndexOutOfRangeException.
Użycie tablicy z pętlą foreach
Załóżmy, że jest potrzebne wypisanie wartości wszystkich elementów tablicy.
Kod przy pomocy instrukcji for mógłby wyglądać następująco:
int [] t = new int[10];
...
for(int i = 0; i<t.Length; i++)
{
Console.Write ("{0}, ",t[i]);
}
Dla tablicy dwuwymiarowej natomiast:
int [,] tt = new int[10,20];
...
for(int i = 0; i<tt.GetLength(0); i++)
{
for(int j = 0; j<tt.GetLength(1); j++)
{
Console.Write("{0}, ", tt[i,j]);
}
}
Powyższy kod można również zapisać przy pomocy instrukcji foreach
int [] t = new int[10];
...
foreach(int element in t)
{
Console.WriteLine("{0}", element);
}
oraz dla tablicy dwuwymiarowej regularnej:
int [,] tt = new int[10,20];
...
foreach(int element in tt)
{
Console.Write("{0}, ",element);
}
Korzystając z pętli foreach, myślimy raczej o wykonaniu pewnej grupy
instrukcji dla każdego elementu tablicy, niż o wykonaniu pewnej grupy
instrukcji określoną ilość razy.
W nawiasach okrągłych, występujących obok słowa foreach, deklarujemy
zmienną, która w bloku instrukcji reprezentuje aktualnie przetwarzany element
tablicy. Zmienną tą nazywamy zmienną iteracyjną pętli foreach. Typ
zmiennej iteracyjnej musi być identyczny z typem elementu tablicy lub musi
istnieć do niego konwersja niejawna z typu elementu tablicy. Jako zmiennej
iteracyjnej nie można użyć zmiennej zadeklarowanej wcześniej w programie.
Wartości zmiennej iteracyjnej nie można zmieniać, jest tylko do odczytu.
Uwaga:
W nawiasach okrągłych, występujących obok słowa foreach, po słowie in,
mogą występować zmienne zawierające uchwyt do obiektów klas kolekcji.
Klasy kolekcji w języku C#, są to klasy, które implementują interfejs
IEnumerable lub posiadają odpowiednią metodę GetEnumerator.
Więcej na temat interfejsów można znaleźć w kursie "Programowanie
obiektowe".
Pytania sprawdzające
1. Jak są indeksowane tablice w języku C#?
Odp.
Tablice w języku C# indeksowane są od wartości zero do n, gdzie n jest
rozmiarem danego wymiaru.
2. Jaki błąd popełniono w poniższym kodzie?
string [] jeziora;
jeziora = {"Śniardwy", "Mamry", "Bajkał"};
Odp.
Tablice można tworzyć bez użycia słowa new, tylko w miejscu deklaracji
zmiennej tablicowej. Powyższy kod należy zapisać:
string [] jeziora;
jeziora=new string[]{"Śniardwy","Mamry","Bajkał"};
lub
string [] jeziora={"Śniardwy", "Mamry", "Bajkał"};
3. Co się stanie, gdy odwołamy się do nieistniejącego elementu tablicy?
Odp.
W momencie próby odwołania się do nieistniejącego elementu tablicy
zostanie zgłoszony wyjątek IndexOutOfRangeException.
4.
Utwórz pięcioelementową tablicę liczb całkowity i zainicjalizuj ją kolejnymi
liczbami naturalnymi nieparzystymi.
Odp.
byte [] liczby = {1,3,5,7,9};
5. Jaki błąd popełniono w poniższym kodzie?
int [] numery = {13, 44, 777, 818};
...
foreach(int el in numery)
el++;
Odp.
Zmienna iteracyjna pętli foreach jest zmienną tylko do odczyt i nie
można zmieniać jej wartości.
Laboratorium
Ćwiczenie 1:
Napisz program, który znajduje największy i najmniejszy element tablicy.
Tablicę zainicjalizuj liczbami pseudolosowymi, korzystając z generatora liczb
pseudolosowych:
Random r = new Random(); //utworzenie obiektu
//generatora liczb pseudolosowych
int n = r.Next(0,101); //losowanie liczby z
//przedziału <0;100>
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: MaxMin.
v. nazwa rozwiązania: Lab6
3. Wewnątrz metody Main napisz następujący kod:
a. Utwórz obiekt tablicy piętnastoelementowej liczb całkowitych.
int [] tablica = new int[15];
b. Nadaj elementom tablicy wartości losowe z przedziału od zera do stu,
korzystając z generatora liczb pseudolosowych.
Random generator = new Random();
for(int i = 0; i < tablica.Length; i++)
{
tablica[i] = generator.Next(0,101);
}
c. Wypisz wartości elementów tablicy korzystając z pętli foreach.
Console.WriteLine("Wylosowano następujące
¬wartości");
foreach(int i in tablica)
{
Console.Write("{0}, ", i);
}
d. Zadeklaruj zmienną indexMax i ustaw jej wartość na wartość zero.
Dla każdego elementu tablicy sprawdzaj, czy jego wartość jest większa
od wartości elementu tablicy o indeksie indexMax. Jeżeli jest
większa, ustaw wartość zmiennej indexMax na numer jego indeksu.
int indexMax = 0;
for(int i = 1; i < tablica.Length; i++)
{
if(tablica[indexMax] < tablica[i])
{
indexMax = i;
}
}
e. Zadeklaruj zmienną indexMin i ustaw jej wartość na wartość zero.
Dla każdego elementu tablicy sprawdzaj, czy jego wartość jest
mniejsza od wartości elementu tablicy o indeksie indexMin. Jeżeli
jest mniejsza, ustaw wartość zmiennej indexMin na numer jego
indeksu.
int indexMin = 0;
for(int i = 1; i < tablica.Length; i++)
{
if(tablica[indexMin] > tablica[i])
{
indexMin = i;
}
}
f. Uwaga:
Wyznaczenie numeru indeksu elementu maksymalnego i minimalnego
można oczywiście wykonać w pojedynczej pętli:
int indexMax = 0;
int indexMin = 0;
for(int i = 1; i < tablica.Length; i++)
{
if(tablica[indexMin] > tablica[i])
{
indexMin = i;
}
if(tablica[indexMax] < tablica[i])
{
indexMax = i;
}
}
g. Wypisz na ekranie wartości elementu największego i najmniejszego
oraz numery ich indeksów. Zatrzymaj program, aby użytkownik mógł
obejrzeć wyniki:
Console.WriteLine("\n\nElemnt najmniejszy o
¬indeksie {0} posiada wartość {1}.",
indexMin, tablica[indexMin]);
Console.WriteLine("Elemnt największy o indeksie
¬{0} posiada wartość {1}.",
indexMax, tablica[indexMax]);
Console.ReadKey();
4. Skompiluj i uruchom program.
Ćwiczenie 2
Utwórz programu, który oblicza iloczyn dwóch macierzy. Wartości elementów
macierzy są podawane przez użytkownika.
Wartości elementów macierzy C = A x B, można wyliczyć ze wzoru:
N - liczba wierszy macierzy A i C.
M - liczba kolumn macierzy B i C
K - liczba kolumn macierzy A i liczba wierszy macierzy B
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: MnozenieMacierzy.
2. Uczyń nowo utworzony projekt projektem startowym
a. Zaznacz projekt MnozenieMacierzy w okienku Solution Explorer i z
menu kontekstowego wybierz Set as StartUp Project.
M
j
N
i
gdzie
b
a
c
K
k
kj
ik
ij
...
1
;
...
1
,
1
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: MnozenieMacierzy.
v. nazwa rozwiązania: Lab6
3. Wewnątrz metody Main napisz następujący kod:
a. Zadeklaruj trzy stałe całkowite reprezentujące odpowiednio
i. N - liczba wierszy macierzy A i C.
ii. M - liczba kolumn macierzy B i C
iii. K - liczba kolumn macierzy A i liczba wierszy macierzy B
const int N = 3;
const int M = 3;
const int K = 2;
b. Zdefiniuj trzy tablice dwuwymiarowe o rozmiarach: NxK, KxM oraz
NxM.
double [,] macierzA = new double[N,K];
double [,] macierzB = new double[K,M];
double [,] macierzC = new double[N,M];
c.
Pobierz od użytkownika wartości elementów macierzy A oraz
macierzy B.
Console.WriteLine("Podaj elementy macierzy A.");
for(int i=0; i<N; i++)
{
for(int j=0; j<K; j++)
{
Console.Write("A[{0},{1}] = ", i+1,j+1);
macierzA[i,j] = Convert.ToDouble(
Console.ReadLine() );
}
}
Console.WriteLine("Podaj elementy macierzy B.");
for(int i=0; i<K; i++)
{
for(int j=0; j<M; j++)
{
Console.Write("B[{0},{1}] = ", i+1,j+1);
macierzB[i,j] = Convert.ToDouble(
Console.ReadLine() );
}
}
d.
Oblicz elementy macierzy C.
for(int i = 0; i<N; i++)
{
for(int j = 0; j<M; j++)
{
macierzC[i,j] = 0;
for(int k=0; k<K; k++)
{
macierzC[i,j]+=macierzA[i,k]*macierzB[k,j];
}
}
}
Uwaga:
W bieżącym programie linijka macierzC[i,j] = 0; jest zbyteczna,
ponieważ domyślnie wszystkie elementy macierzy C zostały
zainicjalizowane wartością zero. Umieszczenie jej ma na celu pokazanie
ogólnego algorytmu mnożenia macierzy, również wtedy, gdy elementy
macierzy wynikowej nie mają wartości zero.
e. Wypisz elementy macierzy C. Zatrzymaj program, aby użytkownik
mógł obejrzeć wyniki:
Console.WriteLine("\nWynikiem mnożenia podanych
¬macierzy jest macierz:");
for(int i = 0; i<macierzC.GetLength(0); i++)
{
for(int j = 0; j<macierzC.GetLength(1); j++)
{
Console.Write("{0,10}, ", macierzC[i, j]);
}
Console.WriteLine();
}
Console.ReadKey();
4. Skompiluj i uruchom program.
Ćwiczenie 3
Napisz program, które losuje sześć różnych liczb całkowitych z przedziału
<1;49>.
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: TotoLotek.
2. Uczyń nowo utworzony projekt projektem startowym
a. Zaznacz projekt TotoLotek 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: TotoLotek.
v. nazwa rozwiązania: Lab6
3. Wewnątrz metody Main napisz następujący kod:
a. Zdefiniuj tablicę jednowymiarową, która będzie zawierać sześć
wylosowanych liczb:
byte [] numery = new byte[6];
b. Wypełnij tablicę liczbami wylosowanymi przez generator liczb
pseudolosowych. Zanim przejdziesz do losowania następnej liczby
sprawdź, czy wylosowana liczba, nie była wylosowana wcześniej.
Jeżeli dana liczba była już wylosowana wcześniej, powtórz losowanie
dla danego elementu tablicy.
Random generator = new Random();
int index = 0;
//ile wylosowano liczb
int i;
bool flaga;
do
{
numery[index] = (byte)generator.Next(1,50);
flaga = true;
for(i=0; i<index; i++)
{
if(numery[index] == numery[i])
{
flaga = false;
break;
}
}
if(flaga)
{
index++;
}
}
while(index<6);
c. Wypisz wylosowane liczby. Zatrzymaj program, aby użytkownik mógł
obejrzeć wyniki.
Console.WriteLine("Wylosowane liczby to:");
foreach(int numer in numery)
{
Console.Write("{0}, ",numer);
}
Console.ReadKey();
4. Skompiluj i uruchom program.
Ćwiczenie 4
Napisz programu, który będzie wyznaczał wszystkie liczby pierwsze w
zadanym przedziale. Program będzie korzystał z algorytmu zwanego sitem
Eratostenesa. Algorytm ten polega na tym, że tworzymy zbiór wszystkich liczb
naturalnych z danego przedziału większych lub równych dwa. Następnie
wybieramy ze zbioru najmniejszą liczbę, czyli dwa i usuwamy wszystkie jej
wielokrotności. Wybrana liczba jest liczbą pierwszą. Po usunięciu ze zbioru
wszystkich wielokrotności liczby dwa, wybieramy kolejną najmniejszą liczbę.
Będzie to kolejna liczba pierwsza. Usuwamy jej wszystkie wielokrotności i
znowu wybieramy najmniejszą liczbą ze zbioru i usuwamy jej wielokrotności.
Czynności wybierania i usuwania powtarzamy, dopóki nie opróżnimy zbioru.
Wybrane liczby będą szukanymi liczbami pierwszymi.
Implementacja tego algorytmu polega na utworzeniu tablicy logicznej o liczbie
elementów równej ilości liczb naturalnych większych lub równych dwa w
danym przedziale. Pierwszy element tablicy odpowiada liczbie dwa, drugi
liczbie trzy itd. Zakładamy, że wszystkie liczby są liczbami pierwszymi, co
realizujemy przez ustalenie jednakowej wartości dla wszystkich elementów
tablicy - np. false gdyż tak domyślnie są inicjalizowane elementy tablic
logicznych. Wybieramy pierwszy element tablicy, który ma wartość false.
Jest to oczywiście pierwszy element tablicy, który reprezentuje liczbę dwa.
Usunięcie wielokrotności liczby dwa, będzie polegało na nadaniu elementom
tablicy reprezentującym te wielokrotności wartości true, bez zmieniania
wartości wybranego elementu. Po nadaniu wszystkim elementom tablicy
reprezentującym wielokrotność liczby dwa wartości true, wybieramy kolejny
element tablicy o wartości false. Wartość elementów tablicy
reprezentujących wielokrotności wybranego elementu ustawiamy na true.
Czynności wyboru elementu i ustawienia wartości elementów reprezentujących
jego wielokrotności na true, powtarzamy aż do momentu, gdy nie mamy do
wyboru następnego elementu tablicy, którego wartość jest równa false.
Elementy tablicy, które mają wartość false, reprezentują liczby pierwsze w
danym przedziale.
Do algorytmu powyższego warto dodać pewne usprawnienia. Niektóre liczby
są wielokrotnościami kilku liczb i nadawanie elementom je reprezentującym
wartości true (usuwanie) wykonywane jest wiele razy. Zupełnie nie uda nam
się tego zlikwidować, ale można to zoptymalizować.
Pierwszą wielokrotnością, którą będziemy "usuwać", będzie wartość równa
kwadratowi wybranej liczby pierwszej, ponieważ mniejsze wielokrotności
musiały być równe iloczynowi wybranej liczby pierwszej i liczby od niej
mniejszej, więc musiały juz być "usunięte" wcześniej.
Wybieranie liczb pierwszych należy zakończyć po osiągnięciu pierwiastka
kwadratowego końca przedziału. Wybór większej liczby nie powoduje już
"usunięcia" więcej wielokrotności - patrz pierwsza optymalizacja.
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: LiczbyPierwsze.
2. Uczyń nowo utworzony projekt projektem startowym
a. Zaznacz projekt LiczbyPierwsze 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: LiczbyPierwsze.
v. nazwa rozwiązania: Lab6
3. Wewnątrz metody Main napisz następujący kod:
a. Pobierz od użytkownika górną granicę przedziału, z którego chce
wypisać wszystkie liczby pierwsze.
ulong n;
Console.WriteLine("Podaj górną granicę
¬ przedziału, z którego chcesz wypisać
¬ wszystkie liczby pierwsze.");
Console.Write("Liczba nie może być większa od
¬{0}: ", ulong.MaxValue);
n = Convert.ToUInt64(Console.ReadLine());
b. Zadeklaruj tablicę logiczną o n-1 elementach.
bool[] liczby = new bool[n-1];
W wyniku powyższej deklaracji, każdy element tablicy ma nadaną
domyślnie wartość false. Tablica o rozmiarze n-1, bo nie bierzemy
pod uwagę liczby jeden.
c. Dla wszystkich liczb całkowitych od liczby dwa do liczby równej
pierwiastkowi kwadratowemu z wartości końca przedziału, wykonuj co
następuje:
i. Sprawdź czy wartość elementu reprezentującą wybraną liczbę jest
równa false.
ii. Jeżeli wartość jest równa false, ustaw wartości elementów tablicy
reprezentujących wielokrotności wybranej liczby na wartość
false. Rozpocznij od liczby równej kwadratowi wybranej liczby.
iii. Następnie przejdź do następnej liczby.
ulong m = (uint)Math.Sqrt(n);
ulong index;
for (ulong i = 2; i <= m; i++)
{
if (!liczby[i - 2])
{
index = i * i - 2;
while (index < n - 1)
{
liczby[index] = true;
index += i;
}
}
}
d.
Wypisz liczby pierwsze z zadanego przedziału:
Console.WriteLine("Liczby pierwsze z podanego
¬ przedziału to:");
int j=0;
for(ulong i=0;i<n-1;i++)
{
if(!liczby[i])
{
Console.Write("{0,22}, ", i + 2);
j++;
if (j % 2 == 0)
Console.WriteLine();
if (j % (2*Console.WindowHeight) == 0)
Console.ReadKey();
}
}
Console.Write("\nLiczb pierwszych w podanym
¬zakresie jest {0}", j);
Console.ReadKey();
4. Skompiluj i uruchom program.