Tablice znakóW – ŁAŃcuchy



Pobieranie 70.42 Kb.
Data09.05.2016
Rozmiar70.42 Kb.

ZAAWANSOWANE PROGRAMOWANIE W JĘZYKU C++

  1. TABLICE ZNAKÓW – ŁAŃCUCHY

Teksty w tablicach przechowuje się w taki sposób, że po ciągu znaków następuje znak o kodzie 0 (NULL). Stąd rozmiar tablicy znaków wypada o jeden większy niż ilość znaków. Właśnie taki ciąg znaków zakończony znakiem NULL (zerem – ‘\0’ ) nazywamy łańcuchem.


char T[80] = {"C++"};
Zainicjowano tablicę znaków T, której przypisano łańcuch mniejszy niż rozmiar tablicy. Niewykorzystanym elementom tablicy przypisywana jest wówczas wartość zerowa.
char T[]={"C++"};

char T[]={’C’,’+’,’+’,’\0’};


W tym przypadku zapisy są równoważne. Otrzymaliśmy dwie czteroelementowe tablice, chociaż w pierwszym przypadku znak NULL został dodany automatycznie. Ponadto rozmiar tablicy jest tutaj ustalany na podstawie podanego łańcucha.



    1. OPERACJE NA ŁAŃCUCHACH


char *strcpy (char *s1, const char *s2)

Funkcja kopiuje łańcuch s2 do łańcucha s1 (znak końca łańcucha s2 również jest kopiowany). Wartością funkcji jest s1.



char *strcat (char *s1, const char *s2)


Funkcja dołącza łańcuch s2 na koniec łańcucha s1. Wartość funkcji stanowi adres (wskaźnik) łańcucha powstałego w wyniku połaczenia.
char *strchr (const char *s, int c)

Funkcja znajduje pierwsze wystąpienie znaku c w łąńcuchu s. Wartością funkcji jest wskaźnik pierwszego odnalezionego znaku lub NULL, jeśli szukany znak nie występuje w łańcuchu s.


char *strstr (cont char *s1, const char *s2)

Funkcja przeszukuje łańcuch s1 w poszukiwaniu podłańcucha s2. Wartością funkcji staje się adres pierwszego znaku odnalezionego podłańcucha lub NULL, jeśli podłańcuch s2 nie występuje w łańcuchu s1.


int strcmp (const char *s1, const char *s2)

Funkcja porównuje łańcuchy s1 i s2 przez bezpośrednie porównanie odpowiadających sobie znaków należących do tych łańcuchów.

Wartość funkcji jest:

<0 jeśli s1

=0 jeśli s1=s2

>0 jeśli s1>s2
int strlen (const char *s)

Funkcja zwraca długość łańcucha s.


char strlwr (char *s)

Funkcja zamienia duże litery (A..Z) w łańcuchu s na małe (a..z). Inne znaki nie są zmieniane. Wartością funkcji jest wskaźnik łańcucha s.


char strrev (char *s)

Funkcja odwraca łańcuch, tzn. ustawia znaki łańcucha w odwrotnej kolejności. Wartością funkcji jest adres odwróconego łańcucha s.


char *strupr (char *s)

Funkcja zamienia wszystkie małe litery (a..z) łańcucha s na duże (A..Z). Wartością funkcji staje się s.



FUNKCJE KONWERSJI

Konwersje łańcuch ↔ liczba całkowita



int atoi (const char *s)

long atol (const char *s)

Powyższe funkcje przekształcają łańcuch wskazywany przez parametr s w liczbę całkowitą typu int (funkcja atoi) lub long (funkcja atol), która staje się wartością funkcji. Pierwszy nie rozpoznany znak kończy konwersję, wartość funkcji jest wówczas równa 0.


char *itoa (int k, char *s, int r)

char *ltoa (long k, char *s, int r)

