Podstawy programowania Typ znakowy. Typ znakowy

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

Podstawy Programowania

Podstawy programowania w języku C++

Podstawy programowania

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

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

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

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

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

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

Programowanie w języku C++

Podstawy programowania w języku C++

Informatyka 1. Plan dzisiejszych zajęć. zajęcia nr 11. Elektrotechnika, semestr II rok akademicki 2008/2009

Inicjacja tablicy jednowymiarowej

Stałe i zmienne znakowe. Stała znakowa: znak

Wykład II. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Programowanie komputerowe. Zajęcia 4

Tablice. int rozmiar; cout << Jaki ma być rozmiar tabeli? ; cin >> rozmiar; { int tablica[rozmiar]; /* TU JEST ŹLE */... }

1 P roste e t ypy p d a d n a ych c - c ąg ą g d a d l a szy 2 T y T py p z ł z o ł żo ż ne e d a d n a ych c : T BLICE

Operacje na łańcuchach znaków

utworz tworzącą w pamięci dynamicznej tablicę dwuwymiarową liczb rzeczywistych, a następnie zerującą jej wszystkie elementy,

Podstawy programowania w C++

Reprezentacja symboli w komputerze.

Kodowanie informacji. Przygotował: Ryszard Kijanka

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 4 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 44

Wstęp do programowania

Reprezentacja symboli w komputerze. Znaki alfabetu i łańcuchy znakowe. Programowanie Proceduralne 1

Informatyka I. Typy danych. Operacje arytmetyczne. Konwersje typów. Zmienne. Wczytywanie danych z klawiatury. dr hab. inż. Andrzej Czerepicki

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

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

DYNAMICZNE PRZYDZIELANIE PAMIECI

Wskaźniki. Informatyka

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

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 5 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 41

Zmienne, stałe i operatory

Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4. Wskaźniki. Dynamiczna alokacja pamięci. Przykłady

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

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

iii. b. Deklaracja zmiennej znakowej poprzez podanie znaku

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

Pascal typy danych. Typy pascalowe. Zmienna i typ. Podział typów danych:

ZASADY PROGRAMOWANIA KOMPUTERÓW

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:

Programowanie Strukturalne i Obiektowe Słownik podstawowych pojęć 1 z 5 Opracował Jan T. Biernat

dr inż. Jarosław Forenc

12. Wprowadzenie Sygnały techniki cyfrowej Systemy liczbowe. Matematyka: Elektronika:

Wprowadzenie do informatyki i użytkowania komputerów. Kodowanie informacji System komputerowy

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

Wstęp do programowania

Wstęp do programowania

Programowanie proceduralne INP001210WL rok akademicki 2018/19 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

Java Podstawy. Michał Bereta

Języki i metody programowania I

Pracownia Komputerowa wyk ad VII

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

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

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

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

Prawidłowa konstrukcja (3 x 4) char** tab = new char*[3]; for (size_t i = 0; i < 3; i++) tab[i] = new char[4];

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Wstęp do programowania obiektowego. WYKŁAD 3 Dziedziczenie Pola i funkcje statyczne Funkcje zaprzyjaźnione, this

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

Wymiar musi być wyrażeniem stałym typu całkowitego, tzn. takim, które może obliczyć kompilator. Przykłady:

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

Podstawy programowania w języku C i C++

Wstęp do informatyki- wykład 4 Deklaracja zmiennych Typy

C++ wprowadzanie zmiennych

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

Techniki multimedialne

Katedra Elektrotechniki Teoretycznej i Informatyki. wykład 9 - sem.iii. Dr inż. M. Czyżak

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

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

1 Podstawy c++ w pigułce.

Języki programowania. Przetwarzanie plików amorficznych Konwencja języka C. Część siódma. Autorzy Tomasz Xięski Roman Simiński

Wstęp do programowania

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Biblioteka standardowa - operacje wejścia/wyjścia

Typ użyty w deklaracji zmiennej decyduje o rodzaju informacji, a nazwa zmiennej symbolicznie opisuje wartość.

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

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

Podstawy algorytmiki i programowania - wykład 1 Tablice powtórzenie Tablice znaków Tablice dwuwymiarowe

Architektura systemów komputerowych Laboratorium 5 Kodowanie liczb i tekstów

Systemy liczenia. 333= 3*100+3*10+3*1

2 Przygotował: mgr inż. Maciej Lasota

