Łańcuchy znakowe string

Podobne dokumenty
dr inż. Jarosław Forenc

#include <iostream> #include <string> using namespace std; auto main() -> int { string s1; // pusty string. Klasa std::string

Podstawy Programowania

Operatory na rzecz typu TString

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Program dopisujący gwiazdkę na końcu pliku tekstowego o nazwie podanej przez uŝytkownika oraz wypisujący zawartość tego pliku.

Część 4 życie programu

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 5. Karol Tarnowski A-1 p.

Podstawy programowania. Wykład: 9. Łańcuchy znaków. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

STL: Lekcja 1&2. Filozofia STL

Podstawy programowania. Wykład: 9. Łańcuchy znaków. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

public: // interfejs private: // implementacja // składowe klasy protected: // póki nie będziemy dziedziczyć, // to pole nas nie interesuje

1 Wskaźniki. 1.1 Główne zastosowania wskaźników

Programowanie w językach

Zaawansowane programowanie w języku C++ Biblioteka standardowa

Programowanie C++ Wykład 2 - podstawy języka C++ dr inż. Jakub Możaryn. Warszawa, Instytut Automatyki i Robotyki

PROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec

lekcja 8a Gry komputerowe MasterMind

Programowanie w C++ Wykład 9. Katarzyna Grzelak. 14 maja K.Grzelak (Wykład 9) Programowanie w C++ 1 / 30

DANE TEKSTOWE W JĘZYKU C/C++ - TABLICE ZNAKOWE

1 Podstawy c++ w pigułce.

Programowanie Obiektowo Zorientowane w języku c++ Przestrzenie nazw

Techniki programowania INP001002Wl rok akademicki 2017/18 semestr letni. Wykład 5. Karol Tarnowski A-1 p.

Programowanie i struktury danych

Podstawy programowania skrót z wykładów:

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 15 kwietnia K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33

Języki programowania obiektowego Nieobiektowe elementy języka C++

Programowanie w C++ Wykład 1. Katarzyna Grzelak. 26 luty K.Grzelak (Wykład 1) Programowanie w C++ 1 / 28

Stałe, znaki, łańcuchy znaków, wejście i wyjście sformatowane

Podstawy Informatyki. Inżynieria Ciepła, I rok. Wykład 10 Kurs C++

Pliki wykład 2. Dorota Pylak

Programowanie - wykład 4

Tablice. Monika Wrzosek (IM UG) Podstawy Programowania 96 / 119

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

Język C++ wykład VIII

1 Pierwsze kroki w C++ cz.3 2 Obsługa plików

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk. Wydział Inżynierii Metali i Informatyki Przemysłowej

Wstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy. Laboratorium 2. Karol Tarnowski A-1 p.

Laboratorium 3: Tablice, tablice znaków i funkcje operujące na ciągach znaków. dr inż. Arkadiusz Chrobot dr inż. Grzegorz Łukawski

Pliki. Informacje ogólne. Obsługa plików w języku C

Wstęp do programowania. Wykład 1

Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1. Kraków 2013

Materiał Typy zmiennych Instrukcje warunkowe Pętle Tablice statyczne Wskaźniki Tablice dynamiczne Referencje Funkcje

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 26 marca kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 40

Wstęp do programowania obiektowego. Przekazywanie parametrów do funkcji w C++ Metody i funkcje operatorowe Strumienie: standardowe, plikowe, napisowe

Programowanie komputerowe. Zajęcia 1

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami:

Projektowanie klas c.d. Projektowanie klas przykład

Języki programowania. Przetwarzanie tablic znaków. Część druga. Autorzy Tomasz Xięski Roman Simiński

Ok. Rozbijmy to na czynniki pierwsze, pomijając fragmenty, które już znamy:

Klasa std::string. Bogdan Kreczmer. ZPCiR IIAiR PWr pokój 307 budynek C3.

Podstawy programowania w języku C++

Zajęcia nr 2 Programowanie strukturalne. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

Paostwowa Wyższa Szkoła Zawodowa w Płocku Dariusz Wardowski

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

Podstawy programowania

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 5

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Zajęcia nr 1 Podstawy programowania. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 16 kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 27

Laboratorium 6: Ciągi znaków. mgr inż. Leszek Ciopiński dr inż. Arkadiusz Chrobot dr inż. Grzegorz Łukawski

Aby uzyskać zaliczenie w pierwszym terminie (do 30 stycznia 2018) rozliczyć trzeba co najmniej 8 projektów, po 4 z każdej z części: C++ oraz Python.

VII. Ciągi znaków łańcuchy

Programowanie w C++ Wykład 1. Katarzyna Grzelak. 25 luty K.Grzelak (Wykład 1) Programowanie w C++ 1 / 38

1 Podstawy c++ w pigułce.