Funkcje te zamieniają liczbę całkowitą określoną parametrem k na łańcuch reprezentujący ją w systemie liczenia o podstawie r. Aby uzyskać łańcuch reprezentujący zadaną liczbę w systemie dziesiątkowym, parametrowi r należy nadać wartość 10. Funkcja itoa zamienia liczbę typu int, natomiast ltoa liczbe typu long. W obu przypadkach, jeśli parametr k ma wartość ujemną, znak minus zostanie umieszczony w łańcuchu. Funkcje zwracają adres określony parametrem s. Funkcja itoa może wykorzystać maksymalnie 17 znaków łańcucha docelowego, ltoa natomiast 33 znaki. Parametr r może mieć wartość z przedziału <2, 36>. W przypadku podania złej podstawy łańcuch wynikowy będzie pusty.



Konwersje łańcuch ↔ liczba rzeczywista



double atof (const char *s)

Funkcja przekształca łańcuch wskazywany przez parametr s w liczbę rzeczywistą typu double. Liczba staje się wartością funkcji. Pierwszy nie rozpoznany znak kończy konwersję.


char *ecvt (double k, int d, int *p, int *z)

char *fcvt (double k, int d, int *p, int *z)

Funkcja ecvt zamienia liczbę rzeczywistą określoną parametrem k na łańcuch zawierający d cyfr. W łańcuchu tym nie jest umieszczany przecinek dziesiętny, lecz jego pozycja mierzona względem początku łańcucha zostaje przypisana zmiennej *p. Jeśli zmienna ta zawiera wartość ujemną, oznacza to, że przecinek dziesiętny leży przed pierwszym znakiem łańcucha. Jeśli znak liczby k jest ujemny, zmiennej *z zostanie przypisana wartość różna od zera, w przeciwnym razie jej wartość jest równa zero. Wartość funkcji stanowi adres statycznej zmiennej używanej przez funkcję ecvt do przechowywania łańcuchów cyfr odpowiadających zamienianej liczbie. Zawartość tej zmiennej ulega zmianie po każdym wywołaniu funkcji ecvt.

Funkcja fcvt działa podobnie jak funkcja ecvt – z ta różnicą, że parametr d określa liczbę cyfr znajdujących się na prawo od przecinka dziesiętnego.


  1. TYP PLIKOWY – PODEJŚCIE PROCEDURALNE

Poniżej przedstawiono zestaw funkcji bibliotecznych umożliwiających korzystanie z plików dyskowych. Plik dyskowy przetwarzany za pomocą tych funkcji może być uważany za ciąg pozycji bajtowych, w których jest wyróżniona jedna pozycja aktualna. Zapis lub odczyt danych rozpoczyna się zawsze od pozycji aktualnej i powoduje przesunięcie tej pozycji w kierunku końca pliku o liczbę przeczytanych lub zapisanych bajtów. Podczas zapisu danych po osiągnięciu końca pliku długość ciągu bajtów reprezentujących ten plik jest zwiększana.

Korzystanie z pliku rozpoczyna się od jego otwarcia, czyli zgłoszenia systemowi operacyjnemu potrzeby dostępu do wskazanego pliku dyskowego. Operacja otwarcia pliku wytwarza wskaźnik pliku, który powinien stać się wartością zmiennej wskaźnikowej typu FILE*. Typ ten jest zdefiniowany w bibliotece stdio.h. Po wykonaniu wszystkich operacji zapisu lub odczytu danych plik powinien zostać zamknięty.


    1. FUNKCJE OTWIERAJĄCE I ZAMYKAJĄCE PLIKI



FILE* fopen (const char* nazwa, const char* tryb)

Funkcja otwiera plik wskazany za pomocą argumentu nazwa, który może być nazwą pliku odnoszącą się do katalogu bieżącego lub może określać pełną ścieżkę dostępu do pliku. Drugi argument tryb ustala sposób dostępu do pliku:



r odczyt istniejącego pliku

w utworzenie pliku do zapisu

a zapis na końcu istniejącego pliku

r+ zapis lub odczyt istniejącego pliku

w+ utworzenie pliku do zapisu i odczytu

a+ zapis lub odczyt na końcu istniejącego pliku

Po otwarciu aktualną pozycją jest początkowy bajt pliku dla trybów r, r+ lub w, w+ albo bajt znajdujący się za ostatnim dotąd zapisanym bajtem dla trybów a, a+.

