Aleksander Timofiejew
Transkrypt
Aleksander Timofiejew
Programowanie Ćwiczenie „Język C. Środowisko programowania Visual Studio” Tematy ćwiczenia praca ze środowiskiem, tworzenie i uruchomienie programu, struktura programu, deklaracje i definicje typy standardowe, tworzenie okna konsolowego Sprawozdanie Na każdym zajęciu laboratoryjnym sporządza się za pomocą edytora Word sprawozdanie na bazie materiałów ćwiczenia. Bazowa zawartość sprawozdania musi być przygotowana przed ćwiczeniem (sprawozdanie do ćwiczenia pierwszego jest przygotowywane w czasie ćwiczenia). W czasie ćwiczenia do sprawozdania są dodawane wyniki testowania. Treść sprawozdania: strona tytułowa, spis treści sporządzony za pomocą Word'a, dla każdego zadania rozdziały "Zadanie", "Opracowanie zadania" (rozdział z tekstem programu, obliczeniami i komentarzami), "Testowanie" (rozdział z opisem danych wejściowych i wynikami testowania, w tym zrzuty okien). Wzorzec strony tytułowej znajduje się w pliku Strona_tytulowa_niestac_Programowanie_PWSBiA.doc. Nazwa pliku ze sprawozdaniem musi zawierać skrót "P_", numer ćwiczenia i nazwisko studenta (bez polskich liter, żeby można było archiwizować). Pliki ze sprawozdaniem są przekazywane do archiwum grupy. a) Program pierwszy Zadanie W środowisku Microsoft Visual Studio stworzyć projekt. Wybrać punkt menu „File / New / Project...”, zaznaczyć język programowania i podsystem „Visual C++ / Win32”, rodzaj aplikacji „Win32 Console Application”, wprowadzić na dole okna nazwę projektu, na przykład „Cw1”, oraz wybrać katalog, do którego będą zapisywane pliki. Nacisnąć „OK”. W oknie "Win32 Application Wizard" wybrać punkt menu "Application Settings". W oknie "Application Settings" ustawić opcję "Empty Project" i nacisnąć "Finish". Dalej należy dodać do projektu plik, w którym będzie umieszczony tekst programu. W tym celu nacisnąć prawym przyciskiem myszy na nazwę projektu w oknie "Solution Explorer", wybrać punkt "Add", wybrać punkt "New Item...". W oknie "Add New Item" zaznaczyć punkt "Code" w "Categories", punkt "C++ File" w "Templates", a na dole wpisać nazwę pliku z rozszerzeniem „.c” , na przykład "main.c"1. Nacisnąć "Add". Przez punkt menu "Project / Properties..." wyświetlić okno "Property Pages". W oknie zaznaczyć "Configuration Properties / General" i ustawić (lub sprawdzić ustawienie) opcję "Use of MFC" w stan "Use Standard Windows Libraries". Dalej w oknie "Property Pages" zaznaczyć "C/C++ / Advanced" i ustawić opcję "Compile As" w stan "Compile As C code (/TC)". Dalej w oknie "Property Pages" zaznaczyć "C/C++ /Precompiled Headers" i ustawić opcję "Precompiled Header" w stan "Not Using Precompiled Headers". Zatwierdzić zmiany naciskając „Zastosuj” i „OK”. Zamknąć okno "Property Pages". Do głównego programu (tj. do pliku „main.c”) wprowadzić tekst: #include <stdio.h> #include <Windows.h> int main(void) { char tt[]="Program w C. <imię, nazwisko> \r\n\r\n"; char buf[128]; //-----------------CharToOemA(tt,buf); //zamiana kodowania printf(buf); //wyprowadzenie na ekran //-----------------system("pause"); //zatrzymanie okna MS DOS return 0; } Na końcu funkcji main jest dodane wywołanie funkcji system(): system("pause"); żeby aplikacja nie znikała z ekranu. Funkcja CharToOemA() zamienia kody polskich znaków komunikatu. Wykonać kompilację przez punkt menu „BUILD/Rebuild Solution”. Uruchomić program w oknie konsolowym (oknie MS DOS) naciskając punkt menu "DEBUG / Start Debugging" lub przyciski Ctrl+F5, lub wykonując operacji w MS DOS w oknie otwartym w Explorator Windows przez punkt menu „Plik / Otwórz wiersz poleceń”. Zapisać projekt w trybie „File / Save All”. Opracowanie zadania <tekst programu> Testowanie <zrzut okna aplikacji> 1 Kompilator w środowisku Visual Studio przekształca plik z programem w zależności od rozszerzenia: dla rozszerzenia ".cpp" tekst jest kompilowany w języku C++, dla rozszerzenia ".c" tekst jest kompilowany w języku C. ----------------------------------------------------------------------------------------------------------------- b) Wykrywanie błędów Zadanie Przeanalizować program w trybie wykrywania usterek (trybie debuggowania). Ustawić punkt zatrzymania na pierwszej instrukcji funkcji main. Uruchomić aplikację. Skierować do okna Watch (punkt menu Debug/Quick Watch...) wszystkie zmienne. W trybie "Step Over" wykonać instrukcje programu do instrukcji return. Testowanie <zrzut okna ze strzałkami debuggera> ----------------------------------------------------------------------------------------------------------------- c) Tworzenie okna konsolowego Zadanie W programie otworzyć okno konsolowe. Wyświetlić okno i komunikaty innymi kolorami niż kolory okna MS DOS. Na środku okna wypisać komunikat „Kolory są ustawione przez <imię i nazwisko>”. Opracowanie zadania <tekst programu> Testowanie <zrzut okna aplikacji> ----------------------------------------------------------------------------------------------------------------Zamknąć środowisko Visual Studio. Wskazówki Tworzenie okna konsolowego Konsolową nazywamy aplikację, w której stosuje się tylko tekstowy tryb monitora. Aplikacja konsolowa przyjmuje polecenia użytkownika z klawiatury lub od myszy oraz wyświetla wyniki obliczeń w postaci tekstu. Aplikacja konsolowa może być otwarta w osobnym oknie lub aplikacja może korzystać z okna MS DOS, które Windows otwiera spod punktu menu Plik / Otwórz wiersz poleceń. Do zalet aplikacji konsolową należy szybkość jej napisania, co wynika z prostego faktu, że nie trzeba opracowywać graficzną część aplikacji. System Windows tworzy okno konsoli jako okno najprostszego rodzaju i kieruje do okna minimalną ilość komunikatów. Do komunikacji z oknem konsoli Windows tworzy trzy bufory: wejściowy, przez który konsola przyjmuje symboli z klawiatury, wyjściowy, zawartość którego jest wyświetlana przez konsolę, komunikatów o błędach. Każdy z buforów posiada deskryptor. Do pobrania deskryptora buforu służy funkcja API GetStdHandle. Na rodzaj deskryptora wskazuje stała STD_INPUT_HANDLE lub STD_OUTPUT_HANDLE. W aplikacjach konsolowych często jest stosowana funkcja CharToOem, która zamienia kody znaków tekstu na kody OEM (Original Equipment Manufacturer), co powoduje na polskojęzycznym komputerze wyświetlenie polskich znaków. Przez stos funkcja otrzymuje dwa argumenty: wskaźnik na wiersz źródłowy i wskaźnik na bufor dla tekstu przekształconego. Fragmenty programu konsolowego //Aplikacja z tworzeniem okna konsoli #include <stdio.h> #include <stdlib.h> #include <math.h> #include <conio.h> #include <windows.h> char tytul[]="..."; char tekst1[]="..."; char tekst2[]="\r\n\r\nAby zakończyć program należy wprowadzić znak z klawiatury"; char buf[128]; HANDLE hinp,hout; COORD pole; int rbuf,rfakt,rout,lengbuf; //--- Kolory ---unsigned short kolor1 = 0xFC; // Bity koloru: BG_I,R,G,B,FG__I,R,G,B unsigned short kolor2 = 0xF9; // Bity koloru: BG_I,R,G,B,FG__I,R,G,B int main(void) { //--- tworzenie konsoli --FreeConsole(); AllocConsole(); //--CharToOemA(tytul,tytul); SetConsoleTitleA(tytul); //--hout=GetStdHandle(STD_OUTPUT_HANDLE);//deskryptor buforu wyjściowego hinp=GetStdHandle(STD_INPUT_HANDLE); // deskryptor buforu wejściowego //--- obliczenie rozmiaru buforu ekranu pole=GetLargestConsoleWindowSize(hout); rbuf=pole.X * pole.Y; //--- napełnienie komórek jednakowym atrybutem --pole.X=0; pole.Y=0; FillConsoleOutputAttribute(hout,kolor2, rbuf,pole,&rfakt); //--- ustawienie kursora --pole.X=0; pole.Y=20; SetConsoleCursorPosition(hout,pole); //ustawienie pozycji kursora //--- wyprowadzenie komunikatu informacyjnego --SetConsoleTextAttribute(hout,kolor1); CharToOemA(tekst1,buf); //konwersja polskich znaków lengbuf=(int)strlen(buf); WriteConsoleA(hout,buf,lengbuf,&rfakt,NULL); //--CharToOemA(tekst2,buf); //konwersja polskich znaków lengbuf=(int)strlen(buf); WriteConsoleA(hout,buf,lengbuf,&rfakt,NULL); //--_getch(); //zatrzymanie zniknięcia okna //--- zamknięcie konsoli FreeConsole(); return 0; } Funkcje API (Application Programming Interface) Win32 Na początku programu z funkcjami API Win32 należy dodawać instrukcję dla kompilatora: #include <windows.h> Funkcje API Win32 przyjmują parametry tylko przez stos; nie stosuje się przekazywania parametrów przez rejestry. Nazwa bibliotecznej funkcji API może być trochę inna niż nazwa pokazana przez system na ekranie pomocy. Na przykład w bibliotekach import32.lib i user32.lib znajduje się funkcja WriteConsoleA, a na ekranie widzimy informacje o funkcji WriteConsole. Dodatkowa litera A w nazwie funkcji WriteConsoleA i podobnych funkcji odpowiada rodzaju tej funkcji dla wierszy w kodzie ANSI. Jeśli na końcu nazwy funkcji jest litera W, to funkcja operuje wierszami UNICODE. Na zakończenie swojego działania funkcja API przez rejestr - akumulator EAX zwraca wartość, która jest wynikiem obliczeń. Często wartość 0 lub wartość dodatnia odpowiadają pomyślnemu zakończeniu działań, a wartość -1 wskazuje na niepowodzenie. W przypadku niepowodzenia funkcja API wywołuje funkcję SetLastError, do której przekazuje podwójne słowo z kodem niepowodzenia. Ten kod można przeczytać wywołując funkcje GetLastError bezpośrednio po wywołaniu funkcji API. Aby komunikaty były wyświetlane na ekranie z poprawnymi polskimi literami, należy stosować funkcję CharToOemA() z zestawu "Platform SDK (Software Development Kit)". Funkcja CharToOemA() pobiera tekst z pierwszego argumentu - tablicy tekstowej, przekoduje i zapisuje do drugiego argumentu - tablicy tekstowej. Aby zastosować funkcję CharToOemA() należy umieścić tekst w tablicy tekstowej oraz zdefiniować bufor tekstowy, na przykład: char tekst[]="Program w C. Autor Ąćęł Ńóśżź \r\n\r\n"; char buf[256]; CharToOemA(tekst,buf); printf(buf); Funkcje API Win32 związane z konsolą BOOL AllocConsole(void); //Alokacja konsoli. BOOL FreeConsole(void); //Zamykanie wszystkich konsoli. HANDLE GetStdHandle(DWORD nStdHandle) Pobranie deskryptora buforu konsoli: wejściowego przy nStdHandle = STD_INPUT_NANDLE, wyjściowego przy nStdHandle = STD_OUTPUT_NANDLE. BOOL SetConsoleTitleA(LPCTSTR lpConsoleTitle); Wypisywanie nagłówka okna konsolowego. Argument: lpConsoleTitle – adres wiersza – nagłówka. BOOL SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes); Ustawienie atrybutów tekstowych. Argumenty: hConsoleOutput – deskryptor buforu wyjściowego konsoli, wAttributes – kolor. COORD GetLargestConsoleWindowSize(HANDLE hConsoleOutput); Zwraca maksymalny rozmiar okna konsoli. Argument: hConsoleOutput – deskryptor buforu wyjściowego konsoli. Struktura typu COORD: typedef struct _COORD { SHORT X; //współrzędna X SHORT Y; //współrzędna Y } COORD, *PCOORD; BOOL FillConsoleOutputAttribute(HANDLE hConsoleOutput,WORD wAttribute, DWORD nLength,COORD dwWriteCoord,LPDWORD lpNumberOfAttrsWritten); Wpisuje do buforu wyjściowego (ekranu) atrybuty znakowe. Argumenty: hConsoleOutput – deskryptor buforu wyjściowego konsoli, wAttribute – kolor, nLength – ilość pozycji, dwWriteCoord – współrzędne X, Y pierwszej pozycji w oknie konsoli, lpNumberOfAttrsWritten – adres zmiennej, do której będzie zapisana faktyczna ilość pozycji. BOOL SetConsoleCursorPosition(HANDLE hConsoleOutput,COORD dwCursorPosition); Ustawienie pozycji kursora. Argumenty: hConsoleOutput – deskryptor buforu wyjściowego konsoli, dwCursorPosition – współrzędne X, Y (typ COORD) pozycji w oknie konsoli. BOOL WriteConsoleOutputCharacter(HANDLE hConsoleOutput, LPCTSTR lpCharacter,DWORD nLength,COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten); Wyprowadzenie znaków od pozycji kursora. Argumenty: hConsoleOutput – deskryptor buforu wyjściowego konsoli, lpCharacter – adres bufora z tekstem, nLength – ilość znaków, dwWriteCoord – współrzędne X, Y pierwszej pozycji w oknie konsoli, lpNumberOfCharsWritten – adres zmiennej, do której będzie zapisana faktyczna ilość wyprowadzonych znaków. BOOL WriteConsole(HANDLE hConsoleOutput,const VOID* lpBuffer, DWORD nNumberOfCharsToWrite,LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved); Wyprowadzenie znaków do buforu konsoli Argumenty: hConsoleOutput – deskryptor buforu wyjściowego konsoli, lpBuffer – adres bufora z tekstem, nNumberOfCharsToWrite – ilość znaków, lpNumberOfCharsWritten – adres zmiennej, do której będzie zapisana faktyczna ilość wyprowadzonych znaków,. lpReserved – rezerwa (musi być 0). Funkcje standardowe Funkcja printf wyprowadza dane do strumienia wyjściowego stdout, tj. na ekran monitora w trybie tekstowym. Zaznaczając słowo "printf" i naciskając F1 można otrzymać pełną informację o tej funkcji, a w tym o nazwie pliku nagłówkowego stdio.h zawierającego deklarację funkcji. Aby wprowadzić nazwie pliku nagłówkowego, należy na początku programu dodać instrukcję kompilatora, na przykład: #include <stdio.h> Funkcja getch czeka na wprowadzenie znaku z klawiatury. System operacyjny Windows też "czeka", i okno nie znika. Funkcja getch zwraca kod znaku. Opis funkcji getch znajduje się w pliku conio.h. Należy na początku pliku dodawać instrukcję dla kompilatora: #include <conio.h> Typy standardowe Liczbowe typy danych języka C są przedstawione w niżej położonej tabeli. Rodzaj danych i zakres wartości Liczba całkowita od -128 do +127 Liczba całkowita bez znaku od 0 do 255 Liczba całkowita od -32768 do +32767 Liczba całkowita bez znaku od 0 do 65535 Liczba całkowita od -2147483648 do +2147483647 Liczba całkowita od 0 do +4294967295 Liczba całkowita od -9223372036854775808 do +9223372036854775807 Liczba całkowita bez znaku od 0 do 18446744073709551615 Liczba rzeczywista ze znakiem, dokładność 7 cyfr Liczba rzeczywista ze znakiem, dokładność 15 cyfr Liczba rzeczywista ze znakiem, dokładność 18 cyfr Typ signed char unsigned char (lub char) short int (lub short) unsigned short int(lub unsigned short) long int(lub long, lub int) Rozmiar w bajtach 1 1 2 2 4 unsigned long int(lub unsigned long) (lub unsigned int) long long int(lub long long) 4 unsigned long long int (lub unsigned long long) float 8 double 8 long double 10 8 4 Znakowe typy danych języka C są przedstawione w niżej położonej tabeli. Rodzaj danych i zakres wartości Znak w kodzie rozszerzonego ASCII Znak w kodzie UNICODE UTF-16 Znak w kodzie UNICODE UTF-32 Typ signed char, unsigned char short int, unsigned short int long int, unsigned long int, float Rozmiar w bajtach 1 2 4 W języku C nie ma typu logicznego. Dla deklaracji zmiennych z dwoma wartościami „fałsz” i „prawda” stosuje się typ "int" oraz wartości 0 i nie 0.