Ćwiczenie 4. Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1.

8. Wektory. Przykłady Napisz program, który pobierze od użytkownika 10 liczb, a następnie wypisze je w kolejności odwrotnej niż podana.

I - Microsoft Visual Studio C++

Wstęp do Programowania 2

Operacje wejścia/wyjścia odsłona pierwsza

BIBLIOTEKA STANDARDOWA C++

7. Pętle for. Przykłady

Podstawy Programowania Podstawowa składnia języka C++

Podstawy Programowania

Podstawy informatyki. Elektrotechnika I rok. Język C++ Operacje na danych - wskaźniki Instrukcja do ćwiczenia

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

Programowanie w języku C++

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Podstawy algorytmiki i programowania - wykład 4 C-struktury

1. Wypisywanie danych

Wstęp do informatyki- wykład 3 Pierwszy program w C++ Wyprowadzanie danych Deklaracja zmiennych

ŁAŃCUCHY W JĘZYKU C/C++

Programowanie obiektowe i C++ dla matematyków

Pytania sprawdzające wiedzę z programowania C++

Pliki. Informacje ogólne. Obsługa plików w języku C

Pętle i tablice. Spotkanie 3. Pętle: for, while, do while. Tablice. Przykłady

Programowanie w C++ Wykład 11. Katarzyna Grzelak. 21 maja K.Grzelak (Wykład 11) Programowanie w C++ 1 / 24

Ćwiczenie nr 6. Poprawne deklaracje takich zmiennych tekstowych mogą wyglądać tak:

Dla każdej operacji łącznie tworzenia danych i zapisu ich do pliku przeprowadzić pomiar czasu wykonania polecenia. Wyniki przedstawić w tabelce.

Wskaźniki. nie są konieczne, ale dają językowi siłę i elastyczność są języki w których nie używa się wskaźników typ wskaźnikowy typ pochodny:

Pliki wykład 2 -przekazywanie strumieni do funkcji -funkcje get(char &) i getline(string)

Inicjacja tablicy jednowymiarowej

Opus Magnum C++11 : programowanie w języku C++. T. 2 / Jerzy Grębosz. Gliwice, cop Spis treści

Programowanie i struktury danych

Struktury. Przykład W8_1

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

Podstawy języka C++ Maciej Trzebiński. Praktyki studenckie na LHC IFJ PAN. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. M. Trzebiński C++ 1/16

Podstawy programowania w C++

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

Transkrypt:

Łańcuchy znakowe Prawie w każdym języku programowania na początku należy opanować sposób wyświetlania informacji na ekranie (standardowe urządzenie wyjścia), wprowadzania ich z klawiatury (standardowe urządzenie wejścia), a co za tym idzie, opanować operacje na łańcuchach znakowych. Łańcuch znakowy to ciąg znaków ujęty w zwykły cudzysłów, np. "to jest łańcuch znakowy". Nawet pojedyncza literka, np. "a" to też łańcuch znakowy, w odróżnieniu od znaku (zmiennej typu char), który należy zapisać w pojedynczym cudzysłowie, np. 'a'. Łańcuch znakowy może być przedstawiony w postaci literału napisowego: const char* ptr = "to jest test"; Warto zwrócić uwagę, że każdy literał jest stałą, zatem wskaźnik pokazujący na niego musi być wskaźnikiem stałym (takim, który gwarantuje, że za jego pomocą ten literał napisowy nie będzie modyfikowany). Okazuje się, że kompilatory (gcc) w wersjach przed 4.2.x nie zwracały uwagi na (niepoprawną) składnię w postaci: char* ptr = "to jest test"; po czym w kolejnych wyższych wersjach, pojawia się słuszne ostrzeżenie: deprecated conversion from string constant to `char*`. Napisano wiele kodu z taką składnią i teraz, kompilując nowym kompilatorem, zasypywani jesteśmy ostrzeżeniami. Jest to dobry przykład na to, że kompilatory nie zawsze skrupulatnie przestrzegały (albo informowały) o tym, co od dawna zapisane jest w standardzie języka. Prymitywny łańcuch znakowy (nazwijmy go C-string) nie jest żadnym nowym typem, nie jest też żadnym obiektem. Aby na nim pracować, trzeba przechowywać go w tablicy znakowej, dbając ciągle, aby była wystarczająco duża (i nie zapominając, że musi być większa o zerowy bajt, kończący łańcuch). Operacje na łańcuchach w języku C realizowane były za pomocą zestawu funkcji o nazwach strxxx, operujących na argumentach char * destination, const char * source. Było to wyjątkowo niewygodne i "niskopoziomowe" programowanie. W języku C++ ich deklaracje znajdują się w pliku nagłówkowym <cstring>. W bibliotece języka C++ pojawia się kompleksowe rozwiązanie operacji na łańcuchach znakowych, jest nim typ abstrakcyjny o nazwie std::string (należy włączyć plik nagłówkowy <string>). Tak naprawdę, string to synonim szablonu klasy specjalizowanego na typie char, a konkretnie: typedef basic_string<char> string; Nas nie będą interesować takie szczegóły, tylko pragmatyczne korzyści, jakie można odnieść z działań na obiektach typu string. Klasa string jest przeładowana mnóstwem użytecznych funkcji. Jest ich aż za dużo, wiele udostępnionej funkcjonalności zrealizować można zewnętrznymi funkcjami z algorytmów uogólnionych i w tym sensie klasa string jest krytykowana jako niepotrzebnie, nadmiernie rozdęta. Wystarczy spojrzeć na bogaty spis funkcji i operatorów, wiele z funkcji występuje w kilku (przeładowanych) wersjach. W żadnym wypadku nie będziemy omawiać tutaj wszystkich po kolei, bo po to jest dokumentacja oraz podręczniki (np. Symfonia C++ Standard J. Grębosza, cały rozdział 11 - prawie 100 stron na ten temat). Poniższe krótkie przykłady pozwolą raczej rozeznać się w możliwościach klasy bibliotecznej std::string. Ponieważ bardzo często będziemy coś wypisywać na ekran, zdefiniujmy sobie definicję preprocesora, która skróci i ułatwi wielokrotne, nudne pisanie tego samego kodu.