Otwarcie istniejącego już pliku w trybie w lub w+ powoduje utratę zapisanych w nim dotąd danych. Gdy natomiast plik otwierany w trybie a lub a+ jeszcze nie istnieje, to zostanie on utworzony.

Wymienione tryby można uzupełnić literą t lub b (np. rt, rt+, wb, a+b). Litera t oznacza plik tekstowy, litera b plik binarny.

Gdy plik został otwarty, wynikiem funkcji fopen jest wskaźnik pliku, po nieudanej próbie otwarcia pliku wynikiem jest NULL.
int fclose (FILE *plik)

Funkcja zamyka plik, którego wskaźnik jest wartością argumentu plik.

Wynikiem funkcji fclose jest 0, gdy operacja zamknięcia pliku została zakończona poprawnie.



    1. FUNKCJE USTALAJĄCE AKTUALNĄ POZYCJĘ PLIKU I BADAJĄCE OSIĄGNIĘCIE KOŃCA PLIKU


long ftell (FILE *plik)

Funkcja odczytuje aktualną pozycję pliku wyrażoną w bajtach.

Wynikiem funkcji ftell jest liczba określająca aktualną pozycję pliku lub wartość –1L w wypadku wystąpienia błędu.
int fseek (FILE *plik, long pozycja, int cel)

Funkcja ustala aktualną pozycję pliku wskazanego za pomocą argumentu plik. Wartością argumentu pozycja powinno być 0 lub wartość uzyskana po wykonaniu funkcji ftell. Wartość parametru pozycja może być również ujemna (przesunięcie wstecz), jak i dodatnia (przesunięcie w przód). Argumentem cel może być jedna ze stałych:

SEEK_SET 0 początek pliku

SEEK_CUR 1 aktualna pozycja pliku

SEEK_END 2 koniec pliku

Wynikiem funkcji fseek jest 0, gdy aktualna pozycja pliku została poprawnie ustalona.


void rewind (FILE *plik)

Funkcja ustala aktualną pozycję na początku pliku wskazanego za pomocą argumentu plik.


int feof (FILE *plik)

Funkcja odczytuje stan znacznika końca pliku. Gdy podczas ostatniej operacji odczytu napotkano koniec pliku, to wynikiem funkcji feof jest wartość niezerowa, w przeciwnym wypadku wynikiem jest 0.




    1. FUNKCJE CZYTAJĄCE I ZAPISUJĄCE DANE



int fgetc (FILE *plik)

Funkcja odczytuje ze wskazanego pliku kolejny znak.



int fputc (int znak, FILE *plik)

Funkcja zapisuje do wskazanego pliku kolejny znak.


char *fgets (char *napis, int liczba, FILE *plik)

Funkcja odczytuje ze wskazanego pliku ciąg znaków o długości co najwyżej (liczba-1) znaków. Mniejsza liczba znaków jest odczytywana, gdy zostanie napotkany znak nowej linii. Odczytany ciąg znaków jest zapisywany jako parametr napis, na końcu dodawany jest znak końca ciągu o wartości 0.

Wynikiem funkcji fgets jest wskaźnik zapisanego ciągu znaków, w przypadku napotkania końca pliku wynikiem jest NULL.
int fputs (char *napis, FILE *plik)

Funkcja zapisuje do wskazanego pliku ciąg znaków, wskazany za pomocą argumentu napis.

Wynikiem funkcji fputs jest wartość ostatniego zapisanego znaku, a w przypadku wystąpienia błędu wynikiem jest EOF.
int fscanf (FILE *plik, const char *format, wskaźnik, wskaźnik, ...)

Funkcja odczytuje ze wskazanego pliku ciągi znaków, dokonuje ich konwersji na wartości binarne i zapamiętuje te wartości w miejscach pamięci wskazanych za pomocą argumentów będących wskaźnikami. Wartością argumentu format jest ciąg wzorców konwersji, których postać jest taka sama jak dla funkcji scanf.


int fprintf (FILE *plik, const char *format, wyrażenie, wyrażenie, ...)

