Bardzo szybkie podsumowanie: wykład 5
Transkrypt
Bardzo szybkie podsumowanie: wykład 5
Bardzo szybkie podsumowanie: wykªad 5 wer. 7 z drobnymi mody kacjami! Wojciech Myszka 2016-05-25 11:55:55 +0200 Uwagi 1. Obowi¡zuje caªy materiaª! 2. Tu tylko podsumowanie. Formatowane (tekstowe) wej±cie/wyj±cie. Binarne wej±cie/wyj±cie. wer. 7 z drobnymi mody kacjami! Wojciech Myszka 2016-05-14 16:58:41 +0200 Cz¦±¢ I Formatowane (tekstowe) wej±cie/wyj±cie Otwarcie pliku I 1. Przed skorzystaniem z pliku nale»y go otworzy¢ (open). 2. stdin, stdout, stderr otwarte s¡ w trybie tekstowym. 3. Standardowa biblioteka (stdio.h) zawiera trzy funkcje fopen, freopen i fclose. 4. Pierwsze dwie sªu»¡ do skojarzenia (powi¡zania) pliku z odpowiedni¡ struktur¡ danych. 5. Ostatnia powi¡zanie to likwiduje. 6. Wszystkie czynno±ci zwi¡zane z otwieraniem i zamykaniem plików realizowane s¡ przez System Operacyjny. Otwarcie pliku II Operacj¦ otwarcia pliku (ponownego otwarcia) realizuj¡ funkcje fopen i freopen: # include < s t d i o . h> F I L E ∗ fopen ( const char ∗ filename , const char ∗ mode ) ; F I L E ∗ freopen ( const char ∗ filename , const char ∗ mode, F I L E ∗ stream ) ; Otwarcie pliku III U»ycie: F I L E ∗ fp ; ... fp = fopen ( " p l i k . t x t " , "w" ) ; ... fp = freopen ( " p l i k . t x t " , " r " , fp ) ; I Pierwszy parametr ( lename) to wska¹nik do tablicy tekstowej (na przykªad staªej) zawieraj¡cej naw¦ pliku. Otwarcie pliku IV I Parametr drugi to ci¡g znaków (lub zmienna) zawieraj¡ca w sposób symboliczny okre±lenie trybu dost¦pu: I I I I I r otwórz plik tekstowy do odczytu (plik musi istnie¢) w otwórz plik tekstowy do zapisu (niszcz¡c jego zawarto±¢ je»eli ju» istnieje) a (append); otwórz plik tekstowy do dopisywania, je»eli plik nie istnieje zostanie utworzony. r+ otwarcie pliku tekstowego do zapisu i odczytu (plik powinien ju» istnie¢!) w+ otwórz istniej¡cy plik (kasuj¡c jego zawarto±¢) lub utwórz nowy plik tekstowy w trybie do zapisu i odczytu Otwarcie pliku V I a+ otwórz plik tekstowy na ko«cu w trybie do zapisu i odczytu Otwarcie pliku VI Przykªad # include < s t d i o . h> ... F I L E ∗pp ; ... pp = fopen ( " Ala . t x t " , " r " ) ; i f ( pp == NULL ) { /∗ B ª ¡d ! ∗/ } ... f s c a n f ( pp , " %d " , & i ) ; Otwarcie pliku VII I Trzeci parametr (stream tylko w przypadku funkcji reopen) zawiera wska¹nik do struktury danych opisuj¡cych strumie« danych. 1. Funkcja fopen() otwiera plik o podanej nazwie we wskazanym trybie, tworzy struktur¦ danych opisuj¡c¡ go i zwraca do niej adres. W przypadku bª¦du zwraca NULL. 2. Funkcja freopen() najpierw zamyka otwarty wcze±niej plik i otwiera go ponownie we wskazanym trybie, zwracaj¡c wska¹nik do struktury danych opisuj¡cych strumie«. W przypadku bª¦du zwraca NULL. Otwarcie pliku VIII 3. Funkcja fclose() zamyka wskazany plik. W przypadku bª¦du zwraca NULL. # include < s t d i o . h> ... i n t f c l o s e ( F I L E ∗ stream ) ; stream to wska¹nik do struktury danych opisuj¡cych strumie« danych. Przykªad: ... f c l o s e ( fp ) ; ... Odczyt formatowany I 1. Funkcje typu scanf # include < s t d i o . h> i n t f s c a n f ( F I L E ∗ stream , const char ∗ format , . . . ) ; i n t s c a n f ( const char ∗ format , . . . ) ; i n t s s c a n f ( const char ∗ s , const char ∗ format , . . . ) ; Odczyt formatowany II Dane czytane s¡ ze wskazanego strumienia (stream) i interpretowane zgodnie z u»ytym formatem. W formacie powinna wyst¡pi¢ wystarczaj¡ca liczba specy kacji aby dostarczy¢ dane dla wszystkich argumentów. I I I fscanf zwraca liczb¦ przeczytanych warto±ci lub warto±¢ EOF scanf jest odpowiednikiem fscanf, ale dotyczy strumienia stdin sscanf jest odpowiednikiem fscanf, z tym, »e dane czytane s¡ z tablicy znakowej; dotarcie do ko«ca tabeli jest równowa»ne z dotarciem do ko«ca pliku Wej±cie: Specy kacja formatu I Na specy kacj¦ formatu skªadaj¡ si¦: I odst¦py; Wyst¡pienie w formacie biaªego znaku (white space) powoduje, »e funkcje z rodziny scanf b¦d¡ odczytywa¢ i odrzuca¢ znaki, a» do napotkania pierwszego znaku nie b¦d¡cego biaªym znakiem. I znaki (ró»ne od % i odst¦pów). Je»eli taki znak wyst¡pi w specy kacji musi si¦ pojawi¢ w strumieniu wej±ciowym na odpowiednim miejscu! I specy kacje konwersji (rozpoczynaj¡ce si¦ znakiem %) Po znaku % wyst¡pi¢ mo»e: Wej±cie: Specy kacja formatu II nieobowi¡zkowy znak ∗ (oznaczaj¡cy, »e zinterpretowana warto±¢ ma by¢ zignorowana) I nieobowi¡zkowa specy kacja dªugo±ci pola (okre±la maksymaln¡ liczb¦ znaków pola) I jeden z nieobowi¡zkowych znaków h, l (maªa litera el ) lub L mówi¡cych jak ma by¢ interpretowana czytana wielko±¢ (h short, l long albo double w przypadku oat, ll long long, L long double), I znak okre±laj¡cy typ konwersji. Po znaku procent (%) wyst¡pi¢ mo»e jeden ze znaków d liczba caªkowita, I Wej±cie: Specy kacja formatu III i liczba caªkowita (mo»na wprowadza¢ warto±ci szesnastkowe je»eli poprzedzone znakami 0x lub ósemkowe je»eli poprzedzone 0; 031 czytane z formatem %d to 31 a z formatem %i to 25), o liczba caªkowita kodowana ósemkowo, u liczba caªkowita bez znaku (unsigned int), x liczba caªkowita kodowana szesnastkowo, a, e, f, g liczba typu oat; mo»na równie» wczyta¢ w ten sposób niesko«czono±¢ lub warto±¢ Not a Number (NaN), Wej±cie: Specy kacja formatu IV s ci¡g znaków (na ko«cu zostanie dodany znak zero), c znak (lub ci¡g znaków gdy wyspecy kowano szeroko±¢ pola), nie jest dodawane zero na ko«cu, [ odczytuje niepusty ci¡g znaków, z których ka»dy musi nale»e¢ do okre±lonego zbioru, argument powinien by¢ wska¹nikiem na char, n do zmiennej odpowiadaj¡cej tej specy kacji konwersji wpisana zostanie liczba znaków przetworzonych przez fscanf, Wej±cie: Specy kacja formatu V p w zale»no±ci od implementacji sªu»y do wprowadzania warto±¢ wska¹ników, % znak %. Wej±cie: Specy kacja formatu VI Format [ Po otwieraj¡cym nawiasie nast¦puje ci¡g okre±laj¡cy znaki jakie mog¡ wyst¦powa¢ w odczytanym napisie i ko«czy si¦ on nawiasem zamykaj¡cym tj. ]. Znaki pomi¦dzy nawiasami (tzw. scanlist) okre±laj¡ mo»liwe znaki, chyba »e pierwszym znakiem jest ^ wówczas w odczytanym ci¡gu znaków mog¡ wyst¦powa¢ znaki nie wyst¦puj¡ce w scanlist. Je»eli sekwencja zaczyna si¦ od [] lub [^] to ten pierwszy nawias zamykaj¡cy nie jest traktowany jako koniec sekwencji tylko jak zwykªy znak. Je»eli wewn¡trz sekwencji wyst¦puje znak − (minus), który nie jest pierwszym lub drugim je»eli pierwszym jest ^ ani ostatnim znakiem zachowanie jest zale»ne od implementacji. Wej±cie: Specy kacja formatu VII Przykªad # include < s t d i o . h> i n t main ( void ) { int x , y , n; x = s c a n f ( " %∗d %d %n " , &y , &n ) ; p r i n t f ( " y= %d , n= %d \ n " , y , n ) ; p r i n t f ( " x= %d \ n " , x ) ; return 0 ; } Wej±cie: Specy kacja formatu VIII Dane i wyniki 10 20 30 40 y= 20, n= 6 x= 1 1␣␣␣␣␣2222␣ala␣ma␣kota y=␣2222,␣n=␣11 x=␣1 Wej±cie: Specy kacja formatu IX Kolejny przykªad # include < s t d i o . h> i n t main ( void ) { int x , y , z , n; x = s c a n f ( " %4d %5d %n " , &y , &z , &n ) ; p r i n t f ( " y= %d , z = %d , n= %d \ n " , y , z , n ) ; p r i n t f ( " x= %d \ n " , x ) ; return 0 ; } Wej±cie: Specy kacja formatu X Dane i wyniki 1234567890 y= 1234, z= 56789, n= 9 x= 2 Wej±cie: Specy kacja formatu XI I jeszcze jeden przykªad # include < s t d i o . h> i n t main ( void ) { int x , y , z , n; x = s c a n f ( " %4d a %5d %n " , &y , &z , &n ) ; p r i n t f ( " y= %d , z = %d , n= %d \ n " , y , z , n ) ; p r i n t f ( " x= %d \ n " , x ) ; return 0 ; } Wej±cie: Specy kacja formatu XII Dane i wyniki 123b123b y=␣123,␣z=␣32767,␣n=␣2023244192 x=␣1 1a2␣3␣4␣5␣6␣7␣8␣9 y=␣1,␣z=␣2,␣n=␣4 x=␣2 Wej±cie: Specy kacja formatu XIII ... # include < s t d i o . h> i n t main ( void ) { int x , y , z , n; x = s c a n f ( " %4da%5d%n " , &y , &z , &n ) ; p r i n t f ( " y= %d , z = %d , n= %d \ n " , y , z , n ) ; p r i n t f ( " x= %d \ n " , x ) ; return 0 ; } Wej±cie: Specy kacja formatu XIV 123a123 y= 123, z= 123, n= 7 x= 2 Podchwytliwe pytania I P: Jak powinna wygl¡da¢ specy kacja wprowadzania pozwalaj¡ca poprawnie zinterpretowa¢ dane w postaci: 123ala456 O: Oczywi±cie tak: %iala%i lub lepiej %dala%d P: A jak powinna wygl¡da¢ specy kacja pozwalaj¡ca przeczyta¢ dane postaci 123ala456 oraz 123ola456 Odpowied¹ b¦dzie dªu»sza. . . Podchwytliwe pytania II Popatrzmy na program # include < s t d i o . h> i n t main ( void ) { int x , y , z , n; char t e k s t [ 1 0 0 ] ; x = s c a n f ( " %d%3[ a−z ]%d%n " , &y , t e k s t , &z , &n ) ; p r i n t f ( " y= %d " , y ) ; p r i n t f ( " t e k s t = %s " , t e k s t ) ; p r i n t f ( " z = %d " , z ) ; p r i n t f ( " n= %d \ n " , n ) ; p r i n t f ( " x= %d \ n " , x ) ; return 0 ; } Podchwytliwe pytania III 123ala20 y= 123 tekst= ala z= 20 n= 8 x= 3 12ooo3456 y= 12 tekst= ooo z= 3456 n= 9 x= 3 123ALA34 y= 123 tekst= x= 1 z= 1250361488 n= 0 Podchwytliwe pytania IV Je»eli specy kacj¦ zmienimy na: "%d%∗3[a−z]%d%n" to dane tekstowe b¦d¡ ignorowane, odpowiednie polecenie b¦dzie wygl¡da¢ tak: x = s c a n f ( " %d %∗3[ a−z ]% d%n " , &y , &z , &n ) ; Podchwytliwe pytania V Co jeszcze mo»e pojawi¢ si¦ wewn¡trz nawiasów kwadratowych? I ci¡g znaków dotyczy wymienionych znaków: [abc] I znak ^ na pierwszym miejscu wszystkie znaki za wyj¡tkiem wymienionych: [^ABC] I pocz¡tek−koniec znaki z podanego zakresu: [a−z] Warto te» poczyta¢ o wyra»eniach regularnych czasami nazywanych reguªowymi . . . Podchwytliwe pytania VI P: W jaki sposób przeczyta¢ dowolny napis? I Jak wiadomo specy kacja %s czyta znaki do pierwszego odst¦pu. Zatem nie mo»na w ten sposób przeczyta¢ napisau Ala ma kota (ze wzgl¦du na odst¦py. I Mo»na wspomóc si¦ wyra»eniami regularnymi: specy kacja %[aA]s czyta¢ b¦dzie dane tekstowe zgodne z wzorcem. Czyli tylko litery a lub A. I U»ycie specy kacji %[^ ]s powoduje przeczytanie dowolnych znaków a» do znaku odst¦pu (w istocie znaczy to samo co poprzednio: wzorcem jest dowolny znak ró»ny od spacji!). Podchwytliwe pytania VII I Co spowoduje zatem specy kacja %[^\n]s? Rodzina polece« fprintf I Wszystkie funkcje realizuj¡ formatowane wyprowadzanie informacji. # include < s t d a r g . h> # include < s t d i o . h> i n t f p r i n t f ( F I L E ∗ stream , const char ∗ format , \ ...); i n t p r i n t f ( const char ∗ format , . . . ) ; i n t s p r i n t f ( char ∗ s , const char ∗ format , . . . ) ; i n t v f p r i n t f ( F I L E ∗ stream , const char ∗ format , \ v a _ l i s t arg ) ; i n t v p r i n t f ( const char ∗ format , v a _ l i s t arg ) ; i n t v s p r i n t f ( char ∗ s , const char ∗ format , \ v a _ l i s t arg ) ; Rodzina polece« fprintf II I I I I fprintf to podstawowa wersja funkcji printf u»ywa stdout jako strumienia wyj±ciowego. sprintf przekazuje sformatowane informacje do tablicy znakowej (odpowiedniej dªugo±ci) warianty o nazwie rozpoczynaj¡cej si¦ na v (vfprintf, fprintf, vsprintf) u»ywaj¡ specy cznej metody przekazywania listy parametrów zmiennej dªugo±ci nie b¦dziemy si¦ nimi zajmowa¢. Wyj±cie: Specy kacje formatu I Podobnie jak w przypadku formatowanego wprowadzania danych, zmienna lub staªa tekstowa zawiera informacje o sposobie wyprowadzania danych. Zasad¡ jest, »e znak % rozpoczyna specy kacj¦ konwersji, a pozostaªe znaki s¡ wyprowadzane w postaci takiej jak w formacie. Specjalne wska¹niki mody kuj¡ce sposób konwersji to: wynik b¦dzie justowany do lewej strony (standardowo do prawej) + Liczby b¦d¡ zapisywane zawsze ze znakiem odst¦p odst¦p b¦dzie zawsze dodawany przed liczb¡ (chyba, »e liczba poprzedzona jest znakiem) Wyj±cie: Specy kacje formatu II # Wynik jest konwertowany do postaci alternatywnej (zale»nej od typu konwersji) I dla formatu o powoduje to zwi¦kszenie precyzji, je»eli jest to konieczne, aby na pocz¡tku wyniku byªo zero; I dla formatów x i X niezerowa liczba poprzedzona jest ci¡giem 0x lub 0X; I dla formatów a, A, e, E, f, F, g i G wynik zawsze zawiera kropk¦ nawet je»eli nie ma za ni¡ »adnych cyfr; I dla formatów g i G ko«cowe zera nie s¡ usuwane. Wyj±cie: Specy kacje formatu III 0 Liczby b¦d¡ poprzedzone wiod¡cymi zerami (dla formatów d, i, o, u, x, X, a, A, e, E, f, F, g i G) Szeroko±¢ pola i precyzja I Minimalna szeroko±¢ pola oznacza ile najmniej znaków ma zaj¡¢ dane pole. Je»eli warto±¢ po formatowaniu zajmuje mniej miejsca jest ona wyrównywana spacjami z lewej strony (chyba, »e podano agi, które mody kuj¡ to zachowanie). Domy±lna warto±¢ tego pola to 0. Precyzja dla formatów: I d, i, o, u, x i X okre±la minimaln¡ liczb¦ cyfr, które maj¡ by¢ wy±wietlone i ma domy±ln¡ warto±¢ 1; I a, A, e, E, f i F liczb¦ cyfr, które maj¡ by¢ wy±wietlone po kropce i ma domy±ln¡ warto±¢ 6; I g i G okre±la liczb¦ cyfr znacz¡cych i ma domy±ln¡ warto±¢ 1; Szeroko±¢ pola i precyzja II dla formatu s maksymaln¡ liczb¦ znaków, które maj¡ by¢ wypisane. Szeroko±¢ pola mo»e by¢ albo dodatni¡ liczb¡ zaczynaj¡c¡ si¦ od cyfry ró»nej od zera albo gwiazdk¡. Podobnie precyzja z t¡ ró»nic¡, »e jest jeszcze poprzedzona kropk¡. Gwiazdka oznacza, »e brany jest kolejny z argumentów, który musi by¢ typu int. Warto±¢ ujemna przy okre±leniu szeroko±ci jest traktowana tak jakby podano ag¦ − (minus). I Rozmiar argumentu I 1. Dla formatów d i i mo»na u»y¢ jednego ze mody kator rozmiaru: I I I I I hh oznacza, »e format odnosi si¦ do argumentu typu signed char, h oznacza, »e format odnosi si¦ do argumentu typu short, l (el) oznacza, »e format odnosi si¦ do argumentu typu long, ll (el el) oznacza, »e format odnosi si¦ do argumentu typu long long, j oznacza, »e format odnosi si¦ do argumentu typu intmax_t, Rozmiar argumentu II I I z oznacza, »e »e format odnosi si¦ do argumentu typu b¦d¡cego odpowiednikiem typu size_t ze znakiem, t oznacza, »e »e format odnosi si¦ do argumentu typu ptrdiff_t. 2. Dla formatów o, u, x i X mo»na u»y¢ takich samych mody katorów rozmiaru jak dla formatu d i oznaczaj¡ one, »e format odnosi si¦ do argumentu odpowiedniego typu bez znaku. Rozmiar argumentu III 3. Dla formatu n mo»na u»y¢ takich samych mody katorów rozmiaru jak dla formatu d i oznaczaj¡ one, »e format odnosi si¦ do argumentu b¦d¡cego wska¹nikiem na dany typ. 4. Dla formatów a, A, e, E, f, F, g i G mo»na u»y¢ mody katorów rozmiaru L, który oznacza, »e format odnosi si¦ do argumentu typu long double. 5. Dodatkowo, mody kator l (el) dla formatu c oznacza, »e odnosi si¦ on do argumentu typu wint_t, a dla formatu s, »e odnosi si¦ on do argumenty typu wska¹nik na wchar_t. Format I Funkcje z rodziny printf obsªuguj¡ nast¦puj¡ce formaty: d, i argument typu int jest przedstawiany jako liczba caªkowita ze znakiem w postaci [−]ddd. o, u, x, X argument typu unsigned int jest przedstawiany jako nieujemna liczba caªkowita zapisana w systemie oktalnym (o), dziesi¦tnym (u) lub heksadecymalnym (x i X). f, F argument typu double jest przedstawiany w postaci [−]ddd.ddd. Format II e, E argument typu double jest reprezentowany w postaci [−]d.ddde+dd, gdzie liczba przed kropk¡ dziesi¦tn¡ jest ró»na od zera, je»eli liczba jest ró»na od zera, a + oznacza znak wykªadnika. Format E u»ywa wielkiej litery E zamiast maªej. g, G argument typu double jest reprezentowany w formacie takim jak f lub e (odpowiednio F lub E) zale»nie od liczby znacz¡cych cyfr w liczbie oraz okre±lonej precyzji. Format III a, A argument typu double przedstawiany jest w formacie [−]0xh.hhhp+d czyli analogicznie jak dla e i E, tyle »e liczba zapisana jest w systemie heksadecymalnym. c argument typu int jest konwertowany do unsigned char i wynikowy znak jest wypisywany. Je»eli podano mody kator rozmiaru l argument typu wint_t konwertowany jest do wielobajtowej sekwencji i wypisywany. Format IV s argument powinien by¢ typu wska¹nik na char (lub wchar_t). Wszystkie znaki z podanej tablicy, a» do i z wyª¡czeniem znaku null s¡ wypisywane. p argument powinien by¢ typu wska¹nik na void. Jest to konwertowany na seri¦ drukowalnych znaków w sposób zale»ny od implementacji. n argument powinien by¢ wska¹nikiem na liczb¦ caªkowit¡ ze znakiem, do którego zapisana jest liczba zapisanych znaków. Cz¦±¢ II Binarne wej±cie/wyj±cie Otwarcie pliku I # include < s t d i o . h> F I L E ∗ fopen ( const char ∗ filename , const char ∗mode ) ; F I L E ∗ freopen ( const char ∗ filename , const char ∗mode, F I L E ∗ stream ) ; ... F I L E ∗ fp ; I Pierwszy parametr ( lename) to wska¹nik do tablicy tekstowej (na przykªad staªej) zawieraj¡cej naw¦ pliku. Otwarcie pliku II I Parametr drugi to ci¡g znaków (lub zmienna) zawieraj¡ca w sposób symboliczny okre±lenie trybu dost¦pu: I I I I I rb otwórz plik binarny do czytania wb utwórz plik do zapisu w trybie binarnym, je»eli plik istnieje, jego zawarto±¢ zostanie skasowana ab otwórz plik binarny w trybie do dopisywania (je»eli plik nie istnieje zostanie utworzony). r+b lub rb+ zapis i odczyt dla plików binarnych (plik musi istnie¢) w+b lub wb+ otwórz w trybie binarnym plik istniej¡cy (kasuj¡c jego zawarto±¢) lub utwórz plik nowy w trybie do zapisu i odczytu Otwarcie pliku III I I a+b lub ab+ otwórz plik w trybie binarnym na ko«cu w trybie do zapisu i odczytu Trzeci parametr (stream tylko w przypadku funkcji reopen) zawiera wska¹nik do struktury danych opisuj¡cych strumie« danych. Zapis/Odczyt binarny I 1. fread() # include < s t d i o . h> s i z e _ t f r e a d ( void ∗ ptr , s i z e _ t s i z e , s i z e _ t nmemb, F I L E ∗ stream ) ; Funkcja realizuj¡ca dost¦p bezpo±redni do pliku, pozwala odczyta¢ nmemb elementów o wielko±ci size ka»dy do tablicy wskazywanej przez ptr ze strumienia stream. Funkcja zwraca liczb¦ przeczytanych elementów, która mo»e by¢ mniejsza od nmemb gdy wyst¡pi bª¡d lub funkcja dojdzie do ko«ca pliku. Zapis/Odczyt binarny II 2. fwrite() # include < s t d i o . h> s i z e _ t f w r i t e ( const void ∗ ptr , s i z e _ t s i z e , s i z e _ t nmemb, F I L E ∗ stream ) ; Funkcja zapisuje binarnie elementy tablicy wskazanej przez ptr do strumienia stream. size okre±la wielko±¢ jednego obiektu, a nmemb liczb¦ obiektów. Zapis tablicy I # include < s t d i o . h> i n t main ( ) { F I L E ∗pp ; double t [ 1 0 ] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; pp = fopen ( " Ala . t x t " , " wb " ) ; i f ( pp == NULL ) { p r i n t f ( " Blad ! \ n " ) ; return 1 ; Zapis tablicy II } f w r i t e ( t , s i z e o f ( double ) , 10 , pp ) ; f c l o s e ( pp ) ; return 0 ; } Pliki binarne I Prosty przykªad /∗ ∗ Odczyt jednej l i c z b y w t r y b i e binarnym ∗/ # include < s t d i o . h> i n t main ( void ) { F I L E ∗ fp ; unsigned i n t e ; fp = fopen ( " foo . t x t " , " rb " ) ; i f ( fp == NULL ) { p r i n t f ( " blad1 \ n " ) ; Pliki binarne II Prosty przykªad return 1 ; } i f ( f r e a d (&e , s i z e o f ( e ) , 1 , fp ) == 0 ) { p r i n t f ( " blad2 \ n " ) ; return 1 ; } p r i n t f ( " e = %u \ n " , e ) ; return 0 ; } Pliki binarne III Prosty przykªad 1. Plik foo.txt nie istnieje $ ls b.c Debug $ Debug/binarne blad1 Pliki binarne IV Prosty przykªad 2. Plik foo.txt istnieje, ale jest pusty $ touch foo.txt $ ls -l razem 8 -rw-r--r-- 1 myszka myszka 319 2008-05-05 12:05 b.c drwxr-xr-x 2 myszka myszka 4096 2008-05-05 12:05 Debug -rw-r--r-- 1 myszka myszka 0 2008-05-05 12:12 foo.txt $ Debug/binarne blad2 Pliki binarne V Prosty przykªad 3. Plik istnieje, ma dªugo±¢ trzech bajtów: $ ls -l razem 12 -rw-r--r-- 1 myszka myszka 319 2008-05-05 12:05 b.c drwxr-xr-x 2 myszka myszka 4096 2008-05-05 12:05 Debug -rw-r--r-- 1 myszka myszka 3 2008-05-05 12:15 foo.txt $ Debug/binarne blad2 Pliki binarne VI Prosty przykªad 4. Plik istnieje, ma dªugo±¢ czterech bajtów: $ cat foo.txt abc $ ls -l razem 12 -rw-r--r-- 1 myszka myszka 319 2008-05-05 12:05 b.c drwxr-xr-x 2 myszka myszka 4096 2008-05-05 12:05 Debug -rw-r--r-- 1 myszka myszka 4 2008-05-05 12:18 foo.txt $ Debug/binarne e = 174285409 Zapis i odczyt I # include < s t d i o . h> i n t main ( void ) { F I L E ∗ fp ; unsigned i n t i , k ; fp = fopen ( " foo . t x t " , " wb " ) ; i f ( fp == NULL ) { p r i n t f ( " blad1 \ n " ) ; return 1 ; } f o r ( i = 0 ; i < 10; i ++ ) Zapis i odczyt II { f s e e k ( fp , i ∗ s i z e o f ( i ) , SEEK_SET ) ; f w r i t e (& i , s i z e o f ( i ) , 1 , fp ) ; } f c l o s e ( fp ) ; fp = fopen ( " foo . t x t " , " rb " ) ; i f ( fp == NULL ) { p r i n t f ( " blad1 \ n " ) ; return 1 ; } f o r ( i = 0 ; i < 10; i ++ ) Zapis i odczyt III { f s e e k ( fp , ( 9 − i ) ∗ s i z e o f ( i ) , SEEK_SET ) ; f r e a d (&k , s i z e o f ( i ) , 1 , fp ) ; p r i n t f ( " k= %d \ n " , k ) ; } f c l o s e ( fp ) ; return 0 ; } Zapis i odczyt (wariant drugi) I # include < s t d i o . h> i n t main ( void ) { F I L E ∗ fp ; unsigned i n t i , k ; fp = fopen ( " foo . t x t " , "w+b " ) ; i f ( fp == NULL ) { p r i n t f ( " blad1 \ n " ) ; return 1 ; } f o r ( i = 0 ; i < 10; i ++ ) Zapis i odczyt (wariant drugi) II { f s e e k ( fp , i ∗ s i z e o f ( i ) , SEEK_SET ) ; f w r i t e (& i , s i z e o f ( i ) , 1 , fp ) ; } f o r ( i = 0 ; i < 10; { f s e e k ( fp , ( 9 − i SEEK_SET ) ; f r e a d (&k , s i z e o f ( p r i n t f ( " k= %d \ n " , } f c l o s e ( fp ) ; i ++ ) ) ∗ sizeof ( i ) , i ) , 1 , fp ) ; k) ; Zapis i odczyt (wariant drugi) III return 0 ; } Operacje na ªa«cuchach znaków wer. 6 z drobnymi mody kacjami! Wojciech Myszka 2016-05-08 16:12:27 +0200 Ša«cuch znaków 1. Z ªa«cuchów znaków korzystamy powszechnie. 2. Najprostszy przykªad: p r i n t f ( " Ala ma kota " ) ; 3. Ša«cuchem znaków (ang: string) jest kazdy napis zawarty w cudzysªowach. 4. Ša«cuch znaków jest tablic¡ typu char, w której na ostatniej pozycji znajduje si¦ znak null (znak o kodzie zero). char ∗ t e k s t = " J a k i s tam t e k s t " ; p r i n t f ( " %c \ n " , " p r z y k l a d " [ 0 ] ) ; /∗ wypisze p − z n a k i w n a p i s a c h sa numerowane od zera ∗/ p r i n t f ( " %c \ n " , t e k s t [ 2 ] ) ; /∗ wypisze k ∗/ Ša«cuch znaków cd I 1. J¦zyk C nie robi jakich± wielkich rozróznie« mi¦dzy znakami a cyframi: # include < s t d i o . h> i n t main ( void ) { char t e s t [ ] = " t e s t " ; int i ; p r i n t f ( "%ld \n " , sizeof ( test ) ) ; f o r ( i = 0 ; i < s i z e o f ( t e s t ) ; i ++) p r i n t f ( " %d \ n " , t e s t [ i ] ) ; return 0 ; } 2. Efekt dziaªania tego programu Ša«cuch znaków cd II 5 116 101 115 116 0 Deklaracje Ponizsze deklaracje s¡ (w zasadzie równowazne) char ∗ t e k s t = " J a k i s tam t e k s t " ; /∗ Umieszcza n a p i s w obszarze danych programu i p r z y p i s u j e adres ∗/ char t e k s t [ ] = " J a k i s tam t e k s t " ; /∗ Umieszcza n a p i s w t a b l i c y ∗/ char t e k s t [ ] = { ' J ' , ' a ' , ' k ' , ' i ' , ' s ' , \ ' ' , ' t ' , ' a ' , 'm' , ' ' , ' t ' , ' e ' , ' k ' , \ ' s ' , ' t ' , ' \0 ' } ; /∗ Tekst to taka t a b l i c a j a k kazda inna ∗/ Jednak w pierwszym przypadku tekst jest odsyªaczem do staªej! Elementów tablicy nie mozna zmienia¢! Operacje na ªa«cuchach Plik nagªówkowy string.h zawiera de nicje staªych i funkcji zwi¡zanych z operacjami na ªa«cuchach tekstów. void void int void void void char char int int char size_t char ∗memccpy ( void ∗, const void ∗, i n t , \ size_t ); ∗memchr ( const void ∗, i n t , s i z e _ t ) ; memcmp( const void ∗, const void ∗ ,\ size_t ); ∗memcpy( void ∗, const void ∗ ,\ size_t ); ∗memmove( void ∗, const void ∗ ,\ size_t ); ∗memset ( void ∗, i n t , s i z e _ t ) ; ∗ s t r c a t ( char ∗, const char ∗ ) ; ∗ s t r c h r ( const char ∗, i n t ) ; strcmp ( const char ∗, const char ∗ ) ; s t r c o l l ( const char ∗, const char ∗ ) ; ∗ s t r c p y ( char ∗, const char ∗ ) ; s t r c s p n ( const char ∗, const char ∗ ) ; ∗s t r d u p ( const char ∗ ) ; char size_t char int char char char size_t char char char size_t ∗strerror ( int ); s t r l e n ( const char ∗ ) ; ∗ s t r n c a t ( char ∗, const char ∗ ,\ size_t ); strncmp ( const char ∗, const char ∗ ,\ size_t ); ∗s t r n c p y ( char ∗, const char ∗ ,\ size_t ); ∗ s t r p b r k ( const char ∗, const char ∗ ) ; ∗ s t r r c h r ( const char ∗, i n t ) ; s t r s p n ( const char ∗, const char ∗ ) ; ∗ s t r s t r ( const char ∗, const char ∗ ) ; ∗ s t r t o k ( char ∗, const char ∗ ) ; ∗ s t r t o k _ r ( char ∗, const char ∗ ,\ char ∗∗); s t r x f r m ( char ∗, const char ∗ ,\ size_t ); Porównywanie ci¡gów znaków 1. Porównywanie pojedynczych znaków kodów ASCII na podstawie ich 2. Dla ci¡gów znaków "aaa" > "aa" > "a" > ""; "ab" > "aa"; "a" > "A" 3. Funkcja strcmp sªuzy do porównywania dwu ci¡gów znaków; ma dwa parametry i zwraca −1 gdy pierwszy ci¡g znaków jest mniejszy od drugiego, 0 gdy s¡ równe i +1, gdy pierwszy ci¡g jest wi¦kszy od drugiego. 4. Funkcja strncmp (o trzech parametrach, trzeci parametr wskazuje ile znaków ma by¢ porównanych) moze by¢ uzyta, gdy nie chcemy porównywa¢ caªych ci¡gów znaków. Kopiowanie znaków 1. Do kopiowania sªuzy funkcja strcpy o dwu parametrach; ci¡g znakach zawarty w drugim parametrze kopiowany jest do pierwszego parametru. Do obowi¡zku programisty nalezy zapewnienie aby tablica b¦d¡ca pierwszym parametrem miaªa wystarczaj¡c¡ ilo±¢ miejsca na pomieszczenie caªego zapisu! 2. Drugi wariant funkcji strncpy; dodatkowy, trzeci parametr mówi ile znaków ma by¢ skopiowanych (ale zawsze trzeba pami¦ta¢ o miejscu na znak null znajduj¡cym si¦ na ko«cu napisu). Znaki z drugiego parametry kopiowane s¡ do ko«ca ªa«cucha, chyba ze tekst jest dªuzszy niz liczba znaków do skopiowania; w tym przypadku programista musi doda¢ znak NULL r¦cznie na ko«cu skopiowanego tekstu. Š¡czenie napisów I 1. Do ª¡czenia napisów sªuzy funkcja strcat (nazwa pochodzi od STRing conCATenate). 2. Podobnie jak w poprzednich przypadkach jest równiez drugi wariant strncat 3. W wersji standardowej Zawarto±¢ drugiego parametru funkcji dopisywana jest na ko«cu zawarto±ci pierwszego. char t e k s t [ 8 0 ] = " " ; s t r c a t ( tekst , " ala " ) ; s t r c a t ( t e k s t , " ma " ) ; s t r c a t ( t e k s t , " kota " ) ; puts ( t e k s t ) ; Š¡czenie napisów II 4. Pierwszy parametr funkcji musi mie¢ dostateczn¡ ilo±¢ miejsca na pomieszczenie poª¡czonych ci¡gów znaków! 5. W drugim wariancie wyst¦puje trzeci parametr mówi¡cy ile znaków ma by¢ doª¡czonych. Dªugo±¢ ci¡gu znaków 1. Funkcja strlen podaje dªugo±¢ ci¡gu znaków (bez znaku NULL) Wyszukiwanie 1. Funkcja strchr (gdzie pierwszym parametrem jest ci¡g znaków a drugim pojedynczy znak) zwraca numer znaku zgodnego z poszukiwanym. 2. Funkcja strrchr poszukuje od prawej do lewej. 3. Funkcja strstr (o dwu parametrach) wyszukuje pierwszego wyst¡pienia ci¡gu znaków b¦d¡cego drugim parametrem w pierwszym. 4. Funkcja strtok moze sªuzy¢ do podziaªu pierwszego parametru na ci¡g zetonów; zakªadamy, ze zetony (tokeny) oddzielone s¡ zadanym znakiem (drugi parametr). Konwersje 1. atol, strtol long 2. atoi zamienia ªa«cuch na liczb¦ caªkowit¡ typu zamienia ªa«cuch na liczb¦ caªkowit¡ typu int 3. atoll, strtoll zamienia ªa«cuch na liczb¦ caªkowit¡ typu long long (64 bity); dodatkowo istnieje przestarzaªa funkcja atoq b¦d¡ca rozszerzeniem GNU, 4. atof, strtod przeksztaªca ªa«cuch na liczb¦ typu double Funkcje ato* nie wykrywaj¡ bª¦dów konwersji Funkcje zde niowane s¡ w pliku stdlib.h Rózne informacje Plik nagªówkowy ctype.h zawiera de nicje funkcji (i róznych staªych) zwi¡zanych z rozpoznawaniem typów informacji int int int int int int int int int isalnum ( i n t ) ; isalpha ( int ); i s a s c i i ( int ); isblank ( int ); i s c n t r l ( int ); i s d i g i t ( int ); isgraph ( int ); islower ( int ); is pr int ( int ); int int int int int int int int int ispunct ( int ); isspace ( int ); isupper ( int ) ; i s x d i g i t ( int ); toascii ( int ); tolower ( i n t ) ; toupper ( i n t ) ; _toupper ( i n t ) ; _tolower ( i n t ) ; Konwersje I i n t a t o i ( const char ∗ s t r i n g ) ; long a t o l ( const char ∗ s ) ; double a t o f ( const char ∗ s t r i n g ) ; Parametrem funkcji jest ci¡g znaków zawieraj¡cy napis, który ma by¢ skonwertowany Konwersje II Funkcje z rodziny strto* long i n t s t r t o l ( const char ∗ s t r , char ∗∗ endptr , i n t base ) ; unsigned long i n t s t r t o u l ( const char ∗ s t r , char ∗∗ endptr , i n t base ) ; double s t r t o d ( const char ∗ s t r , char ∗∗ endptr ) ; Pierwszym parametrem funkcji jest napis podlegaj¡cy konwersji, drugim jest znak ograniczaj¡cy napis (moze to by¢ znak NULL). Trzecim parametrem w przypadku funkcji konwersji do postaci caªkowitej jest podstawa zapisu liczb (zawarta pomi¦dzy 2 a 36). Specjalna warto±¢ 0 pozwala automatycznie rozpoznawa¢ liczby postaci 0nnnnn (gdzie n to cyfra od zera do 7) jako ósemkowe a liczby postaci 0xuuuu jako szesnastkowe (u to cyfry od zera do 9 oraz a f lub A F) Unicode I 1. Jezeli ograniczy¢ si¦ do kodowania jednobajtowego (255 znaków) nie ma wªa±ciwie zadnych problemów, poza tym, ze pogram musi by¢ uruchamiany w odpowiednim ±rodowisku. Dost¦pne kodowania znaków to ISO-8859-n (n od 1 do 9), cp-12xx, i tak dalej, i tak dalej. . . 2. Standardowe funkcje porównywania ci¡gów znaków nie b¦d¡ dziaªaªy! 3. Uniwersalny system kodowania znaków Unicode zostaª dopuszczony do uzytku w standardzie C99 4. Z Unicode tez nie jest ªatwo, mamy kilka rodzajów. Zestaw znaków Unicode obejmuje ponad 900 tys. symboli. Zapisa¢ to mozna na 3 bajtach. Unicode II 5. Ze wzgl¦dów technicznych przyj¦to 4 bajty jako podstawowa wielko±¢ znaku (bo ªatwo jedn¡ instrukcj¡) wybra¢ z pami¦ci. 6. W praktyce to za duzo, st¡d warianty 6.1 UTF-8 od 1 do 6 bajtów (dla znaków ponizej 65536 do 3 bajtów) na znak; wszystkie standardowe znaki ASCII na jednym bajcie. 6.2 UTF-16 2 lub 4 bajty (UTF-32) na znak. 6.3 UCS-2 2 bajty na znak przez co znaki z numerami powyzej 65 535 nie s¡ uwzgl¦dnione 7. Domy±lne kodowanie dla C to kodowanie zlezne od systemu; linux: czterobajtowe!. Unicode III Co nalezy zrobi¢, by zacz¡¢ korzysta¢ z kodowania UCS-2 I I I powinni±my korzysta¢ z typu wchar_t (ang. wide character ), jednak je±li chcemy udost¦pnia¢ kod ¹ródªowy programu do kompilacji na innych platformach, powinni±my ustawi¢ odpowiednie parametry dla kompilatorów, by rozmiar byª identyczny niezaleznie od platformy. korzystamy z odpowiedników funkcji operuj¡cych na typie char pracuj¡cych na wchar_t (z reguªy skªadnia jest identyczna z t¡ róznic¡, ze w nazwach funkcji zast¦pujemy str na wcs np. strcpy wcscpy; strcmp wcscmp) je±li przyzwyczajeni jeste±my do korzystania z klasy string, powinni±my zamiast niej korzysta¢ z wstring, która posiada zblizon¡ skªadni¦, ale pracuje na typie wchar_t. Polskie literki UTF-8! # include < s t d i o . h> # include < s t r i n g . h> i n t main ( void ) { char n a p i s 1 [ 3 0 ] = " Ala ma kota " ; char n a p i s 2 [ 3 0 ] = " Ala ma kot ¦ " ; p r i n t f ( " n a p i s 1 : %d \ n " , ( i n t ) s t r l e n ( n a p i s 1 ) ) ; p r i n t f ( " n a p i s 2 : %d \ n " , ( i n t ) s t r l e n ( n a p i s 2 ) ) ; return 0 ; } Wyniki: napis1: 11 napis2: 12 Polskie literki # include < s t d i o . h> # include < s t r i n g . h> # include <wchar . h> i n t main ( void ) { char n a p i s 1 [ 3 0 ] = " Ala ma kota " ; char n a p i s 2 [ 3 0 ] = " Ala ma kot ¦ " ; wchar_t n a p i s 3 [ 1 2 ] = L " Ala ma kot ¦ " ; p r i n t f ( " n a p i s 1 : %d \ n " , ( i n t ) s t r l e n ( n a p i s 1 ) ) ; p r i n t f ( " n a p i s 2 : %d \ n " , ( i n t ) s t r l e n ( n a p i s 2 ) ) ; p r i n t f ( " n a p i s 3 : %d , s i z e o f n a p i s 3 %d \ n " , ( i n t ) wcslen ( n a p i s 3 ) , ( int ) sizeof ( napis3 ) ) ; return 0 ; } Wyniki napis1: 11 napis2: 12 napis3: 11, sizeof napis3 48 Polskie literki # include < s t d i o . h> # include < s t r i n g . h> # include <wchar . h> i n t main ( void ) { int i ; wchar_t m[ 2 ] = L " A " ; union ccc { char n [ 8 ] ; wchar_t N [ 2 ] ; } c; c .N [ 0 ] = m[ 0 ] ; c .N [ 1 ] = m[ 1 ] ; f o r ( i =0; i <8; i ++) p r i n t f ( " %d − %x \ n " , i , c . n [ i ] ) ; return 0 ; } 0 1 2 3 4 5 6 7 - 41 0 0 0 0 0 0 0 Polskie literki # include < s t d i o . h> # include < s t r i n g . h> # include <wchar . h> i n t main ( void ) { int i ; wchar_t m[ 2 ] = L " • " ; union ccc { char n [ 8 ] ; wchar_t N [ 2 ] ; } c; c .N [ 0 ] = m[ 0 ] ; c .N [ 1 ] = m[ 1 ] ; f o r ( i =0; i <8; i ++) p r i n t f ( " %d − %x \ n " , i , c . n [ i ] ) ; return 0 ; } 0 1 2 3 4 5 6 7 - 4 1 0 0 0 0 0 0 Locale 1. Locale to zestaw de nicji okre±laj¡cych specy czny dla róznych j¦zyków (i krajów) sposób prezentacji róznych informacji. 2. Z jakich± dziwnych powodów problem nie ma zbyt bogatej literatury . 3. Jezeli kto± chce si¦ zapozna¢ z pewn¡ realizacj¡ uniksow¡ mog¦ poleci¢ bardzo stary tekst System Operacyjny HP-UX a sprawa polska. Locale Unix Zachowanie systemu po wyborze okre±lonego j¦zyka zmienia si¦. Za pomoc¡ kilku zmiennych ±rodowiska mozna regulowa¢ zakres w jakim podporz¡dkowujemy si¦ specy cznym reguªom. I tak: LANG okre±la uzywany j¦zyk, LC_CTYPE de niuje charakter (litery, cyfry, znaki przestankowe, znaki drukowalne) poszczególnych znaków, LC_COLLATE okre±la sposób sortowania, LC_MONETARY opisuje zaznaczania jednostek monetarnych (symbol waluty, gdzie jest on umieszczany. . . ), LC_NUMERIC sposób zapisu liczb, znak oddzielaj¡cy grypy cyfr, znak oddzielaj¡cy cz¦±¢ caªkowit¡ od uªamkowej, LC_TIME posta¢ podawania daty i czasu, LC_MESSAGES j¦zyk uzywany w wy±wietlanych komunikatach, LC_ALL wszystkie LC_*. Locale Programowanie 1. Sprawa nie jest prosta! 2. Mozna wszystko zrobi¢ na wiele sposobów. 3. Bardzo cz¦sto komunikaty wyprowadzanie przez (rózne) programy powtarzaj¡ si¦. 4. Powstaje my±l stworzenia bazy danych zawieraj¡cych rózne komunikaty oraz ich tªumaczenia na rózne j¦zyki. 5. S¡ tez gotowe biblioteki zapewniaj¡ce obsªug¦ takiej bazy danych (oraz jej tworzenie). Locale Przykªad Wyniki # include < s t d i o . h> $ LANG=C ./stringi # include < s t d l i b . h> 144 # include < s t r i n g . h> $ LANG=pl_PL.utf8 ./stringi # include <wchar . h> -25 # include < l o c a l e . h> i n t main ( void ) { /∗ p r i n t f ( " % s \ n " , getenv ( " LANG " ) ) ; ∗/ s e t l o c a l e ( LC_ALL , getenv ( " LANG " ) ) ; p r i n t f ( " %d \ n " , w c s c o l l ( L " zó ª ¢ " , L " zó ªw" ) ) ; return 0 ; }