#define P(str, val) cout << str " = " << val << endl Wszędzie tam, gdzie preprocesor napotka w kodzie P( X, Y ) wykona ślepą zamianę na cout << X " = " << Y << endl gdzie X, Y jakieś argumenty typu takiego, który można posłać do obiektu cout, czyli na ekran komputera. Celowo tej definicji nie zakończyliśmy średnikiem, tak aby w samym kodzie zapis wyglądał tak: P(X, Y); Przyjrzyjmy się kilku sposobom na tworzenie obiektów klasy string. Przede wszystkim zauważymy, że interesuje nas pojemność łańcucha znakowego. Wewnątrz obiektu string jest bufor, odpowiednio się dla nas powiększający. #include <iostream> #include <string> using namespace std; int main () { const char *linijka = "ta linijka to stary lancuch znakowy"; // najpierw pusty obiekt string s1; // poniżej przypisanie, nie inicjalizacja s1 = "abrakadabra"; P("s1", s1); // inicjalizacja istniejącym obiektem // tu działa konstruktor kopiujący string s2 (s1); P("s2", s2); // inicjalizacja C stringiem string s3 (linijka); P("s3", s3); // pierwszy argument C string // drugi długo ść łańcucha jakim chcemy inicjalizować string s4 (linijka,10); P("s4", s4); // pierwszy obiekt s3 (typu string) // drugi pozycja początkowa // trzeci liczba argumentów string s5 (s3,6,4); P("s5", s5); // pierwszy liczba powtórze ń znaków // drugi znak (w pojedynczym cudzysłowie!) string s6 (15,'*'); P("s6", s6); // pierwszy iterator początku // drugi iterator końca odj ąć 5 pozycji string s7 (s3.begin(),s3.end() 5);

