LEKCJA 19: KILKA INNYCH PRZYDATNYCH FUNKCJI. ________________________________________________________________ W trakcie tej lekcji dowiesz się, jak zapisać teksty na dysku i jak jeszcze można nimi manipulować przy pomocy gotowych funkcji Borland C++. ________________________________________________________________ Program poniżej demonstruje zastosowanie trzech przydatnych funkcji: [P072.CPP] #include int main(void) { int i, x = 0, y = 0; clrscr(); for (i = 1; i < 10; i++) { y = i; x = 5*i; textbackground(16-i); textcolor(i); gotoxy(x, y); cprintf("Wspolrzedne: x=%d y=%d", x, y); getch(); } return 0; } textbackground() - ustaw kolor tła pod tekstem texcolor() - ustaw kolor tekstu gotoxy() - rozpocznij drukowanie tekstu od punktu o współrzędnych ekranowych x - numer kolumny (w normalnym trybie: 1-80) y - numer wiersza (w normalnym trybie: 1-25) [Z] ________________________________________________________________ 1. Rozmieść na ekranie napisy i znaki semigraficzne tworzące rysunek tabelki. 2. Opracuj program, w którym pojedyncze znaki, bądź napisy będą poruszać się po ekranie. 3. Spróbuj przyspieszyć działanie swojego programu z poprzedniego zadania poprzez wstawkę w assemblerze. ________________________________________________________________ OPERACJE PLIKOWE - NIEOBIEKTOWO. W systemia DOS dane i programy są zgrupowane w pliki. Pliki (ang. file) mogą być TEKSTOWE i BINARNE. Najczęstszymi operacjami na plikach są: * Utworzenie nowego pliku (ang. CREATE); * Odczyt z pliku (ang. READ); * Zapis do pliku (WRITE); * Otwarcie pliku (OPEN); * Zamknięcie pliku (CLOSE); * Wyszukanie danej w pliku (SEEK); W kontaktach z urządzeniami - np. z dyskiem pośredniczą DOS i BIOS. To system DOS wie, gdzie na dysku szukać pliku (katalogu) o podanej nazwie i w których sektorach dysku znajdują się fizycznie dane należące do danego pliku. Operacje z plikami opierają się o odwoływanie do systemu operacyjnego za pośrednictwem tzw. Deskryptora pliku (File Descriptor - numer identyfikacyjny pliku). Zestaw "narzędzi" potrzebnych nam do pracy to: IO.H - prototypy funkcji obsługi WEjścia/WYjścia (ang. Input/Output=IO); FCNTL.H - plik zawierający definicje wymienionych poniżej stałych: O_BINARY - otwarcie pliku w trybie binarnym; O_TEXT - otwarcie pliku w trybie tekstowym; O_RDONLY (Open for Read Only) - otwórz tylko do odczytu; O_WRONLY (...Write Only) - tylko dla zapisu; O_RDWR (Reading and Writing) dozwolony zapis i odczyt; STAT.H - zawiera definicje stałych S_IREAD - plik tylko do odczytu (przydatne dla funkcji creat); S_IWRITE - tylko zapis (przydatne dla funkcji creat); FUNKCJE: int open(p1, p2, p3) - trójparametrowa funkcja otwierająca plik; (parametry patrz przykład) zwraca do programu Wynik = -1 (operacja zakończona niepowodzeniem - np. nie ma pliku) lub Wynik = File Descriptor - numer pliku przekazany przez DOS. int creat(p1, p2) - funkcja tworząca nowy plik; int read(...) - funkcja czytająca z pliku; int write(...) - funkcja zapisu do pliku; imt close(...) - zamknięcie pliku. Po uruchomieniu program otwiera automatycznie trzy standardowe pliki, związane z urządzeniami: 0 - stdin - standardowy plik wejściowy (norm. klawiatura konsoli); 1 - stdout - standardowy plik wyjściowy (norm. monitor); 2 - stderr - standardowy plik wyjściowy - diagnostyczny (komunikaty o błędach). [S] STD... STandarD INput - standardowe wejście. STD OUTput - standardowe wyjście. STD ERRors - plik diagnostyczny. //[P072-2.CPP] # include # include # include //Duze litery tylko dla podkreslenia # include # include char *POINTER; int IL_znakow, DLUG_pliku, TRYB_dostepu, Wynik, i; int Plik_1, Plik_2; char BUFOR[20] = {"TEKST DO PLIKU"}; char STOS[3], ZNAK='X'; main() { POINTER = &BUFOR[0]; printf("Wloz dyskietke do A: i nacisnij cos...\n"); Plik_1 = creat( "a:\\plik1.dat", S_IWRITE); if (Plik_1 == -1) printf("\n Nie udalo sie zalozyc plik1.dat..."); Plik_2 = creat( "a:\\plik_2.dat", S_IWRITE); if (Plik_2 == -1) printf("\n Klops przy Plik2.dat"); _fmode = O_BINARY; //Bedziemy otwierac w trybie binarnym Wynik = open( "a:\\plik1.dat", O_WRONLY ); if (Wynik == -1) printf("\n Nie udalo sie otworzyc pliku..."); IL_znakow = 15; //Ilosc znakow do zapisu Wynik =write( Plik_1, POINTER, IL_znakow ); printf("Zapisalem %d znakow do pliku.", Wynik); close( Plik_1 ); Plik_1 = open("a:\\Plik1.dat", O_RDONLY ); Plik_2 = open("a:\\Plik_2.dat", O_WRONLY ); POINTER = &STOS[0]; for (i=1; ZNAK; i++) //Kopiuje plik + spacje { STOS[1] = ZNAK; write( Plik_2, POINTER, 2); read( Plik_1, &ZNAK, 1); } close(Plik_1); close(Plik_2); getch(); return 0; } Przykładowy program wykonuje następujące czynności: 1. Tworzy plik a:\plik1.dat (potrzebny dostęp do dyskietki a:). 2. Tworzy plik a:\plik_2.dat. 3. Otwiera plik a:\plik1.dat w trybie binarnym tylko do zapisu. (ZWRÓĆ UWAGĘ, że tryb binarny nie przeszkadza zapisać tekstu.) 4. Dokonuje zapisu do pliku. 5. Zamyka plik a:\plik1.dat. 6. Otwiera plik1.dat w trybie binarnym tylko do odczytu. 7. Otwiera plik_2.dat tylko do zapisu. 8. Kopiuje plik1.dat do plik_2.dat dodając spacje. Zwróć uwagę na konstrukcję: for(i=1; ZNAK; i++) Wyjaśnienie. Póki jest znak wykonuj kopiowanie. Przypominam, że koniec to NUL - '\0'. Jeśli czytamy i piszemy po kolei - wszystko jest proste. Jeżeli natomiast chcemy wyszukać w pliku określone miejsce, to będzie nam jeszcze dodatkowo potrzebny mechanizm do określenia pozycji w pliku - tzw. WSKAŹNIK PLIKOWY. Pozycję można określać względem początku pliku: SEEK_SET - stała określająca pozycjonowanie względem początku pliku; SEEK_CUR - względem położenia bieżącego (ang. Current - bieżący); SEEK_END - określenie pozycji względem końca pliku; EOF - End Of File - znak końca pliku. Funkcja lseek(): WSK_PLK = long int lseek( plik, o_ile, kierunek); służy do pozycjonowania w pliku. Liczba typu long int określająca pozycję w pliku nazywana jest WSKAŹNIKIEM PLIKOWYM ( w programie przykładowym została oznaczona long int WSK_PLK). W programie przykładowym wykonywane jest kolejno: * utworzenie na dysku pliku PROBA.DAT; * zapis do pliku wprowadzonych z klawiatury liczb całkowitych typu int; * zamknięcie pliku; * otwarcie pliku do odczytu; * ustawienie wskaźnika na końcu pliku; * odczyt z pliku od końca; * wyprowadzenie odczytanych z pliku danych na ekran. [P073.CPP] # include "sys\stat.h" # include "conio.h" # include "stdio.h" # include "io.h" # include "fcntl.h" # define Cofnij_o_Zero 0 # define dwa_bajty 2 int Numer = 0; int Plik, L, M, i; long int Dlug_Pliku; main() { clrscr(); creat("A:\PROBA.DAT", S_IWRITE); printf("\nPodaj liczbe rozna od zera, zero - KONIEC"); _fmode=O_BINARY; Plik=open("A:\PROBA.DAT", O_WRONLY); do { printf("\n Nr liczby \t%d\t\t", Numer++); scanf("%d", &L); if (L) write(Plik, &L, 2); } while (L != 0); close(Plik); getch(); printf("\n Teraz odczytam te liczby z pliku \n"); Plik=open("A:\PROBA.DAT", O_RDONLY); Dlug_Pliku=lseek(Plik, 0, SEEK_END); for (i=Dlug_Pliku-dwa_bajty; i>=0; i-=2) { lseek(Plik, i, SEEK_SET); read(Plik, &M, dwa_bajty); printf("%d, ", M); } close(Plik); getch(); return 0; } [Z] ________________________________________________________________ Opracuj program wykonujący operacje na tekstach opisane wcześniej na łańcuchach tekstowych pobieranych z zewnętrznych plików dyskowych i umieszczanych w wynikowych plikach tekstowych. ________________________________________________________________