Podstawy Programowania C++

Wstęp do programowania. Wykład 1

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

tablica: dane_liczbowe

9 Napisy. Napisy w stylu języka C

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

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami

Struktura pliku projektu Console Application

Język C, tablice i funkcje (laboratorium, EE1-DI)

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 12. Karol Tarnowski A-1 p.

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

main( ) main( void ) main( int argc, char argv[ ] ) int MAX ( int liczba_1, liczba_2, liczba_3 ) źle!

Język C++ wykład VIII

Wstęp do informatyki- wykład 11 Funkcje

Microsoft IT Academy kurs programowania

Języki i metodyka programowania. Wprowadzenie do języka C

Transkrypt:

Typ znakowy 295 Typ znakowy Typ znakowy jest zbiorem podstawowych znaków używanych do komunikacji komputera z człowiekiem. Każdy element typu znakowego (znak) posiada przyporządkowany mu kod liczbowy, na przykład litera A może mieć kod 65, litera B może mieć kod 66, Wewnętrzna reprezentacja znaków to binarny zapis liczb będących ich kodami. 296 dr inż. P. Borowiecki (KAMS, WETI, PG) 1

Standardy kodowania znaków (1) W standardowym C/C++ używany jest zbiór znaków zgodny ze standardem ISO/IEC 646. Bardziej znaną wersją tego standardu jest amerykański standard narodowy ANSI X3.4 definiujący zbiór 7. bitowych znaków tzw. podstawowy zbiór ASCII (American Standard Code for Information Interchange). <tabela> 297 Standardy kodowania znaków (2) Wykorzystanie ósmego bitu pozwoliło na stworzenie rozszerzonego zbioru ASCII zawierającego 256 znaków. W reprezentacji wewnętrznej każdy znak z tego zbioru wymaga jednego bajtu. Dla różnych grup języków istnieją różne wersje rozszerzonego zbioru ASCII tzw. strony kodowe, różniące się znakami o kodach od 128 do 255. Strona kodowa zawierająca znaki narodowe języka polskiego zdefiniowana jest przez standard ISO 8859-2. Oprócz Polski, ze standardu tego korzystają również : Albania, Bośnia, Chorwacja, Czechy, Finlandia, Węgry, Rumunia, Serbia, Słowacja i Słowenia. W systemie Windows dla Polski używana jest domyślnie strona Windows 1250. <tabela> 298 dr inż. P. Borowiecki (KAMS, WETI, PG) 2