P("s7", s7); /*********************** wszystkie poniższe przykłady piszmy po prostu jako kolejne linie tego kodu ************************/ return 0; Wypełnianie stringów ze strumienia standardowego lub plikowego W poniższym przykładzie następuje czytanie z klawiatury, aż do wprowadzenia (oddzielonego białymi znakami lub znakiem enter) literki q. Zauważmy, że wprowadzając kilka słów przedzielonych spacją (i zatwierdzonych enterem) zobaczymy kilkukrotny obieg w pętli, bo formatowane czytanie kończy się właśnie na białym znaku (spacji) lub znaku końca linii. string s8; while (cin >> s8 && s8!= 'q') { cout << endl; P("wpisane z klawiatury: ", s8); Jeśli chcemy wczytać coś z pliku, przygotujmy sobie wcześniej jakiś plik ASCII z kilkunastoma linijkami, np. nazwiemy go test.txt. Teraz będziemy korzystać z obiektu obsługującego strumień plikowy, więc potrzebne będzie włączenie pliku nagłówkowego (piszemy go u góry, np. pod zapisanymi już wcześniej) // nazwa pochodzi od file stream #include <fstream> string s9; // w tym będziemy akumulowa ć kolejne czytane linie // tworzymy obiekt klasy input file stream czyli do czytania strumienia plikowego // jako argument podana nazwa pliku ifstream plik( "test.txt" ); // sprawdzamy czy si ę otworzył if (!plik ) cerr << "nie ma pliku \n"; while (!plik.eof() ) { getline( plik, s8 ); s9 += s8 + '\n'; P("wczytany plik: ", s9); W powyższym przykładzie występuje obiekt standardowego strumienia błędu, cerr, który na ekran wyprowadza zadaną informację. Różnicę w działaniu pomiędzy cout i cerr można zauważyć, jeśli skierujemy strumień wyjścia zamiast na ekran, do pliku. Jeśli nasz program ma nazwę prog, to robimy to tak:./prog > mojplik.txt (albo jeśli dopisywać do pliku to:./prog >> mojplik.txt) Wszystkie komunikaty z cout zamiast na ekran trafią do pliku. Natomiast komunikaty z cerr nadal zostaną wyświetlone na ekranie, co znacznie ułatwia zorientowanie się, że coś przebiegło niepoprawnie. Jeśli chcemy przekierować również strumień błędu do pliku, to napiszmy:./prog > mojplik.txt 2>&1 Więcej o przekierowaniach w unixie można poczytać np. na Wikipedii.

Operacje na stringach Typ string jest wyposażony w całą masę przydatnych metod oraz przeciążonych operatorów. Np. operacje dodawania do siebie dwóch łańcuchów znakowych zapisujemy po prostu znaczkiem + a operację dopisania czegoś, operatorem += Nie pozbawiono nas jednak metody składowej assign i append. Np. gdybym chciał dołożyć na koniec stringu trzy wykrzykniki, to mogę tak: s9.append( 3, '!' ); a jeśli przypisać 20 znaczków * to mogę tak: s9.assign( 20, '*' ); Są też metody insert, replace, copy i swap. Pozostawiam ich poznanie samodzielnej pracy. Poszukiwanie zawartości string jest przykładem sekwencyjnego kontenera, zawierającego literki. Możemy buszować po nim jak po zwykłej tablicy (czyli za pomocą operatora []), możemy odnieść się do konkretnej pozycji za pomocą metody at (proszę sprawdzić różnicę). Możemy odczytać wielkość stringu (metody size, length) oraz wielkości wewnętrznego buforu (capacity), możemy też zarezerwować bufor (reserve) danej wielkości, a od C++11 również skurczyć (shrink_to_fit). Warto zwrócić uwagę na metodę: max_size() oraz składową statyczną string::npos Proszę sprawdzić co otrzymamy gdy wypiszemy ich wartości w naszym systemie? Ja otrzymuję 4294967295 dla npos oraz 1073741820 dla max_size(), przy czym sizeof(string) wynosi 4. Widzą Państwo związek? Wreszcie, mamy cały zestaw metod szukających (find, rfind, find_first_of, find_first_not_of, find_last_of, find_last_not_of)... Filozofia ich używania jest taka, że zwracają znalezioną pozycję albo gdy takiej nie ma wartość npos. std::string s = "test"; if(s.find('a') == std::string::npos) std::cout << "no 'a' in 'test'\n"; Bieganie iteratorem Komunikacja kontenerów ze światem zewnętrznym często odbywa się za pomocą sprytnych, inteligentnych obiektów wskaźnikopodobych zwanych iteratorami. String jest kontenerem, ma więc też swoje iteratory, a w szczególności metody je zwracające: begin() i end() (oraz kilka wariacji na ich temat, w postaci stałej cbegin() i cend() i takiż sam zestaw do biegania wspak, zaczynający te metody od literki r). Konwencja jest zawsze taka: begin() - pokazuje na adres pierwszego elementu stringu, end() - na adres pierwszy za ostatnim elementem stringu (tak zwany za-ostatni ). I odwrotnie: rbegin() - pokazuje na ostatni element, zaś rend() - na adres poprzedzający pierwszy element (tak zwany przed-pierwszy ). Oto prosty przykład (zakładamy, że mamy już jakiś string s przygotowany): // iterator, jako wskaźnik trzeba wyłuskać * żeby dostać zawartość, na którą pokazuje string::iterator it = s.begin(); // proszę zwrócić uwagę na konwencję, sprawdzamy!= a nie < while ( it!= s.end() ) { cout << *it << ;

Można oczywiście tak samo w pętli for, tworząc iterator zupełnie lokalnie. Zwykle takie długie pisanie typu, jak string::iterator, jest zniechęcające. W nowym standardzie języka możemy wykorzystać dedukcję typu w oparciu o inicjalizację i zapis jest o wiele przyjemniejszy, np. for ( auto it = s.rbegin(); it!= s.rend(); ++it ) {.i tak dalej. Proszę poćwiczyć różne warianty biegania za pomocą iteratorów! Ciekawostki do poczytania Na pewno zauważyli Państwo, że niektóre metody zwracające czy to wielkość, czy pozycję, mają napisane typ size_type. A czasem napotkać można też size_t. Proszę sobie poczytać o tym, co oznaczają. http://stackoverflow.com/questions/918567/size-t-vs-containersize-type