Temat:
Struktury
Charakterystyczną cechą rozpatrywanych dotychczas złożonych typów danych (np. tablic) była ich jednorodność. Oznacza to, że niezależnie od rozmiaru tablicy wszystkie jej elementy muszą być tego samego typu.
W praktyce często mamy do czynienia z obiektami, które nie dają się opisać za pomocą danych tego samego typu. Przykładem takiego obiektu może być dowód osobisty.
Do opisu podobnych obiektów w języku C++ używany jest typ strukturalny. Struktura jest jednostką syntaktyczną grupującą składowe różnych typów, zarówno podstawowych, jak i pochodnych. Definicja typu strukturalnego ma następującą postać:
struct nazwa
{
// lista składników
};
Dostęp do składowych struktury uzyskuje się za pomocą nazwy zmiennej strukturalnej, operatora kropki (.) i nazwy składnika:
Nazwa_Zmniennej_Strukturalnej . Nazwa_Składnika
Przykład 1 (plik PROG64.CPP):
#include <iostream.h>
#include <conio.h>
struct Osoba
{
char *Nazwisko;
char *Imie;
int Wiek;
};
Osoba Student;
/*-----------------------------------------------------------------------------*/
void main ( )
{
clrscr();
// Wartość zmiennej strukturalnej wyznaczamy poprzez
// nadanie wartości poszczególnym jej składnikom.
// Można to zrobić za pomocą instrukcji przypisania:
Student.Nazwisko = "Kowalski";
Student.Imie = "Jan";
Student.Wiek = 20;
cout << "Nazwisko: " << Student.Nazwisko << endl;
cout << "Imię: " << Student.Imie << endl;
cout << "Wiek: " << Student.Wiek << endl;
// Można nadać wartości poszczególnym składnikom zmiennej
// strukturalnej poprzez wczytanie z klawiatury:
cout << "\nNazwisko: ";
cin.width(30);
cin >> Student.Nazwisko;
cin.width(20);
cout << "Imię: ";
cin >> Student.Imie;
cout << "Wiek: ";
cin >> Student.Wiek;
cout << Student.Nazwisko << ″ ″ << Student.Imie
<< ″\ t″ << Student.Wiek;
while (! kbhit( ))
{ };
}
Przykład 2 (plik PROG65.CPP):
#include <iostream.h>
#include <conio.h>
#include <dos.h>
struct Data // definicja typu strukturalnego Data
{
int Dzien, Miesiac, Rok;
};
struct Osoba // definicja typu strukturalnego Osoba
{
char Nazwisko[30];
char Imie[20];
Data Data_Ur;
};
Osoba Pracownik;
Osoba Dane[3];
/*-------------------- koniec definicji i deklaracji ------------------------*/void main( )
{
clrscr();
cout << "Wprowadzam dane do zmiennej strukturalnej Pracownik:\ n";
cout << "\ nNazwisko: ";
cin.width(sizeof(Pracownik.Nazwisko);
cin >> Pracownik.Nazwisko;
cout << "Imię: ";
cin.width(sizeof(Pracownik.Imie));
cin >> Pracownik.Imie;
cout << "Data urodzenia: " << " \ n\ tDzien: ";
cin >> Pracownik.Data_Ur.Dzien;
cout << "\ tMiesiąc: ";
cin >> Pracownik.Data_Ur.Miesiac;
cout << "\t Rok: ";
cin >> Pracownik.Data_Ur.Rok;
delay(3000);
clrscr();
cout << "Teraz wprowadzam dane do tablicy Dane składającej się\n"
<< "z dwóch elementów typu strukturalnego:\n";
int i;
for (i=0; i < 2; i++)
{
cout << "\ nNazwisko: ";
cin.width(sizeof(Dane[i]. Nazwisko));
cin >> Dane[i].Nazwisko;
cout << "Imię: ";
cin.width(sizeof(Dane[i]. Imie));
cin >> Dane[i].Imie;
cout << "Data urodzenia: " << " \ n\ tDzien: ";
cin << Dane[i].Data_Ur.Dzien;
cout << "\ tMiesiąc: ";
cin >> Dane[i].Data_Ur.Miesiac;
cout << "\ tRok: ";
cin >> Dane[i].Data_Ur.Rok;
}
while (! kbhit())
{ };
}
Jeśli do obiektu strukturalnego odwołujemy się za pomocą wskaźnika, to dostęp do poszczególnych pól uzyskujemy za pomocą operatora -> ( znak ′-′ oraz znak ′>′ ):
Wskaźnik -> Nazwa_Składnika
Przykład 3 ( plik PROG66.CPP):
#include <iostream.h>
#include <conio.h>
#include <dos.h>
struct Data
{
int Dzien, Miesiac, Rok;
};
struct Osoba
{
char Nazwisko[30];
char Imie[20];
Data Data_Ur;
};
Osoba Pracownik;
Osoba Dane[3];
Osoba *Wsk;
/*-------------------- koniec definicji i deklaracji -----------------------------*/
void main()
{
clrscr();
cout << "Wprowadzam dane do zmiennej strukturalnej Pracownik:\ n";
Wsk = &Pracownik; // ustawiam wskaźnik na zmiennej Pracownik
cout << "\ nNazwisko: ";
cin.width(sizeof(Wsk->Nazwisko));
cin >> Wsk->Nazwisko;
cout << "Imię: ";
cin.width(sizeof(Wsk->Imie));
cin >> Wsk->Imie;
cout << "Data urodzenia: " << "\ n\ tDzien: ";
cin >> Wsk->Data_Ur. Dzien;
cout << "\ t Miesiąc: ";
cin >> Wsk->Data_Ur. Miesiac;
cout << "\ tRok: ";
cin >> Wsk->Data_Ur. Rok;
delay(3000);
clrscr();
cout << "Teraz wprowadzam dane do tablicy Dane składającej się\ n"
<< "z dwóch elementów typu strukturalnego:\ n";
int i;
Wsk = Dane; // ustawiam wskaźnik na początku tablicy Dane
for (i=0; i < 2; i++, Wsk++)
{
cout << "\ nNazwisko: ";
cin.width(sizeof(Wsk->Nazwisko));
cin >> Wsk->Nazwisko;
cout << "Imię: ";
cin.width(sizeof(Wsk->Imie));
cin >> Wsk->Imie;
cout << "Data urodzenia: " << "\ n\ tDzien: ";
cin >> Wsk->Data_Ur.Dzien;
cout << "\ t Miesiąc: ";
cin >> Wsk->Data_Ur.Miesiac;
cout << "\ t Rok: ";
cin >> Wsk->Data_Ur.Rok;
}
delay(3000);
clrscr( );
cout << "Teraz wyświetlam zawartość zmiennej Pracownik:\ n";
Wsk = &Pracownik;
cout << Wsk->Imie << " " << Wsk->Nazwisko << ", ur. "
<< Wsk->Data_Ur.Dzien << "." << Wsk->Data_Ur.Miesiac
<< "." << Wsk->Data_Ur.Rok << endl;
cout << "\ nTeraz wyświetlam zawartość tablicy Dane:\n";
Wsk = Dane;
for (i=0; i < 2; i++,Wsk++)
{
cout << Wsk->Imie << " " << Wsk->Nazwisko << ", ur. "
<< Wsk->Data_Ur.Dzien << "." << Wsk->Data_Ur.Miesiac
<< "." << Wsk->Data_Ur.Rok << endl;
}
while (!kbhit())
{ };
}
Każda definicja struktury wprowadza nowy, unikatowy typ, np.:
struct S1 { int i; };
struct S2 { int j; };
Typy S1 i S2 są różnymi typami, zatem w deklaracjach
S1 x, y;
S2 z;
zmienne x oraz y są tego samego typu S1, natomiast x oraz z są różnych typów. Wobec tego przypisania:
x = y;
y = x;
są poprawne, podczas gdy:
x = z;
z = y;
są błędne. Dopuszczalne są natomiast przypisania składowych o tych samych typach, np.:
x.i = z.j;
Poniżej przytoczono program ilustrujący zastosowanie struktur (plik OCENA3.CPP):
/*************************************************************************************/
/* Program umożliwia wystawienie oceny na podstawie liczby */
/* uzyskanych punktów według następującego kryterium: */
/* 0 - 49 pkt. 2 */
/* 50 - 59 pkt. 3 */
/* 60 - 69 pkt. 3+ */
/* 70 - 79 pkt. 4 */
/* 80 - 89 pkt. 4+ */
/* 90 - 100 pkt. 5 */
/* UWAGA: nazwiska i punkty są przechowywane w tablicy struktur */
/**************************************************************************************/
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
#include <ctype.h>
#include <fstream.h>
const int Max_Punkt = 100,
Min_Punkt = 0,
n = 20;
char Napis [ ] = { "Ile osób oceniasz?: " };
enum Stopnie {ndst, dst, dst_plus, db, db_plus, bdb};
struct Osoba
{ char Nazwisko[30];
int Punkty;
};
Osoba Dane[n];
int Ile_Osob;
void Pisz_Naglowek (char Napis1[ ], char Napis2[ ], char Napis3[ ]);
int Czyt_Int (char Napisy[ ],int Ogr_d, int Ogr_g);
void Wprowadz_Jedna_Osobe(char Nazwisko[ ], int &Lp, int Ogr_d, int Ogr_g);
void Wprowadz_Wszystkie_Dane(Osoba Dane[ ],
int Ile_Osob, int Ogr_d, int Ogr_g);
Stopnie Wystaw_Ocene (int Lp );
void Wyswietl_Ocene ( Stopnie Ocena);
void Wyswietl_Wszystkie_Oceny(Osoba Dane[ ], int Ile_Osob);
/*----------------------------------------------------------------*/
void main () // program główny
{
clrscr ();
Ile_Osob = Czyt_Int (Napis, 1,n);
Pisz_Naglowek ("Nazwisko", "Liczba punktów", "");
Wprowadz_Wszystkie_Dane (Dane, Ile_Osob, Min_Punkt, Max_Punkt);
Pisz_Naglowek ("Nazwisko", "Liczba punktów", "Ocena");
Wyswietl_Wszystkie_Oceny (Dane, Ile_Osob);
while (! kbhit( ))
{ } ;
} // koniec programu głównego
/*----------------------------------------------------------------*/
void Pisz_Naglowek (char Napis1[ ], char Napis2[ ], char Napis3[ ])
/* Procedura umożliwia napisanie nagłówka składającego się */
/* z max trzech wyrazów */
{
clrscr();
cout << Napis1;
gotoxy (32, wherey());
cout << Napis2;
gotoxy (55, wherey());
cout << Napis3 << endl;
cout << endl;
}
int Czyt_Int ( char Napisy[], int Ogr_d, int Ogr_g)
/* Funkcja umożliwia wczytanie liczby całkowitej oraz */
/* kontrolowanie formalnej i logicznej poprawności liczby */
{
int x, y, Liczba, r;
enum Boolean {false, true} Poza_Zakresem, Powtorz;
cout << Napisy;
x = wherex();
y = wherey();
while (1)
{
cin >> Liczba;
Powtorz = (Liczba < Ogr_d) || (Liczba > Ogr_g) || (cin.fail());
if (cin.fail( ))
{
cin.clear(cin.rdstate() & ~ios::failbit);
char L[80];
cin >> L;
}
if (Powtorz)
{
gotoxy (x, y);
clreol ();
}
else break;
}
return Liczba;
}
/*----------------------------------------------------------------*/
void Wprowadz_Jedna_Osobe(char Nazwisko[ ], int &Lp, int Ogr_d, int Ogr_g)
/* Procedura umożliwia wprowadzenie nazwiska i liczby punktów */
/* dla jednej osoby. */
/* UWAGA: po wprowadzeniu nazwiska nacisnąć <Enter>, */
/* wprowadzić liczbę punktów i nacisnąć <Enter>. */
{
cin >> Nazwisko;
gotoxy(32, wherey()-1);
Lp = Czyt_Int("", Ogr_d, Ogr_g);
}
void Wprowadz_Wszystkie_Dane(Osoba Dane[ ],
int Ile_Osob, int Ogr_d, int Ogr_g)
/* Procedura umożliwia wprowadzenie nazwisk i punktów */
/* dla całej grupy */
{
int i;
for (i=0; i < Ile_Osob; i++)
Wprowadz_Jedna_Osobe(Dane[i].Nazwisko, Dane[i].Punkty, Ogr_d, Ogr_g);
}
//----------------------------------------------------------------------------------
Stopnie Wystaw_Ocene ( int Lp )
/* Funkcja umożliwia wystawienie oceny na podstawie */
/* liczby uzyskanych punktów. */
{
Stopnie Wynik;
Lp = Lp/10;
switch (Lp)
{
default : { Wynik = ndst; break; }
case 5 : { Wynik = dst; break; }
case 6 : { Wynik = dst_plus; break; }
case 7 : { Wynik = db; break; }
case 8 : { Wynik = db_plus; break; }
case 9 : { Wynik = bdb; break; }
case 10 : { Wynik = bdb; break; }
}
return Wynik;
}
/*----------------------------------------------------------------*/
void Wyswietl_Ocene ( Stopnie Ocena)
/* Funkcja umożliwia wyświetlenie oceny w postaci słownej */
{
switch (Ocena)
{
case ndst : { cout << "niedostateczna\n"; break; }
case dst : { cout << "dostateczna\n"; break; }
case dst_plus : { cout << "dość dobra\n"; break; }
case db : { cout << "dobra\n"; break; }
case db_plus : { cout << "ponad dobra\n"; break; }
case bdb : { cout << "bardzo dobra\n"; break; }
}
}
void Wyswietl_Wszystkie_Oceny(Osoba Dane[ ], int Ile_Osob)
/* Procedura umożliwia wyświetlenie oceny w postaci słownej */
/* dla wszystkich osób. */
{
int i;
Stopnie Ocena;
for (i=0; i < Ile_Osob; i++)
{
Ocena = Wystaw_Ocene(Dane[i].Punkty);
cout << Dane[i].Nazwisko;
gotoxy (32, wherey ());
cout << Dane[i].Punkty;
gotoxy (55, wherey ());
Wyswietl_Ocene(Ocena);
}
}
Temat:
Grafika
Język C++ umożliwia graficzną prezentację danych za pomocą standardowych funkcji graficznych znajdujących się w pliku graphics.h. Funkcje te (jest ich ponad 80) pozwalają m.in. rysować na ekranie pracującym w trybie graficznym krzywe różnych kształtów i kolorów, wypełniać kontury określonym kolorem i deseniem, wyświetlać na ekranie napisy (poziomo i pionowo) w różnych krojach pisma, z możliwością skalowania kroju oraz justowania napisu.
Mikrokomputery klasy IBM PC mogą być wyposażone w różne karty graficzne, np. EGA, VGA, SVGA, VESA, obsługujące ekrany monitorów o różnej rozdzielczości. Rozdzielczość ekranu, czyli liczba wyświetlanych w poziomie i pionie punktów, jest ściśle związana z procedurami i funkcjami graficznymi. W celu uniezależnienia systemu C++ od kart graficznych komputerów, przewidziano dla najczęściej stosowanych kart sterowniki, tj. programy obsługujące związek funkcji graficznych z tymi kartami. Sterowniki są plikami z rozszerzeniem .BGI. Oprócz sterowników, programy graficzne korzystające z innych niż standardowy krojów pisma powinny mieć dostęp do plików zawierających definicje tych krojów. Są to pliki z rozszerzeniem .CHR.
Wykorzystanie funkcji graficznych z pliku graphics.h wymaga jego deklaracji w dyrektywie #include. Ponadto, przed wywołaniem pierwszej funkcji graficznej, tryb graficzny powinien być zainicjalizowany przez wywołanie funkcji detectgraph i initgraph. Na zakończenie wykonywania operacji graficznych należy zamknąć tryb graficzny za pomocą funkcji closegraph, która powoduje usunięcie z pamięci sterownika graficznego i powrót do trybu tekstowego.
Podczas pracy w trybie graficznym istnieje także możliwość przełączania trybu graficznego na tekstowy i odwrotnie (funkcje restorecrtmode i setgraphmode).
Ekran w trybie graficznym posiada inny układ współrzędnych niż w trybie tekstowym. Każdy punkt tego ekranu ma swoje współrzędne, przy czym punkt znajdujący się w lewym górnym narożniku ma współrzędne (0, 0), a punkt w dolnym prawym narożniku ma współrzędne zależne od karty graficznej , które mogą być określone za pomocą funkcji standardowych getmaxx i getmaxy. Przykładowo, dla karty graficznej VGA współrzędne ekranu graficznego ilustruje poniższy rysunek:
Karty graficzne, w zależności od trybu pracy, mogą mieć od jednej do kilku stron graficznych. Zwiększenie stron graficznych odbywa się kosztem pogorszenia rozdzielczości karty. Poniżej podano parametry graficzne karty VGA dla różnych trybów:
VGALO - 640×200 pkt., 16 kolorów, 4 strony graficzne;
VGAMed - 640×350 pkt., 16 kolorów, 2 strony graficzne;
VGAHI - 640×480 pkt., 16 kolorów, 1 strona graficzna.
Większa liczba stron graficznych może być wykorzystana do tworzenia animacji za pomocą manipulowania stronami aktywnymi i widocznymi.
Kursor w trybie graficznym, w odróżnieniu od trybu tekstowego, jest niewidoczny, ale w każdej chwili można określić jego współrzędne za pomocą funkcji getx i gety.
1. Predefiniowane stałe graficzne
Stałe są wykorzystywane przez standardowe funkcji z pliku graphics.h. Służą one do definiowania sterowników kart graficznych i trybów ekranu, oznaczania kolorów i wzorów wypełnień, określenia rodzaju i grubości linii, oznaczania krojów pisma, kierunku wyprowadzania napisów i sposobu ich justowania itd. Poniżej przytoczono najczęściej używane w programach stałe predefiniowane i ich wartości domyślne (kody).
Stałe oznaczania kolorów
nazwa kod
BLACK = 0; { czarny }
BLUE = 1; { niebieski }
GREEN = 2; { zielony }
CYAN = 3; { turkusowy }
RED = 4; { czerwony }
MAGENTA = 5; { karmazynowy }
BROWN = 6; { brązowy }
LIGHTGRAY = 7; { jasnoszary }
DARKGRAY = 8; {ciemnoszary }
LIGHTBLUE = 9; { jasnoniebieski }
LIGHTGREEN= 10; { jasnozielony }
LIGHTCYAN = 11; { jasnoturkusowy }
LIGHTRED = 12; { jasnoczerwony }
LIGHTMAGENTA = 13; { jasnokarmazynowy }
YELLOW = 14; { żółty }
WHITE = 15; { biały }
Stałe te mogą być wykorzystane np. w procedurach ustalających kolor pierwszoplanowy i kolor tła:
setcolor(YELLOW); (* kolor pierwszoplanowy - żółty *)
setbkcolor(BLUE); (* kolor tła - niebieski *)
Stałe określania rodzaju i grubości linii
Stałe predefiniowane należące do tej grupy służą do oznaczania rodzajów linii oraz ich grubości. Są one wykorzystywane w procedurze setlinestyle określającej sposób rysowania linii, a ich definicja jest następująca:
nazwa kod
SOLID_LINE = 0; (* linia ciągła *)
DOTTED_LINE = 1; (* linia kropkowana *)
CENTER_LINE = 2; (* linia symetrii *)
DASHED_LINE = 3; (* linia przerywana *)
USERBIT_LINE = 4; (* linia definiowana przez programistę *)
NORM_WIDTH = 1; (* linia o normalnej grubości
(pojedyncza) *)
THICK_WIDTH = 3; (* linia pogrubiona (potrójna grubość) *)
Stała USERBIT_LINE oznacza rodzaj linii definiowanej przez programistę za pomocą procedury setlinestyle.
Stałe wzorów wypełniających kontury
Stałe te służą do określania sposobu wypełniania konturów. Są one wykorzystywane w procedurze setfillstyle, a ich definicja jest następująca:
nazwa kod
EMPTY_FILL = 0; (* wypełnianie w kolorze tła *)
SOLID_FILL = 1; (* wypełnianie w kolorze pierwszoplanowym *)
LINE_FILL = 2; (* wzór - linie poziome *)
LTSLASH_FILL= 3; (* wzór - linie ukośne cienkie *)
SLASH_FILL = 4; (* wzór - linie ukośne pogrubione *)
BKSLASH_FILL= 5; (* wzór - linie ukośne prawostronne pogrub. *)
LTBKSLASH_FILL= 6; (* wzór - linie ukośne prawe; ciemne tło *)
HATCH_FILL = 7; (* wzór - siatka prostokątna *)
XHATCH_FILL = 8; (* wzór - siatka ukośna *);
INTERLEAVE_FILL = 9; (* wzór - linie pionowe; ciemne tło *)
WIDE_DOT_FILL = 10; (* wzór - kropki rzadkie *)
CLOSE_DOT_FILL = 11; (* wzór - kropki gęste *)
USER_FILL = 12; (* wzór definiowany przez programistę *)
Stała USER_FILL oznacza wypełnienie konturów wzorem definiowanym przez programistę za pomocą procedury setfillpattern.
Stałe krojów pisma, kierunku wyprowadzania tekstów i rozmiaru liter
W trybie graficznym dostępnych jest 11 różnych krojów pisma: standardowe, „triplex”, małe, bezszeryfowe, gotyckie i sześć innych krojów ponumerowanych od 5 do 10 o rozmiarach od 1 do 10, przy czym poza pierwszym krojem, którego matryca wynosi 8×8 bitów (pikseli), wszystkie pozostałe są krojami wektorowymi. Do określania krojów pisma służą następujące stałe predefiniowane:
nazwa kod
DEFAULF_FONT = 0;
TRIPLEX_FONT = 1;
SMALL_FONT = 2;
SANSSERIF_FONT = 3;
GOTHIC_FONT = 4;
SCRIPT_FONT = 5;
SIMPLEX_FONT = 6;
TRIPLEX_SCR_FONT = 7;
COMPLEX_FONT = 8;
EUROPEAN_FONT = 9;
BOLD_FONT = 10;
Podane stałe są wykorzystywane w procedurze settextstyle.
Z pismem wyprowadzanym na ekran związane są także stałe określające kierunek wyprowadzania tekstu:
nazwa kod
HORIZ_DIR = 0; (* wyprow. poziome od strony lewej do prawej *)
VERT_DIR = 1; (* wyprow. pionowe z góry na dół *)
Stałe justowania tekstu w poziomie i pionie
Do określenia sposobu justowania tekstu w poziomie i pionie służą stałe zdefiniowane następująco:
nazwa kod
CENTER_TEXT = 1; (* centrowanie tekstu *)
LEFT_TEXT = 0; (* wyrównanie w poziomie do lewej *)
RIGTH_TEXT = 2; (* wyrównanie w poziomie do prawej *)
BOTTOM_TEXT = 0; (* wyrównanie w pionie do dołu *)
TOP_TEXT = 2; (* wyrównanie w pionie do góry *)
Stałe te są wykorzystywane w procedurze settextstyle. Domyślnie wyprowadzany tekst jest wyrównywany w poziomie do lewej i w pionie do dołu.
2. Wybrane funkcje pliku graphics.h.
2.1. Rozdzielczość karty graficznej
getmaxx - funkcja zwraca rozdzielczość karty graficznej względem osi X;
getmaxy - funkcja zwraca rozdzielczość karty graficznej względem osi Y.
Przykładowo, dla karty graficznej VGA funkcja getmaxx zwraca wartość 640.
2.2. Kursor graficzny
getx - funkcja zwraca aktualną współrzędną X kursora;
gety - funkcja zwraca aktualną współrzędną Y kursora;
moveto(X,Y) - procedura przesuwa kursor do punktu ekranu o współrzędnych (X,Y);
moverel(dX, dY) - procedura przesuwa kursor graficzny do punktu ekranu
o współrzędnych zmienionych w stosunku do aktualnych
odpowiednio o dX i dY.
Przykład:
moveto(50, 130); (* ustawienie kursora graficznego w punkcie *)
(* o współrzędnych (50, 130) *)
moverel(60, 25); (* przesunięcie kursora graficznego z punktu *)
(* o współrzędnych (50, 130) do punktu *)
(* o współrzędnych (110, 155) *)
2.3. Teksty w trybie graficznym.
settextstyle(czcionka, kierunek_wyprowadzania, rozmiar_czcionki)
Procedura określa styl wyprowadzanego tekstu. Przykładowo:
settextstyle(SANS_SERIF_FONT, HORIZ_DIR, 5) - procedura ustala, że wyprowadzany na ekran monitora tekst będzie pisany czcionką SANS_SERIF_FONT, poziomo i będzie miał rozmiar 5.
Jeżeli nie określimy stylu za pomocą procedury settextstyle, to tekst będzie pisany czcionką domyślną, poziomo.
Sposób justowania tekstu względem aktualnej pozycji kursora określamy za pomocą procedury:
settextjustify (poziom, pion )
Przykładowo, procedura settextjustify (CENTER_TEXT, TOP_TEXT) spowoduje wyśrodkowanie tekstu w poziomie i wyrównanie do góry w pionie. Domyślny sposób justowania - wyrównanie do lewej w poziomie i do dołu w pionie.
Do wyprowadzania tekstów służą dwie procedury:
outtext(łańcuch_znaków) - wyprowadzenie podanego
łańcucha znaków poczynając
od aktualnej pozycji kursora;
outtextxy(X, Y, łańcuchz_znaków) - wyprowadzenie podanego
łańcucha znaków poczynając
od punktu (X, Y).
Przykłady:
outtextxy(320, 160, ″Ala ma kota″);
settextjustify (RIGHT_TEXT, TOP_TEXT);
outtextxy (320, 160, ″Ala ma kota″);
settextjustify(CENTER_TEXT, CENTER_TEXT);
outtextxy(320, 160, ″Ala ma kota″);
2.4. Struktura linii
setlinestyle(rodzaj_linii, wzór, grubość)
Procedura określa rodzaj linii i jej grubość. Wszystkie parametry muszą być typu całkowitego. Parametr wzór jest istotny tylko w przypadku, gdy rozdaj linii jest określony przez stałą USERBIT_LINE. W przeciwnym przypadku może przyjmować dowolną wartość typu całkowitego. Jeżeli linia jest definiowana przez programistę (parametr wzór jest równy stałej USERBIT_LINE), to na ekranie będą wyświetlone tylko te punkty linii, które odpowiadają bitom o wartości 1.
2.5. Kreślenie figur
a). Linia prosta
line(x1, y1, x2, y2) (* kreślenie linii prostej łączącej punkty *)
(* o współrzędnych (x1, y1) i (x2, y2) *)
lineto(x, y); (* kreślenie linii prostej łączącej punkt o aktualnych *)
(* współrzędnych z punktem (x, y) *)
linerel(dX, dY); (* kreślenie linii prostej łączącej punkt o aktualnych *)
(* współrzędnych z punktem , którego współrzędne *)
(* różnią się od aktualnych o dX i dY *)
b). Prostokąt
rectangle(x1, y1, x2, y2); (* (x1, y1) - współrzędne lewego górnego *)
(* narożnika prostokąta, natomiast (x2, y2) *)
(* są to współrzędne prawego dolnego *)
(* narożnika prostokąta *)
c). Wielobok
drawpoly(liczba_punktów, współrzędne_punktów);
(* liczba punktów musi być o 1 większa *)
(* od liczby wierzchołków wieloboku *)
Współrzędne punktów muszą być sekwencją par liczb całkowitych odpowiadających współrzędnym x oraz y kolejnych wierzchołków wieloboku.
d). Okrąg
circle(x, y, r); (* rysowanie okręgu o promieniu r, którego *)
(* środek znajduje się w punkcie (x,y) *)
e). Łuk okręgu
arc (x, y, α, β, r); (* rysowanie łuku okręgu o promieniu r, którego *)
(* środek znajduje się w punkcie (x, y); *)
(* α - kąt początkowy łuku; *)
(* β - kąt końcowy łuku. *)
f). Wypełnianie konturów zamkniętych
setfillstyle(wzór, kolor) (* określenie wzoru wypełniającego kontur *)
(* kolor - jest kolorem konturu *)
C++ oferuje 12 wzorów standardowych (patrz stałe wypełnień) oraz wzór programisty USER_FILL. Użycie wzoru USER_FILL wymaga zdefiniowania wzoru za pomocą procedury:
setfillpattern(wzór_definiowany, kolor_wzoru);
(* wzór definiowany jest wzorcem 8×8 piks. *)
Wyspecyfikowanym wzorem wypełnia się figury zamknięte:
bar(x1, y1, x2, y2) (* prostokąt wypełniony; *)
(* x1, y1 - współrzędne lewego górnego *)
(* narożnika; x2, y2 - współrzędne *)
(* prawego dolnego narożnika *)
bar3d(x1, y1, x2, y2, h, góra)
(* słupek trójwymiarowy; *)
(* x1, y1 - współrzędne lewego górnego *)
(* narożnika płaszczyzny czołowej słupka; *)
(* x2, y2 - współrzędne prawego dolnego *)
(* narożnika płaszczyzny czołowej słupka; *)
(* h - głębokość; góra - parametr typu *)
(* int; wartość niezerowa powoduje *)
(* zaznaczenie płaszczyzny górnej *)
fillpoly(liczba_pinktów, współrzędne_punktów)
(* wielobok wypełniony *)
pieslice(x, y, α, β, r) (* wypełniony wycinek kołowy *)
fillellipse(x, y, półośX, półośY) (* wypełniona elipsa ze środkiem *)
(* w punkcie x,y; *)
2.6. Okna w trybie graficznym
setviewport(x1, y1, x2, y2, obcięcie)
(* otwarcie okna graficznego; *)
(* x1, y1 - współrzędne lewego górnego *)
(* narożnika okna; x2, y2 - współrzędne *)
(* prawego dolnego narożnika okna; *)
(* obcięcie - parametr typu int - jeśli jest *)
(* niezerowe, to rysunek jest przycinany *)
(* do rozmiarów okna *)
clearviewport (* czyszczenie aktualnego okna graficznego *)
cleardevice (* czyszczenie urządzenia graficznego *)
2.7. Przełączanie stron graficznych
setactivepage(strona) (* uczynienie strony podanej jako parametr *)
(* stroną aktywną *)
setvisualpage(strona) (* uczynienie strony podanej jako parametr *)
(* stroną widoczną; *)
(* parametr strona jest typu int *)
2.8. Przełączanie trybów pracy monitora
restorecrtmode (* przełączenie się z trybu graficznego *)
(* na tryb tekstowy *)
setgraphmode(tryb) (* powrót do podanego trybu graficznego *)
2.9. Działania na obrazach
a). Określenie rozmiarów obrazu:
imagesize(x1, y1, x2, y2)
(* określenie rozmiarów obrazu *)
(* prostokątnego; x1,y1 - współrzędne *)
(* lewego górnego narożnika; *)
(* x2, y2 - współrzędne prawego dolnego *)
(* narożnika *)
b). Zapamiętanie obrazu:
getimage(x1, y1, x2, y2, *obraz)
(* x1, y1, x2, y2 - parametry muszą być *)
(* takie same jak w imagesize; *)
(* obraz - wskaźnik do obszaru pamięci, *)
(* w którym przechowywany jest obraz *)
c). Wywołanie obrazu na ekranie
putimage(x, y, obraz, operacja)
(* x, y - współrzędne lewego górnego *)
(* narożnika obrazu na ekranie; *) (* obraz - definicja obrazu; *)
(* operacja - działanie wykonywane na *)
(* odpowiadających sobie punktach *) (* ekranu oraz wyprowadzanego na ten *) (* ekran obrazu *)
Parametr operacja może przyjmować wartość jednej ze stałych:
nazwa kod
COPY_PUT (0)
XOR_PUT (1)
OR_PUT (2)
AND_PUT (3)
NOT_PUT (4)
2.10. Otwieranie i zamykanie trybu graficznego
detectgraph(sterownik, tryb)
(* określenie sterownika karty graficznej *) (* i trybu pracy tej karty; *)
(* sterownik i tryb - zmienne typu int *)
initgraph(sterownik, tryb, ścieżka)
(* zainicjowanie trybu graficznego; *)
(* ścieżka - jest łańcuchem znaków, , *)
(* który określa ścieżkę dostępu do *)
(* sterownika karty graficznej (plik typu *)
(* .BGI *)
closegraph (* zamknięcie trybu graficznego *)
Poniżej przedstawiono program (plik OCENA5.CPP) ilustrujący zastosowanie funkcji graficznych do prezentacji wyników obliczeń.
/*************************************************************************************/
/* Program umożliwia wystawienie oceny na podstawie liczby */
/* uzyskanych punktów według następującego kryterium: */
/* 0 - 49 pkt. 2 */
/* 50 - 59 pkt. 3 */
/* 60 - 69 pkt. 3+ */
/* 70 - 79 pkt. 4 */
/* 80 - 89 pkt. 4+ */
/* 90 - 100 pkt. 5 */
/* UWAGA: nazwiska i punkty są przechowywane w tablicy struktur. */
/* Program umożliwia prezentację wyników w postaci wykresu */
/* kołowego. */
/**************************************************************************************/
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
#include <ctype.h>
#include <fstream.h>
#include <math.h>
#include <dos.h>
#include <graphics.h>
const int Max_Punkt = 100,
Min_Punkt = 0,
n = 20;
char Napis [ ] = {"Ile osób oceniasz?: "};
enum Stopnie {ndst, dst, dst_plus, db, db_plus, bdb};
struct Osoba
{ char Nazwisko[30];
int Punkty;
};
Osoba Dane[n];
int Ocena_Ile[6];
int Ile_Osob, Sterownik, Tryb;
void Pisz_Naglowek (char Napis1[ ], char Napis2[ ], char Napis3[ ]);
int Czyt_Int ( char Napisy[ ], int Ogr_d, int Ogr_g);
void Wprowadz_Jedna_Osobe(char Nazwisko[ ],int &Lp, int Ogr_d, int Ogr_g);
void Wprowadz_Wszystkie_Dane(Osoba Dane[ ],
int Ile_Osob, int Ogr_d, int Ogr_g);
Stopnie Wystaw_Ocene ( int Lp );
void Wyswietl_Ocene ( Stopnie Ocena);
void Wyswietl_Wszystkie_Oceny(Osoba Dane[ ],int Ile_Osob);
void Inicjuj_Grafike(void);
void Statystyka_Ocen(Osoba Dane[ ], int Ile_Osob, int Ocena_Ile[ ]);
void Legenda(int Ocena_Ile[ ], int Ile_Osob);
void Wykres_Kolowy(int Ocena_Ile[], int Ile_Osob);
void Wykres(Osoba Dane[],int Ile_Osob);
/*------------------- koniec definicji i deklaracji ---------------------------------------------*/
void main () // program główny
{
clrscr ();
Ile_Osob = Czyt_Int(Napis, 1,n);
Pisz_Naglowek("Nazwisko", "Liczba punktów", "");
Wprowadz_Wszystkie_Dane(Dane, Ile_Osob, Min_Punkt, Max_Punkt);
Pisz_Naglowek("Nazwisko", "Liczba punktów", "Ocena");
Wyswietl_Wszystkie_Oceny(Dane, Ile_Osob);
delay(300);
Inicjuj_Grafike();
Wykres (Dane, Ile_Osob);
while (!kbhit())
{ }
closegraph();
} // koniec programu głównego
/*----------------------------------------------------------------*/
void Pisz_Naglowek (char Napis1[ ], char Napis2[ ], char Napis3[ ])
/* Procedura umożliwia napisanie nagłówka składającego się */
/* z max trzech wyrazów */
{
clrscr();
cout << Napis1;
gotoxy (32, wherey());
cout << Napis2;
gotoxy (55, wherey());
cout << Napis3 << endl;
cout << endl;
}
/*----------------------------------------------------------------*/
int Czyt_Int ( char Napisy[ ], int Ogr_d, int Ogr_g)
/* Funkcja umożliwia wczytanie liczby całkowitej oraz */
/* kontrolowanie formalnej i logicznej poprawności liczby */
{
int x, y, Liczba, r;
enum Boolean {false, true} Powtorz;
cout << Napisy;
x = wherex();
y = wherey();
while (1)
{
cin >> Liczba;
Powtorz = (Liczba < Ogr_d) || (Liczba > Ogr_g) || (cin.fail());
if (cin.fail())
{
cin.clear(cin.rdstate() & ~ios::failbit);
char L[80];
cin >> L;
}
if (Powtorz)
{
gotoxy (x, y);
clreol ();
}
else break;
}
return Liczba;
}
/*----------------------------------------------------------------*/
void Wprowadz_Jedna_Osobe(char Nazwisko[ ], int &Lp, int Ogr_d, int Ogr_g)
/* Procedura umożliwia wprowadzenie nazwiska i liczby punktów */
/* dla jednej osoby. */
/* UWAGA: po wprowadzeniu nazwiska nacisnąć <Enter>, */
/* wprowadzić liczbę punktów i nacisnąć <Enter>. */
{
cin >> Nazwisko;
gotoxy(32, wherey()-1);
Lp = Czyt_Int("", Ogr_d, Ogr_g);
}
/*----------------------------------------------------------------*/
void Wprowadz_Wszystkie_Dane(Osoba Dane[ ],
int Ile_Osob, int Ogr_d, int Ogr_g)
/* Procedura umożliwia wprowadzenie nazwisk i punktów */
/* dla całej grupy */
{
int i;
for (i=0; i < Ile_Osob; i++)
Wprowadz_Jedna_Osobe(Dane[i].Nazwisko, Dane[i].Punkty, Ogr_d, Ogr_g);
}
/*----------------------------------------------------------------*/
Stopnie Wystaw_Ocene ( int Lp )
/* Funkcja umożliwia wystawienie oceny na podstawie */
/* liczby uzyskanych punktów. */
{
Stopnie Wynik;
Lp = Lp/10;
switch (Lp)
{
default : { Wynik = ndst; break; }
case 5 : { Wynik = dst; break; }
case 6 : { Wynik = dst_plus; break; }
case 7 : { Wynik = db; break; }
case 8 : { Wynik = db_plus; break; }
case 9 : { Wynik = bdb; break; }
case 10 : { Wynik = bdb; break; }
}
return Wynik;
}
/*----------------------------------------------------------------*/
void Wyswietl_Ocene ( Stopnie Ocena)
/* Funkcja umożliwia wyświetlenie oceny w postaci słownej */
{
switch (Ocena)
{
case ndst : { cout << "niedostateczna\n"; break; }
case dst : { cout << "dostateczna\n"; break; }
case dst_plus : { cout << "dość dobra\n"; break; }
case db : { cout << "dobra\n"; break; }
case db_plus : { cout << "ponad dobra\n"; break; }
case bdb : { cout << "bardzo dobra\n"; break; }
}
}
/*----------------------------------------------------------------*/
void Wyswietl_Wszystkie_Oceny(Osoba Dane[ ], int Ile_Osob)
/* Procedura umożliwia wyświetlenie oceny w postaci słownej */
/* dla wszystkich osób. */
{
int i;
Stopnie Ocena;
for (i=0; i < Ile_Osob; i++)
{
Ocena = Wystaw_Ocene(Dane[i].Punkty);
cout << Dane[i].Nazwisko;
gotoxy(32, wherey ());
cout << Dane[i].Punkty;
gotoxy (55, wherey ());
Wyswietl_Ocene(Ocena);
}
}
/*----------------------------------------------------------------*/
void Inicjuj_Grafike(void)
/* Procedura umożliwia zainicjalizowanie trybu graficznego */
{
Sterownik = DETECT;
initgraph( &Sterownik, &Tryb, "" );
}
/*----------------------------------------------------------------*/
void Statystyka_Ocen(Osoba Dane[ ], int Ile_Osob, int Ocena_Ile[ ])
{
int i;
for (i=0; i<Ile_Osob; i++)
switch (Dane[i].Punkty / 10)
{
default : { Ocena_Ile[0] = Ocena_Ile[0] + 1; break; }
case 5 : { Ocena_Ile[1] = Ocena_Ile[1] + 1; break; }
case 6 : { Ocena_Ile[2] = Ocena_Ile[2] + 1; break; }
case 7 : { Ocena_Ile[3] = Ocena_Ile[3] + 1; break; }
case 8 : { Ocena_Ile[4] = Ocena_Ile[4] + 1; break; }
case 9 : { Ocena_Ile[5] = Ocena_Ile[5] + 1; break; }
case 10: { Ocena_Ile[5] = Ocena_Ile[5] + 1; break; }
}
}
/*----------------------------------------------------------------*/
void Legenda(int Ocena_Ile[], int Ile_Osob)
/* Procedura rysuje legendę do wykresu */
{
int i, y, y1;
char Ile[3];
char Ile_Proc[6];
setcolor(EGA_YELLOW);
settextstyle(DEFAULT_FONT, HORIZ_DIR,1);
settextjustify(LEFT_TEXT, CENTER_TEXT);
outtextxy(50, 100, "oceny");
outtextxy(498, 100, "liczba");
outtextxy(572, 100, "%");
rectangle(20, 119, 40, 419);
rectangle(600, 119, 620, 419);
for (i = 5; i>=0; i--)
{
setfillstyle(SOLID_FILL,i);
y = 119 + (5-i+1)*50;
line(20,y,40,y);
line(600,y,620,y);
floodfill(21, y-1, EGA_YELLOW);
floodfill(601, y-1, EGA_YELLOW);
y1 = y - 40;
switch (i)
{
case 0 : {outtextxy(50, y1, "2"); break;}
case 1 : {outtextxy(50, y1, "3"); break;}
case 2 : {outtextxy(50, y1, "3.5"); break;}
case 3 : {outtextxy(50, y1, "4"); break;}
case 4 : {outtextxy(50, y1, "4.5"); break;}
case 5 : {outtextxy(50, y1, "5"); break;}
}
itoa(Ocena_Ile[i], Ile, 10);
outtextxy(520, y1, Ile);
gcvt((100.0*Ocena_Ile[i])/Ile_Osob, 3, Ile_Proc);
outtextxy(565, y1, Ile_Proc);
}
}
/*----------------------------------------------------------------*/
void Wykres_Kolowy(int Ocena_Ile[], int Ile_Osob)
/* Procedura rysuje wykres kołowy */
{
int i;
int Alfa = 0, Beta = 0;
for (i = 5; i >= 0; i--)
{
Beta = Alfa + floor(360.0*Ocena_Ile[i]/Ile_Osob);
setfillstyle(SOLID_FILL, i);
if (Ocena_Ile[i] > 0)
pieslice(getmaxx()/2, 270, Alfa, Beta, 150);
Alfa = Beta;
if (Beta > 360)
Beta = 360;
}
}
/*----------------------------------------------------------------*/
void Wykres(Osoba Dane[ ], int Ile_Osob)
/* Procedura rysuje wykres kołowy oraz legendę */
{
int i;
Inicjuj_Grafike();
setcolor(EGA_RED);
rectangle(0,0,getmaxx(), getmaxy());
settextstyle(TRIPLEX_FONT, HORIZ_DIR, 4);
settextjustify(CENTER_TEXT, CENTER_TEXT);
setcolor(EGA_YELLOW);
outtextxy(getmaxx()/2, 25, "Statystyka ocen");
Statystyka_Ocen(Dane, Ile_Osob, Ocena_Ile);
Legenda(Ocena_Ile, Ile_Osob);
Wykres_Kolowy(Ocena_Ile, Ile_Osob);
}
/*----------------------------------------------------------------*/
27
(0, 0)
(640, 480)
Ala ma kota
320
160
Ala ma kota
320
160
Ala ma kota
320
160