Funkcja zapisuje we wskazanym pliku ciągi zanaków zadane za pomocą wyrażeń będących jej argumentami. Sposób konwersji wartości wyrażeń na ciągi znaków określa argument format, będący ciągiem znaków zawierającym znaki wpisywane bezpośrednio do pliku dyskowego i wzorce konwersji. Postać wzorca konwersji jest taka sama jak dla funkcji printf.


Przykład 2.1.

Program zapisujący do pliku tekstowego wszystkie liczby podzielne przez 5 z zakresu [10,50] oraz wyświetlający zawartość pliku na ekranie.


#include

#include


void Wczytaj (FILE *plik)

{

for (int i=10;i<=50;i+=5)



fprintf(plik,"%d\n",i);

}
void Wyswietl (FILE *plik)

{

int liczba;



rewind(plik);

while (!feof(plik))

{

fscanf(plik,"%d\n",&liczba);



cout<

}

cout<

}
int main (void)

{

FILE *plik;



plik = fopen ("C:\\liczby.txt","wt+");

if (plik==NULL) cout<<"Plik nie zostal otwarty"<

else

{

Wczytaj(plik);



Wyswietl(plik);

fclose(plik);

}

getch();


return 0;

}


  1. TYP PLIKOWY – STRUMIENIE


Biblioteka fstream.h zawiera definicje klas umożliwiających prosty dostęp do plików dyskowych. Pliki te są traktowane jak strumienie wejściowe lub wyjściowe, reprezentowane przez obiekty klas ifstream (pliki wejściowe) i ofstream (pliki wyjściowe). Obiekty reprezentujące pliki mogą być argumentami operatorów strumieniowych >>, <<. Wymienione klasy udostepniają funkcje składowe:



open - otwarcie pliku o podanej nazwie w trybie znakowym
close - zamknięcie pliku

W zależności od rodzaju operacji wykonywanych na danych zawartych w pliku, może on być otwierany w różnych trybach. Dostępne są następujące specyfikatory trybu otwarcia pliku zdefiniowane w klasie ios:





Specyfikator

Znaczenie

ios::app

dopisuj dane na końcu pliku

ios::ate

przesuń wskaźnik na koniec pliku

ios::in

otwarcie do odczytu (tryb domyślny dla klasy ifstream)

ios::out

otwarcie do zapisu (tryb domyślny dla klasy ofstream)

ios::binary

otwarcie w trybie binarnym (domyślnie w trybie tekstowym)

ios::trunc

zapisuj na dotychczasową zawartość pliku

ios::nocreate

nie otwieraj, jeżeli plik już istnieje

ios::noreplace

nie otwieraj, jeżeli plik już istnieje, chyba, że zadano ate lub app

Poniżej przedstawiono przykładowe zastosowania podanych specyfikatorów:

ifstream archiwum;

archiwum.open („arch.doc”, ios::in & ios::nocreate);

ofstream raport;

raport.open („raport.doc”, ios::out & ios::app);

ofstream plik („test.dat”, ios::app);

Zamiast operatorów strumieniowych można zapis i odczyt do/z pliku realizować za pomocą funkcji get i put. Niepoprawne wykonanie tych funkcji sygnalizowane jest wartością NULL.



Przykład 3.1.

Program wczytujący do pliku i odczytujący z pliku tekstowego 5 wierszy tekstu wprowadzonego z klawiatury.


#include

#include

#include
void Wczytaj (char *nazwapliku)

{

char s[50];



ofstream fout (nazwapliku);

if (!fout) cout<<"Plik nie zostal otwarty"<

else

{

for (int i=1;i<=5;i++)



{

cout<<"\nPodaj tekst nr "<

cin>>s;

fout<

}

fout<<"\b";

fout.close();

}

}


void Wyswietl (char *nazwapliku)

{

char s[50];



ifstream fin(nazwapliku);

if (!fin) cout<<"Plik nie zostal otwarty"<

else

{

cout<<"\nWczytany tekst:"<

while (!fin.eof())

{

fin>>s;



cout<

}

fin.close();



}

}
int main(void)

{

char *plik1="C:\\plik1.txt";



Wczytaj(plik1);

Wyswietl(plik1);

getch();

return 0;

}

  1. STRUKTURY

