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:
Tablica sześciu liczb rzeczywistych:
double [] liczby = new double[6];
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
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.
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ł"};
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.
Utwórz pięcioelementową tablicę liczb całkowity i zainicjalizuj ją kolejnymi liczbami naturalnymi nieparzystymi.
Odp.
byte [] liczby = {1,3,5,7,9};
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>
Uruchom Visual Studio
Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005.
Utwórz nowy projekt
Z menu File wybierz New/Project...
W oknie dialogowym New Project określ następujące właściwości:
typu projektu: Visual C#/Windows
szablon: Console Application
lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\
nazwa projektu: MaxMin.
nazwa rozwiązania: Lab6
Wewnątrz metody Main napisz następujący kod:
Utwórz obiekt tablicy piętnastoelementowej liczb całkowitych.
int [] tablica = new int[15];
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);
}
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);
}
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;
}
}
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;
}
}
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;
}
}
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();
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
Dodaj do bieżącego rozwiązania nowy projekt
Z menu File wybierz Add/New Project...
W oknie dialogowym Add New Project określ następujące właściwości:
typu projektu: Visual C#/Windows
szablon: Console Application
nazwa projektu: MnozenieMacierzy.
Uczyń nowo utworzony projekt projektem startowym
Zaznacz projekt MnozenieMacierzy w okienku Solution Explorer i z menu kontekstowego wybierz Set as StartUp Project.
albo, gdy rozpoczynasz laboratorium od tego ćwiczenia
Uruchom Visual Studio
Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005.
Utwórz nowy projekt
Z menu File wybierz New/Project...
W oknie dialogowym New Project określ następujące właściwości:
typu projektu: Visual C#/Windows
szablon: Console Application
lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\
nazwa projektu: MnozenieMacierzy.
nazwa rozwiązania: Lab6
Wewnątrz metody Main napisz następujący kod:
Zadeklaruj trzy stałe całkowite reprezentujące odpowiednio
N - liczba wierszy macierzy A i C.
M - liczba kolumn macierzy B i C
K - liczba kolumn macierzy A i liczba wierszy macierzy B
const int N = 3;
const int M = 3;
const int K = 2;
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];
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() );
}
}
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.
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();
Skompiluj i uruchom program.
Ćwiczenie 3
Napisz program, które losuje sześć różnych liczb całkowitych z przedziału <1;49>.
Dodaj do bieżącego rozwiązania nowy projekt
Z menu File wybierz Add/New Project...
W oknie dialogowym Add New Project określ następujące właściwości:
typu projektu: Visual C#/Windows
szablon: Console Application
nazwa projektu: TotoLotek.
Uczyń nowo utworzony projekt projektem startowym
Zaznacz projekt TotoLotek w okienku Solution Explorer i z menu kontekstowego wybierz Set as StartUp Project.
albo, gdy rozpoczynasz laboratorium od tego ćwiczenia
Uruchom Visual Studio
Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005.
Utwórz nowy projekt
Z menu File wybierz New/Project...
W oknie dialogowym New Project określ następujące właściwości:
typu projektu: Visual C#/Windows
szablon: Console Application
lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\
nazwa projektu: TotoLotek.
nazwa rozwiązania: Lab6
Wewnątrz metody Main napisz następujący kod:
Zdefiniuj tablicę jednowymiarową, która będzie zawierać sześć wylosowanych liczb:
byte [] numery = new byte[6];
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);
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();
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.
Dodaj do bieżącego rozwiązania nowy projekt
Z menu File wybierz Add/New Project...
W oknie dialogowym Add New Project określ następujące właściwości:
typu projektu: Visual C#/Windows
szablon: Console Application
nazwa projektu: LiczbyPierwsze.
Uczyń nowo utworzony projekt projektem startowym
Zaznacz projekt LiczbyPierwsze w okienku Solution Explorer i z menu kontekstowego wybierz Set as StartUp Project.
albo, gdy rozpoczynasz laboratorium od tego ćwiczenia
Uruchom Visual Studio
Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005.
Utwórz nowy projekt
Z menu File wybierz New/Project...
W oknie dialogowym New Project określ następujące właściwości:
typu projektu: Visual C#/Windows
szablon: Console Application
lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\
nazwa projektu: LiczbyPierwsze.
nazwa rozwiązania: Lab6
Wewnątrz metody Main napisz następujący kod:
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());
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.
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:
Sprawdź czy wartość elementu reprezentującą wybraną liczbę jest równa false.
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.
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;
}
}
}
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();
Skompiluj i uruchom program.
L
L