Standardy kodowania znaków (3) EBCDIC (Extended Binary-Coded Decimal Interchange Code) to zbiór znaków 8 bitowych. Llitery i cyfry nie muszą mieć kolejnych kodów. Używany np. na komputerach typu mainframe. Unicode stworzony i rozwijany przez Unicode Consortium (http://www.unicode.org). W tym standardzie kodowania każdy znak posiada swój unikalny numer. W języku C++ dostępne są typy znakowe pozwalające na pracę ze znakami Unicode. Standard Unicode określa też reguły sortownia dla poszczególnych języków etnicznych. 299 Uporządkowanie znaków języka etnicznego Ustawienia międzynarodowe systemu operacyjnego określają między innymi zbiór dostępnych znaków oraz reguły ich sortowania, np. Kolejne znaki alfabetu etnicznego nie muszą mieć kolejnych kodów. Litera eszett występująca w języku niemieckim podczas sortowania musi być traktowana jak dwa osobne znaki. znaki ch w języku hiszpańskim podczas sortowania muszą być traktowane jak jedna litera występująca pomiędzy literą c a literą d. Zagadnienie to nie jest więc tak trywialne na jakie wygląda na pierwszy rzut oka ;) 300 dr inż. P. Borowiecki (KAMS, WETI, PG) 3

Typ znakowy Zmienne typu znakowego w C++ deklarujemy następująco char c; wchar_t c; // zwykłe znaki // znaki "szerokie" Typ wchar_t jest stosunkowo nowym typem (ANSI/ISO draft 1995). W kompilatorze g++ ver. 2.95, sizeof(wchar_t) daje 4. Zapis stałych dosłownych: a jest znakiem reprezentującym literę a 8 jest znakiem reprezentującym cyfrę 8 ( nie chodzi o liczbę 8! ) 301 Typ znakowy Znaki sterujące: \b - kasownik (ang. Backspace) \f - nowa strona (ang. Form feed) \n - nowa linia (ang. New line) \r - powrót karetki (ang. carriage Return) \t - tabulator poziomy (ang. Tabulator) \v - tabulator pionowy (ang. Vertical tabulator) \a - sygnał dźwiękowy (ang. Alarm) Znaki specjalne: \\ - ukośnik lewostronny \ - apostrof \ - cudzysłów \0 - NULL (znak o kodzie 0) \? - znak zapytania 302 dr inż. P. Borowiecki (KAMS, WETI, PG) 4

Znaki Wykonanie tego fragmentu programu Pominięcie niektórych znaków niedrukowalnych for (int i = 14; i < 256; i++) cout << setw(5) << i << setw(3) << static_cast<char>(i); daje aktualnie używany zestaw znaków, np. 14 15 16 17 18 19!! 20 21 22 23 24 25 26 27 28 29 30 31 32 33! 34 " 35 # 36 $ 37 % 38 & 39 ' 40 ( 41 ) 42 * 43 + 44, 45-46. 47 / 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63? 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w 120 x 121 y 122 z 123 124 125 126 ~ 127 128 Ç 129 ü 130 é 131 â 132 ä 133 ů 174 «175» 176 177 178 179 180 181 Á 182 Â 183 Ě 184 Ş 185 186 187 188 189 Ż 190 ż 191 192 193 194 195 196 197 198 Ă 199 ă 200 201 202 203 303 Wybrane funkcje dla znaków Wybrane funkcje biblioteki cctype operujące na znakach. int isalpha(int c); Jeżeli c jest literą, to zwraca true a w przeciwnym przypadku false. int isupper(int c); Jeżeli c jest dużą literą, to zwraca true a w przeciwnym przypadku false. int islower(int c); Jeżeli c jest małą literą, to zwraca true a w przeciwnym przypadku false. int isdigit(int c); Jeżeli c jest cyfrą, to zwraca true a w przeciwnym przypadku false. int isxdigit(int c); Jeżeli c jest cyfrą systemu o podst. 16, to zwraca true a w p. p. false. int ispunct(int c); Jeżeli c jest znakiem drukowalnym różnym od spacji, cyfry lub litery, to zwraca true a w przeciwnym przypadku false. int isprint(int c); Jeżeli c jest znakiem drukowalnym włączając w to spację i c < 128, to zwraca true a w przeciwnym przypadku false. int iscntrl(int c); Jeżeli c jest znakiem kontrolnym, to zwraca true a w p. p. zwraca false. 304 dr inż. P. Borowiecki (KAMS, WETI, PG) 5

Wybrane funkcje dla znaków Wybrane funkcje biblioteki cctype operujące na znakach c.d. int isspace(int c); Jeżeli c jest białym znakiem, to zwraca true a w przeciwnym przypadku false. int toupper(int c); Jeżeli c jest małą literą, to zwraca literę dużą w przeciwnym przypadku zwraca argument bez zmian. int tolower(int c); Jeżeli c jest dużą literą, to zwraca literę małą w przeciwnym przypadku zwraca argument bez zmian. Przykład for (int i = 0; i < 128; i++) if (isprint(i)) cout << setw(5) << i << setw(3) << static_cast<char>(i); else cout << setw(5) << i << setw(3) << ' '; 305 Wybrane funkcje dla znaków Wybrane funkcje biblioteki cctype operujące na znakach. Nul + znaki steruj. Znaki iscntrl isspace isupper islower isalpha \t, \f, \v, \n, \r X X X isdigit/ isxdigit ispunct Spacja X X! #$%& ()*+,-./ X X 0123456789 X / X X : ; < = > @? X X ABCDEF X X - / X X GHIJKLMNOPQRSTUVW XYZ isprint X X X [ ] ^ _ ` \ X X abcdef X X - / X X ghijklmnopqrstuvw xyz X X X ~ X X Dla znaków ASCII o kodach do 127 306 dr inż. P. Borowiecki (KAMS, WETI, PG) 6

Tablice znaków Tablice znaków służą do przechowywania ciągów znaków z 1,1 z 1,2 z 1,3 z 1,k1 Ciągi te nazywane są również łańcuchami znakowymi lub napisami (ang. string). Ciągi znaków, zwykle za sprawą wyróżnionych znaków formatujących mogą mieć różne interpretacje. Na przykład ciąg znaków zawierający znaczniki końca linii często nazywany jest tekstem z 1,1 z 1,2 z 1,k1 #z 2,1 z 2,2 z 2,k2 #z r,1 z r,2 z r,kr # gdzie # jest znakiem końca linii (w C/C++ jest to '\n'). 307 Tablice znaków Specjalny ciąg znaków, zakończony znakiem NULL o kodzie ASCII równym 0 nazywamy C-napisem (ang. C-string, ASCII-Z string). D o m '\0' 0 1 2 3 4 n-2 n-1 Nazwa C-string ma wskazywać na pochodzenie takiej reprezentacji z języka C i odróżniać od obiektów klasy string dostępnych w C++. Klasa string jest odpowiedzią na problemy związane ze złożoną obsługą operacji na C-napisach i stanowi obecnie część biblioteki standardowej C++. Ponieważ jednak w wielu programach można spotkać zaczniemy właśnie od nich. 308 dr inż. P. Borowiecki (KAMS, WETI, PG) 7

Tablice znaków Stałe dosłowne reprezentujące napisy są literałami składającymi się z ciągu znaków ujętych w cudzysłów "Dom na polu" Stałe takie traktowane są jak. Tablicę znaków deklarujemy następująco char nazwa[rozmiar]; Podczas definicji tablicę znaków można inicjalizować, np: char zdanie[80] = "Dom na polu"; Za ostatnią literą w tablicy dodany zostanie znak '\0'. Dzieje się tak dlatego, że znaki ujęte w cudzysłów są C-napisem. Tak utworzona tablica może być traktowana jak C-napis. 309 Tablice znaków Inicjalizacja zbiorcza pojedynczymi znakami char zdanie[80]='d','o','m',' ','n','a',' ','p','o','l','u'; Można jej używać gdy mamy na myśli tablicę pewnych znaków, która nie będzie używana jako napis. Unikać przy inicjalizacji napisów! Można liczyć, że zgodnie z zasadą inicjalizacji zbiorczej nieokreślone jawnie elementy tablicy zostaną uzupełnione zerami, jednak gdy cała tablica jest wypełniona, uzupełnienie nie będzie możliwe. char zdanie[11]='d','o','m',' ','n','a',' ','p','o','l','u'; Podobne zjawisko wystąpi, gdy pozostawimy wyznaczenie rozmiaru tablicy kompilatorowi tablica 11. elementowa char zdanie1[]='d','o','m',' ','n','a',' ','p','o','l','u'; char zdanie2[] = "Dom na polu"; tablica 12. elementowa, '\0' na końcu 310 dr inż. P. Borowiecki (KAMS, WETI, PG) 8

Wprowadzanie C-napisu ze standardowego wejścia. #include <iostream> const int MAX_N = 80; char s[max_n]; Podaj napis: ^^^^^Dobra^robota Podales napis: Dobra_ cout << "Podaj napis: "; cin >> s; cout << "Podales napis: " << s; znakiem ^ zaznaczono spację Znaki wyjmowane są z cin operatorem >> aż do napotkania pierwszego białego znaku, tzn. spacji, tabulatora albo znaku końca linii. Przed rozpoczęciem wyjmowania białe znaki poprzedzające w cin pierwszy znak, który nie jest biały, tzw. wiodące białe znaki są pomijane. Biały znak kończący wyjmowanie nie wchodzi do napisu i pozostaje w strumieniu wraz z ewentualnymi innymi znakami. 311 #include <iostream> Biały znak kończący wyjmowanie nie wchodzi do napisu i pozostaje w strumieniu wraz z ewentualnymi innymi znakami. const int MAX_N = 80; char s[max_n]; Podaj napis: ^^^^^Dobra^robota Podales napis: Dobra Ciag dalszy: robota_ cout << "Podaj napis: "; cin >> s; cout << "Podales napis: " << s << endl; cin >> s; cout << "Ciag dalszy: " << s; Czy w powyższym przykładzie po wyjęciu ^robota strumień jest pusty? Nie. Pozostaje w nim biały znak '\n' co może mieć wpływ na dalsze operacje, szczególnie gdy będą wykonane bez pomijania wiodących białych znaków. 312 dr inż. P. Borowiecki (KAMS, WETI, PG) 9

Jeżeli napis nie zawierający białych znaków jest dłuższy niż rozmiar tablicy, to można uznać to za błąd logiczny. Cała zawarość strumienia, aż do białego znaku kończącego wyjmowanie zostanie umieszczona w kolejnych komórkach pamięci co może nadpisać wartości zmiennych znajdujących się bezpośrenio za wczytywaną zmienną s. #include <iostream> const int MAX_N = 5; char s[max_n]; Podaj napis: ^^^^^Dobranocka Podales napis: Dobranocka_ cout << "Podaj napis: "; cin >> s; cout << "Podales napis: " << s ; Pozornie wszystko działa jak zaplanowano D o b r a n o c k a '\0' s??? 313 Wprowadzanie ze standardowego wejścia C-napisu zawierającego białe znaki, np. spacje ale również znaki końca linii. #include <iostream> const int MAX_N = 80; char s[max_n]; char ogr; ogr = '\n'; cout << "Podaj tekst: "; cin.getline(s,max_n,ogr); cout << endl; cout << "Podales tekst: " << s; Podaj tekst: Dobra robota ale jeszcze popracuj. Podales tekst: Dobra robota ale jeszcze popracuj. Funkcja getline wyjmuje ze strumienia co najwyżej MAX_N-1 znaków (również białych) i umieszcza je w s dodając za ostatnim znakiem '\0'. Napotkanie znaku ogranicznika ogr, natychmiast przerywa wyjmowanie. Znak ogr jest wyjmowany ze strumienia ale nie jest dodawany do s. 314 dr inż. P. Borowiecki (KAMS, WETI, PG) 10

Jeżeli po zakończeniu wyjmowania przez cin.getline są jeszcze w strumieniu inne znaki, to gdy wyjmowanie przerwano z powodu napotkania ogranicznika, znaki po ograniczniku nie zostaną wyjęte (pozostaną do dalszego przetwarzania) char s[10] = "123456789"; cout << "Wpisz max 9 znakow: "; cin.getline(s,10,'x') cout << "Podales znaki:" << endl; for (int i=0; i < 10; i++) cout << "s[" << i << "]= " << s[i] << endl; // tu można przetwarzać "bet" Domyślnie ogranicznikiem jest '\n'. Wpisz max 9 znakow: Alfaxbet Podales znaki: s[0]= A s[1]= l s[2]= f s[3]= a s[4]= s[5]= 6 s[6]= 7 s[7]= 8 s[8]= 9 s[9]= _ Gdy korzystamy z '\n' można użyć cin.getline z dwoma parametrami. '\0' 315 Jeżeli po zakończeniu wyjmowania przez cin.getline są w strumieniu inne znaki, to: gdy wyjmowanie przerwano z powodu napotkania ogr, znaki po ogr nie zostaną wyjęte (pozostaną do dalszego przetwarzania), gdy wyjmowanie przerwano po wyjęciu MAX_N-1 znaków i pozostały w strumieniu znaki różne od ogranicznika, to wystąpi błąd i będzie on sygnalizowany przez ustawienie flagi failbit (obsługę tego typu sytuacji omówimy w późniejszej części wykładu). Podczas operacji na C-napisach obowiązek kontrolowania zakresów poszczególnych tablic znakowych spoczywa na programiście!! 316 dr inż. P. Borowiecki (KAMS, WETI, PG) 11

#include <iostream> Problemy podczas równoczesnego używania cin >> oraz cin.getline char s1[80]; char s2[80]; Podaj pierwszy napis: ^^Dobranoc Podaj drugi napis: Podales napisy: Dobranoc _ cout << "Podaj pierwszy napis: "; cin >> s1; cout << "Podaj drugi napis: "; cin.getline(s2,80); cout << "Podales napisy: " << endl; << s1 << " " << s2; Po wyjęciu oc strumień nie jest pusty. Pozostał w nim biały znak '\n'. Ponieważ cin.getline nie pomija wiodących białych znaków a znak '\n' jest domyślnym ogranicznikiem, więc nie są wyjmowane żadne znaki i s2 jest pusty. 317 Problemy podczas równoczesnego używania cin >> oraz cin.getline char s1[80]; char s2[80]; Podaj pierwszy napis: ^^Dobrej^nocy Podaj drugi napis: Podales napisy: Dobrej nocy_ cout << "Podaj pierwszy napis: "; cin >> s1; cout << "Podaj drugi napis: "; cin.getline(s2,80); cout << "Podales napisy: " << endl; << s1 << " " << s2; Podobnie po wyjęciu ^^Dobrej przez operator >> strumień nie jest pusty. Pozostała w nim spacja i napis nocy oraz znak '\n'. Ponieważ cin.getline nie pomija wiodących białych znaków a znak '\n' jest domyślnym ogranicznikiem, więc do s2 wyjmowane są znaki: spacja i nocy, natomiast '\n' jest pomijany. 318 dr inż. P. Borowiecki (KAMS, WETI, PG) 12

Wybrane funkcje biblioteki string operujące na C-napisach. char *strcpy(char *s_cel, const char *s_zrodlo); Kopiuje zawartość napisu s_zrodlo do s_cel. Zwraca s_cel. Programista musi zadbać aby s_zrodlo zmieściło się w s_cel. Do przypisywania jednego napisu do drugiego, nie wolno używać operatora = char *strcat(char *s1, const char *s2); Rozszerza s1 dołączając s2 na końcu s1 (konkatenacja - złączenie). Zwraca s1. Pierwszy znak s2 nadpisuje '\0' na końcu s1. Napis s2 pozostaje bez zmian. Programista musi zagwarantować, że s1 pomieści połączone napisy s1 i s2. int strcmp(const char *s1, const char *s2); Porównuje napisy s1 i s2 i zwraca 0 gdy są jednakowe. Jeżeli s1 jest leksykograficznie mniejszy od s2 zwraca liczbę ujemną oraz liczbę dodatnią, gdy s1 jest leksykograficznie większy od s2. size_t strlen(const char *s); Zwraca długość napisu s. Znak '\0' kończący napis nie jest wliczany. Typ size_t nie jest specyficzny dla C++. Występuje w innych językach. Zalecany przez POSIX jako nazwa typu dla wartości unsigned int albo unsigned long, gdy wynik funkcji jest odpowiedzią na pytania: ile?, jak wiele? 319 Wybrane funkcje biblioteki string operujące na C-napisach c.d. char *strstr(const char *s_gdzie, const char *s_co); Szuka pierwszego wystąpienia napisu s_co w napisie s_gdzie. Jeżeli napis s_co został znaleziony, to zwracany jest wskaźnik do jego pierwszego znaku w napisie s_gdzie. W przeciwnym przypadku zwracany jest wskaźnik o wartości NULL. char *strtok(char *ptr, const char *s); Dzieli na "tokeny" napis podany jako pierwszy parametr. Aby dokonać podziału wymaga wielokrotnego wywoływania (patrz przykład w dalszej części). Wybrane funkcje biblioteki stdlib operujące na C-napisach. double atof(const char *s); Zamienia napis s na liczbę typu double. double atoi(const char *s); Zamienia napis s na liczbę typu int. double atol(const char *s); Zamienia napis s na liczbę typu long.... 320 dr inż. P. Borowiecki (KAMS, WETI, PG) 13

#include <cstring> char s1[80], s2[80]; strcpy(s1, "C#"); strcpy(s2, "C++"); cout << "Dlugosci: " << strlen(s1) << " " << strlen(s2) << endl; cout << s1 << " i " << s2 << " to"; if(!strcmp(s1, s2)) cout << " takie same napisy." << endl; else cout << " rozne napisy." << endl; strcat(s1, s2); cout << "Zlaczenie: " << s1 << endl; Dlugosci: 2 3 C# i C++ to rozne napisy. Zlaczenie: C#C++ C#C++ oraz C#C++ to teraz takie same napisy. _ strcpy(s2, s1); cout << s1 << " oraz " << s2; if(!strcmp(s1, s2)) cout << " to teraz takie same napisy."; else cout << " wciaz sie roznia."; cout << endl; 321 Do poszczególnych znaków napisu można odwołać się jak do elementu tablicy podając indeks. Zamieniając litery napisu na duże, skorzystamy również z faktu, że C-napis zakończony jest znakiem o kodzie 0. #include <cstring> #include <cctype> // zamiana liter małych na wielkie char s[80]; Alternatywnie: s[i] == '\0' albo for (i = 0; s[i] = toupper(s[i]); i++); strcpy(s," NapiS Probny 234 &\"-._>"); for (int i=0; s[i]; i++) s[i] = toupper(s[i]); cout << s << endl; NAPIS PROBNY 234 &"-._> _ 322 dr inż. P. Borowiecki (KAMS, WETI, PG) 14

Podobnie można wykonać kopiowanie C-napisu #include <cstring> char cel[80], zrodlo[80]; int i=0; Wyrażenie to ma wartość ostatnio skopiowanego znaku. Alternatywa: ((cel[i] = zrodlo[i]) == '\0') strcpy(zrodlo,"napis probny"); while (cel[i] = zrodlo[i]) i++; cout << cel << endl; Co by się stało, gdyby rozmiar cel był mniejszy niż rozmiar zrodlo? Zapobieganie: stosować funkcje strncpy, strncat, strncmp, które posiadają dodatkowy trzeci parametr typu size_t pozwalający na określenie maksymalnej liczby przetwarzanych znaków. 323 Podział napisu na tokeny. #include <cstring> char zdanie[] = "To zdanie ma 5 tokenow"; cout << zdanie << endl; Separator(y) tokenów char* wsk_tokena; wsk_tokena = strtok( zdanie, " " ); while (wsk_tokena!= NULL) cout << wsk_tokena << endl; wsk_tokena = strtok( NULL, " " ); To zdanie ma 5 tokenow To zdanie ma 5 tokenow _ Pierwsze wywołanie przekazuje do strtok dzielony napis i zbiór separatorów. W wyniku dostajemy wskaźnik na pierwszy token a pierwsze wystąpienie separatora zamieniane jest na '\0' stanowiący zakończenie aktualnego tokena. Funkcja "zapamiętuje" wskaźnik do pierwszego znaku po aktualnym tokenie. NULL jako pierwszy par. kolejnych wywołań nakazuje kontynuację od znaku wskazywanego przez zapamiętany wskaźnik. Uwaga: dzielony napis ulega zmianie. Aby zachować oryginał, przed użyciem strtok należy zrobić kopię. 324 dr inż. P. Borowiecki (KAMS, WETI, PG) 15

Przykład Zastosowanie wskaźników do C-napisów #include <cstring> // Odwócenie napisu w miejscu char s[] = "napis probny"; char *start, *end; int n; char buf; cout << "Przed odwroceniem: " << s << endl; n = strlen(s); start = s; '\0' ma zostać w tym end = &s[n-1]; samym miejscu while (start < end) buf = *start; *start = *end; *end = buf; start++; end--; cout << "Po odwroceniu: " << s << endl; 325 Tablica C-napisów #include <cstring> Tablica wskaźników na stałe napisy char* stacje[] = "Stocznia", "Politechnika", "Wrzeszcz", "Przymorze", "Oliwa", "Sopot" ; const int Rozmiar = sizeof(stacje)/sizeof(char*); // Rozmiar zostanie obliczony podczas kompilacji char* wsk[rozmiar]; // Tablica wskaźników na napisy. for (int i = 0; i < Rozmiar; i++) cout << "Stacja " << i+1 << ". " << stacje[i] << endl; wsk[0] = stacje[0]; wsk[1] = stacje[1]; wsk[2] = stacje[2]; cout << wsk[0] << wsk[1] << wsk[2] << endl; Stacja 1. Stocznia Stacja 2. Politechnika Stacja 3. Wrzeszcz Stacja 4. Przymorze Stacja 5. Oliwa Stacja 6. Sopot StoczniaPolitechnikaWrzeszcz _ Źródło: Język C++ w praktyce, T. Ratajczak + autor 326 dr inż. P. Borowiecki (KAMS, WETI, PG) 16

Tablica C-napisów // zapisanie do tablicy wsk wskaźników na tworzone dynamicznie bloki // pamięci o rozmiarach odpowiednich do zapamiętania napisów // o wartościach takich jak napisy w tablicy stacje for(int i = 0; i < Rozmiar; i++) wsk[i] = new char [strlen(stacje[i])+1]; strcpy(wsk[i],stacje[i]); wsk[0] wsk[1] wsk[rozmiar-1] Stocznia\0 Politechnika\0 Sopot\0 for (int i = 0; i < Rozmiar; i++) cout << "Stacja " << i+1 << ". " << wsk[i] << endl; cout << wsk[1][0]; // wypisze pierwszy znak drugiego napisu czyli 'P' // Uwaga: pamiętaj o zakresach indeksów! 327 dr inż. P. Borowiecki (KAMS, WETI, PG) 17