Struktura to zestaw pól, z których każde może być daną lub strukturą danych dowolnego typu. Pola te oznacza się identyfikatorami.

W języku C++ definicję struktury można połączyć z zadeklarowaniem jednego lub kilku egzemlarzy tej struktury.
struct nazwa_struktury {lista_pól} lista_zmiennych;
gdzie

lista_pól – deklaracje kolejnych pól struktury będące deklaracjami zmiennych, tablic lub struktur

lista_zmiennych – zawiera oddzielone przecinkami zmienne tego typu strukturalnego
Zarówno nazwa_struktury, jak i lista_identyfikatorów mogą w deklaracji struktury nie wystąpić. Jeżeli nie występuje nazwa_struktury, to nie jest możliwe tworzenie dalszych zmiennych tego typu strukturalnego. Jeżeli nie występuje lista_zmiennych, to nie jest tworzona żadna zmienna tego typu strukturalnego – utworzenie takich zmiennych jest w dalszej części programu możliwe za pomocą deklaracji:
struct nazwa_struktury lista_zmiennych;
W języku C++ słowo kluczowe struct rozpoczynające deklarację zmiennych struktury może być opuszczone (jest ono niezbędne w języku C).
Przykłady 4.1.

Deklaracja struktury bez nazwy wraz z jedną zmienną strukturalną wzorzec:


struct

{

int szerokosc;



int dokladnosc;

char konwersja;

} wzorzec;
Przykłady 4.2.

Deklaracja struktury bez nazwy wraz z trzema zmiennymi strukturalnymi z0, z1 i z2:


struct

{

float re;



float im;

} z0, z1, z2;


Przykłady 4.3.

Deklaracja struktury osoba i deklaracja trzech zmiennych strukturalnych Ala, Ola i Ela (język C):


struct osoba

{

char *imie;



char *nazwisko;

int rok_urodzenia;

};

struct osoba Ala, Ola, Ela;


Przykłady 4.4.

Deklaracja struktury adres i deklaracja trzech zmiennych strukturalnych AAla, AOla i AEla (język C++):


struct adres

{

char miejscowosc[16];



char ulica[32];

int dom;


int mieszkanie;

};

adres AAla, AOla, AEla;


Przykłady 4.5.

Jako pole struktury można zadeklarować inną strukturę. Deklaracja takiego pola zawiera definicję struktury (bez zmiennej strukturalnej) lub deklarację zmiennej strukturalnej struktury zadeklarowanej wcześniej.


struct silnik

{

float pojemnosc;



char *paliwo;

}
struct samochod

{

struct

{

char *producent;



char *model;

} marka;

silnik naped;

}
Przykłady 4.6.

Deklarację zmiennych strukturalnych można połączyć z nadaniem wartości początkowych poszczególnym jej polom.
struct AZ

{

char z1;



char z2;

int lz;


} p1 = {’a’, ’b’, 37}, p2 = {’x’, ’y’, 35};

AZ p3 = {’k’, ’l’, 36};


Przykłady 4.7.

Dostęp do pól struktury można uzyskać, korzystając ze zmiennej lub ze wskaźnika.


struct podpis

{

char *imie;



char *inicjal;

char *nazwisko;

};

podpis st, *wsk=&st;



st.imie = „Andrzej”;

wsk->inicjal = ’K’;

Dla zmiennych strukturalnych tego samego typu dozwolone jest stosowanie operatora przypisania.
podpis AK = {„Anna”, ’M’, „Kowalska”}, NN;

NN = AK;


/*równoważne NN.imie = AK.imie;

NN.inicjal = AK.inicjal;

NN.nazwisko = AK.nazwisko; */
Przykłady 4.8.

Struktury mogą być również elementami tablic. Tablicę taką tworzy się, podając po nazwie zmiennej strukturalnej rozmiar tablicy.


struct kartoteka

{

char nazwa[16];



int liczba;

} komputery[100];

kartoteka drukarki[100];

int ile_k=0, ile_d=0;

for (int i=0; i<100; i++)

{

ile_k += komputery[i].liczba;



ile_d += drukarki[i].liczba;

}




©absta.pl 2016
wyślij wiadomość

    Strona główna