Materiały do nauki języka C/C++ Tomasz Kubik



Podobne dokumenty
Strumienie standardowe C

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

INFORMATYKA Studia Niestacjonarne Elektrotechnika

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

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

Wejście wyjście strumieniowe

2 Przygotował: mgr inż. Maciej Lasota

Informatyka, Ćwiczenie Uruchomienie Microsoft Visual C++ Politechnika Rzeszowska, Wojciech Szydełko. I. ZałoŜenie nowego projektu

Operacje na plikach. Informatyka. Standardowe strumienie wejścia i wyjścia

Operacje na plikach (niskiego poziomu) < IO.H >

1. Wprowadzanie danych z klawiatury funkcja scanf

Metodyki i Techniki Programowania MECHANIZM POWSTAWANIA PROGRAMU W JĘZYKU C PODSTAWOWE POJĘCIA

Operacje wejścia/wyjścia (odsłona druga) - pliki

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

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

Programowanie w językach

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

#include <stdio.h> void main(void) { int x = 10; long y = 20; double s; s = x + y; printf ( %s obliczen %d + %ld = %f, Wynik, x, y, s ); }

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

Zmienne, stałe i operatory

C++ - [3-5] Pliki i strumienie w C++

OPERACJE WEJŚCIA / WYJŚCIA. wysyła sformatowane dane do standardowego strumienia wyjściowego (stdout)

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście.

Podstawy programowania w C++

Biblioteka standardowa - operacje wejścia/wyjścia

Funkcje zawarte w bibliotece < io.h >

#include <stdio.h> int main( ) { int x = 10; long y = 20; double s; s = x + y; printf ( %s obliczen %d + %ld = %f, Wynik, x, y, s ); }

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

Funkcje zawarte w bibliotece < io.h >

Pliki wykład 2. Dorota Pylak

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

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

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

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

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

Wykład II Tablice (wstęp) Przykłady algorytmów Wstęp do języka C/C++

Funkcje standardowej biblioteki wejść-wyjść do wyświetlania i pobierania danych

jest mocny, skoro da się w nim wyrazić nowe pojęcia; łatwiej przenieść go na nową platformę jest mniejszy.

dr inż. Paweł Myszkowski Wykład nr 8 ( )

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

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

TEMAT : KLASY DZIEDZICZENIE

Jak napisać program obliczający pola powierzchni różnych figur płaskich?

Programowanie Obiektowe i C++

Zmienne powłoki. Wywołanie wartości następuje poprzez umieszczenie przed nazwą zmiennej znaku dolara ($ZMIENNA), np. ZMIENNA=wartosc.

Wykład 2 Operacje wejściawyjścia. Ewa Gajda

Klasa iostream... 1 Klasy ofstream, ifstream Struktura FILE... 8

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

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

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

Język C++ wykład VIII

Wstęp do programowania. Wykład 1

XV. Wskaźniki Odczytywanie adresu pamięci istniejących zmiennych Wskaźniki pierwsze spojrzenie.

Program 6. Program wykorzystujący strukturę osoba o polach: imię, nazwisko, wiek. W programie wykorzystane są dwie funkcje:

Wykład PASCAL - Pliki tekstowe

Adresowanie obiektów. Adresowanie bitów. Adresowanie bajtów i słów. Adresowanie bajtów i słów. Adresowanie timerów i liczników. Adresowanie timerów

Pliki. Operacje na plikach w Pascalu

Język C++ zajęcia nr 1

ISO/ANSI C dostęp do plików ISO/ANSI C. ISO/ANSI C dostęp do plików. ISO/ANSI C dostęp do plików. ISO/ANSI C dostęp do plików

Formatowane (tekstowe) wejście/wyjście. Binarne wejście/wyjście.

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

Tablice (jedno i wielowymiarowe), łańcuchy znaków

Proste typy zmiennych języka C++ *) Zapis 3.4 e-38 jest równoważny zapisowi 3,

Spis treści OBSŁUGA PLIKÓW W JĘZYKU C++ Informatyka 2. Instrukcja do pracowni specjalistycznej z przedmiotu. Numer ćwiczenia INF32

Wstęp do Programowania, laboratorium 02

Struktury, unie, formatowanie, wskaźniki

Pliki wykład. Dorota Pylak

Wstęp do informatyki- wykład 8 Pętla while, do while,for -pętla w pętli- przykłady Operator rzutowania Manipulatory

Wskaźniki do funkcji. Wykład 11. Podstawy programowania ( język C ) Wskaźniki do funkcji (1) Wskaźniki do funkcji (2)

Język C++ Różnice między C a C++

Wykład :37 PP2_W9

ISO/ANSI C dostęp do plików ISO/ANSI C. ISO/ANSI C dostęp do plików. ISO/ANSI C dostęp do plików. ISO/ANSI C dostęp do plików

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

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

1 Podstawy c++ w pigułce.

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

referencje Wykład 2. Programowanie (język C++) Referencje (1) int Num = 50; zdefiniowano zmienną Num (typu int) nadając jej wartość początkową 50.

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

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

Programowanie i struktury danych

Pliki wykład 2. Dorota Pylak

Pliki wykład. Dorota Pylak

Zasady programowania Dokumentacja

KURS C/C++ WYKŁAD 5. Typ wyliczeniowy enum

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

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

Programowanie obiektowe

Programowanie w językach wysokiego poziomu

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

Temat 1: Podstawowe pojęcia: program, kompilacja, kod

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

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Referencje. Zasady zaliczeń. Zasady zaliczeń. Zasady zaliczeń. Zasady zaliczeń. Zaawansowane Programowanie Obiektowe. Informacje organizacyjne:

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

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

1 Podstawy c++ w pigułce.

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

Globalne / Lokalne. Wykład 15. Podstawy programowania (język C) Zmienne globalne / lokalne (1) Zmienne globalne / lokalne (2)

Język C i C++. Podstawy. Zagadnienia do opanowania. Przykład 1. (modyfikuj kod, aby zrealizować punkty 5., 7.)

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

Transkrypt:

Materiały do nauki języka C/C++ Tomasz Kubik Operacje wejścia i wyjścia w języku C i C++ Operacje wejścia/wyjścia (we/wy) nie zostały wbudowane w struktury ani języka C ani C++. śaden z tych języków nie dostarcza poleceń, komend czy słów kluczowych, których bezpośrednie uŝycie pozwoliłoby na wyświetlenie danych na ekranie komputera lub zapisanie ich do pliku. Oczywiście w C/C++ moŝna korzystać z operacji we/wy, jednak operacje te są dostępne poprzez odpowiednie biblioteki. UŜycie bibliotek pozwala oddzielić operacje zaleŝne od platformy (środowiska programowego i sprzętowego) od operacji niezaleŝnych. Dzięki temu kod źródłowy programu w C/C++ moŝe być przeniesiony z komputera PC na komputery HP lub stacje Sun i tam bez problemu skompilowany (jeśli tylko nie będą w nim wykorzystane niestandardowe biblioteki C/C++). Za poprawne wykonanie operacji we/wy programu odpowiedzialny będzie dostawca kompilatora i bibliotek. Strumienie Pojęcie strumienia najłatwiej chyba wytłumaczyć na przykładzie zbiornika z wodą, mającego zawór wlotowy i zawór wylotowy. Aby napełnić zbiornik (wprowadzić dane do strumienia) naleŝy odkręcić zawór wlotowy. Wtedy woda zacznie do zbiornika napływać (bufor strumienia zacznie zapełniać się danymi jeśli oczywiście taki bufor istnieje). Gdy otworzony zostanie zawór wylotowy, woda zacznie ze zbiornika wypływać (odpowiada to pobieraniu danych ze strumienia). Jeśli woda szybciej wypływa niŝ napływa (dane ze strumienia szybciej są pobierane niŝ dostarczane), zbiornik opróŝnia się całkowicie (strumień danych staje się pusty). Jeśli zaś woda napływa szybciej niŝ odpływa (bufor strumienia jest zapełniany szybciej niŝ opróŝniany), następuje przepełnienie. Jedyną istotną róŝnicą pomiędzy strumieniem danych a jego wodną analogią jest fakt, iŝ cząsteczki wody mogą mieszać się ze sobą, zaś kolejność danych w strumieniu nie moŝe ulec zmianie. Co więcej, dla strumieni jest moŝliwe wykonanie operacji pobierania, zwracania, jak równieŝ przewijania danych (choć nie dotyczy to wszystkich zaimplementowanych strumieni). W odniesieniu do zbiornika z wodą miałoby to odpowiednik w przetłaczania wody w róŝnych kierunkach poprzez jego zawory. NajwaŜniejszym celem, któremu przyświecało zaimplementowanie strumieni było opracowanie metody pozwalającej na łatwe korzystanie z ekranu monitora, klawiatury oraz zasobów dyskowych. To właśnie strumienie pozwalają programiście zapomnieć o szczegółach realizacji operacji we/wy. Wystarczy, aby strumień został skojarzony z jakimś urządzeniem, aby przesyłanie danych ograniczyło się do wykorzystania własności samego strumienia. Przy pracy ze strumieniami wyróŝnić moŝna trzy zasadnicze kroki. Pierwszym jest nawiązanie połączenia z urządzeniem i skojarzenie go ze strumieniem (mówi się o otwarciu strumienia). Drugim jest przesyłanie danych. Trzecim krokiem jest zamknięcie połączenia (mówi się o zamykaniu strumienia). Zarówno otwarcie strumienia, jak i przesyłanie danych oraz jego zamknięcie realizuje się poprzez funkcje operujące na strumieniu reprezentującym połączenie. KaŜdy otwarty w programie strumień powinien zostać zamknięty zanim program zakończy się. Jeśli program zakończy się, a któryś ze strumieni pozostanie otwarty, jego zamknięciem zajmie się system operacyjny. Jednak zamknięcia strumienia przez system operacyjny jest sytuacja niepoŝądaną. MoŜe ona prowadzić do powaŝnych błędów i utraty danych. Kiedy program zaczyna swoje działanie, kod inicjujący automatycznie otwiera kilka strumieni: standardowe wejście (stdin), standardowe wyjście (stdout), oraz standardowe wyjście błędów (stderr). Zgodnie z nazwą wejście normalnie słuŝy jako źródło danych do programu, wyjście pozwala wyprowadzać dane z programu, strumień błędu zaś pozwala wyprowadzać komunikaty o błędach. Dzięki strumieniom praktycznie nie ma Ŝadnej róŝnicy pomiędzy odczytywaniem danych z pliku a odczytywaniem danych z klawiatury. Podobnie, jeśli wyjście programu składa się ze znaków

alfanumerycznych i interpunkcyjnych, nie ma Ŝadnej róŝnicy między zapisem danych do pliku, a wypisaniem ich na ekran komputera lub wyprowadzeniem do potoku (pipe) następnego programu. Strumień wejściowy domyślnie jest skojarzony z klawiaturą, strumień wyjściowy i strumień błędu - z ekranem komputera. Jednak skojarzenie to moŝna zmienić. Istnieją na to dwa sposoby. Pierwszy sposób polega na wykorzystaniu moŝliwości samego systemu operacyjnego. W tym przypadku o skojarzeniu strumieni decyduje format komendy uruchamiającej program (wydanej w linii poleceń). Drugi sposób polega na wykorzystaniu przez programistę moŝliwości bibliotek we/wy. W tym przypadku skojarzenie strumieni jest zaimplementowane w kodzie źródłowym programu. Składnia komend wydawanych w linii poleceń moŝe być róŝna w róŝnych systemach operacyjnych. Zazwyczaj standardowe wejście kojarzy się z plikiem wydając komendę: mprog < plikwe. Komenda ta znaczy tyle, co: uruchom program mprog kojarząc ze standardowym wejściem plik o nazwie plikwe (a nie klawiaturę!). Podobnie przekierować moŝna strumień wyjściowy: mprog > plikwy. UŜycie operatora > w podanym przykładzie spowoduje, Ŝe dane wyjściowe z programu mprog zapisane zostaną w pliku o nazwie plikwy (jeśli plik o podanej nazwie nie istnieje, to zostanie on stworzony, w przeciwnym razie system operacyjny moŝe zgłosić błąd). Z poziomu komend moŝna równieŝ skojarzyć wyjście jednego programu z wejściem do programu drugiego. Odpowiednia komenda miałaby postać: mprog1 mprog2, gdzie operator występujący w tej komendzie tworzy potok. Przykłady najczęściej uŝywanych komend słuŝących przekierowaniu strumieni w systemie operacyjnym UNIX są podane w poniŝszej tabeli. Znaczenie: uruchom program prog i... komenda (csh) komenda (sh) skojarz stdout z plikiem file prog > file prog > file skojarz stderr z plikiem file prog 2> file skojarz stdout i stderr z plikiem file prog >& file prog > file 2>&1 skojarz stdin z plikiem file prog < file prog < file skojarz stdout z plikiem file (dopisuj do końca) prog >> file prog >> file skojarz stderr z plikiem file (dopisuj do końca) skojarz stdout i stderr z plikiem file (dopisuj do końca) prog >>& file prog 2>> file skojarz stdin z klawiaturą i czytaj dopóki c prog <<c prog <<c prog >> file 2>&1 utwórz potok (stdout programu prog do prog2) prog prog2 prog prog2 utwórz potok (stdout i stderr programu prog do prog2) prog & prog2 prog 2>&1 prog2 Uwaga: RóŜne systemy operacyjne (a nawet róŝne powłoki tego samego systemu) mogą róŝnić się pod względem składni komend i ich moŝliwości. Większość z nich pozwala jednak na jednoczesne przekierowanie standardowego wejście i wyjścia w jednym poleceniu: prog < plikwe > plikwy (czytanie z pliku plikwe i pisanie do pliku plikwy). Niektóre z nich pozwalają zapisać stderr w trzecim pliku. W unix owej powłoce bash odpowiednia komenda miałaby postać: prog < plikwe > plikwy 2> plikerr. Rozdzielenie stdout od stderr moŝe być nieco bardziej skomplikowane dla innych powłok (w przypadku csh osiąga się to przez wydanie polecenia (prog > plikwy) >& plikerr ). Co więcej, w niektórych systemach operacyjnych istnieją specjalne pliki systemowe na stałe związane ze standardowymi strumieniami (jak np. unix owe /dev/stdin, /dev/stdout, /dev/stderr). Korzystanie z takich plików nie róŝni się od korzystania ze zwykłych plików. Strumienie w C W języku C strumienie są obiektami reprezentowanymi przez strukturę danych o nazwie FILE. PoniewaŜ większość funkcji bibliotecznych operuje na obiektach typu FILE *, zwyczajowo obiekty te określa się mianem wskaźników pliku mając jednak na myśli strumienie. Prowadzi to czasem do konfliktu w nazewnictwie. Typ FILE jest zadeklarowany w pliku nagłówkowym stdio.h. Obiekt typu FILE przechowuje w sobie informacje o połączeniu ze związanym ze sobą plikiem (w tym wskaźnik pozycji

pliku oraz informacje związane z buforowaniem). W kaŝdym obiekcie-strumieniu jest przechowywana równieŝ informacja o statusie błędu oraz stanie końca strumienia. Dostęp do nich jest realizowany przez odpowiednie funkcje. Obiekty typu FILE są tworzone i zarządzane wewnętrznie przez funkcje biblioteki wejścia/wyjścia. Nie naleŝy tworzyć własnych obiektów typu FILE. Program powinien posługiwać się jedynie wskaźnikami do tych obiektów, tj. zmiennymi zadeklarowanymi jako FILE *. Strumienie standardowe i funkcje operujące na nich Lista standardowych strumieni w języku C składa się z trzech elementów: stdin (strumień wejściowy), stdout (strumień wyjściowy) oraz stderr (standardowe wyjście błędów). W niektórych implementacjach wyróŝnia się dodatkowo stdprn (strumień wyjściowy związany z drukarką), stdaux (strumień wyjściowy związany z ekranem). Najczęściej uŝywanymi funkcjami operującymi na tych strumieniach są: printf, puts, scanf, gets (zdefiniowane w stdio.h). printf jest funkcją słuŝącą do wysyłania sformatowane danych do stdout, zdefiniowaną w stdio.h. Zazwyczaj funkcja ta jest uŝywana do wypisywania danych na ekranie komputera (jeśli stdout jest skojarzony z ekranem komputera, a nie z np. plikiem). Funkcja printf zwraca liczbę wypisanych znaków lub wartość ujemną, jeśli wystąpił błąd. Funkcja ta moŝe mieć zmienną liczbę parametrów. Jej składnia wygląda następująco: int printf(const char * ciąg_formatujący[,argument_1, argument_2,...]); ciąg_formatujący w wywołaniu printf musi pojawić się zawsze, natomiast obecność kolejnych argumentów jest uzaleŝniona od postaci ciągu_formatującego. ciąg_formatujący jest stałą łańcuchową, tj. ciągiem znaków ujętych w podwójne cudzysłowie. MoŜe on zawierać: zwykłe znaki (widoczne znaki ASCII z pominięciem niektórych z nich), sekwencje znaków kontrolnych (składające się ze znaku \ i pojedynczej litery), oraz specyfikację formatowania kolejnych argumentów (zaczynające się znakiem %). Kiedy ciąg_formatujący nie zawiera Ŝadnej specyfikacji formatowania, funkcja printf ma tylko jeden argument ciąg_formatujący właśnie. Jeśli nie występują w nim sekwencje kontrolne, to ciąg_formatujący jest zwykłym tekstem, bez zmian wypisywanym na stdout. Gdy ciąg_formatujący zawiera sekwencje kontrolne, ich znaczenie będzie takie, jak podano w poniŝszej tabelce: sekwencje znaków kontrolnych sekwencja znaczenie \a dzwonek (alarm) Przykład: kod źródłowy \b cofnięcie (backspace) \n znak nowej linii \t znak tabulacji \\ ukośnik (backslash) \? pytajnik \' pojedynczy apostrof \" podwójny apostrof wynik #include <stdio.h> void main(){ printf( "\n\nsekwencja\tznaczenie" ); printf( "\n=========\t=======" ); printf( "\n\\a\t\tdzwonek" ); printf( "\n\\b\t\tbackspace" ); printf( "\n...\t\t..."); Sekwencja Znaczenie ========= ======= \a dzwonek \b backspace......

Obecność w ciągu_formatującym specyfikacji formatowania świadczy o tym, Ŝe funkcja printf ma wypisać na stdout wartość jakiegoś argumentu. Sposób wypisania tej wartości zaleŝy od specyfikacji formatowania. Składnia specyfikacji formatowania jest następująca (choć moŝe być bogatsza): %[flagi] [szerokość] [.precyzja] [{ l h L ]znak_typu gdzie znak_typu jest parametrem obowiązkowym, pozostałe zaś parametry specyfikacji są opcjonalne. flagi (tj. jeden znak lub parę znaków) definiują sposób wyrównania oraz sposób wypisywaniu znaków, pól pustych, przecinków dziesiętnych, przedrostów dla liczb dziesiętnych, ósemkowych i szesnastkowych. Ich znaczenie i wartości domyślne przedstawia poniŝsza tabela. Flaga Znaczenie Wartość domyślna - wyrównanie do lewej wewnątrz danego pola wyrównanie do prawej + przedrostek określający znak (+ albo -) dla liczby ze znakiem znak występuje tylko dla ujemnych liczb ze znakiem 0 jeśli jest przedrostkiem szerokości, zera są dodawane aŝ do nie uwzględniane wypełnienia pola o zadanej minimalnej szerokości. 0 jest ignorowane, jeśli: występuje razem ze znakiem ; towarzyszy któremuś ze znaków typu (i, u, x, X, o, d). ' ' (spacja) jeśli wartość wyjściowa jest ze znakiem i jest dodatnia, to dodawana jest przed nią spacja. Flaga ta jest ignorowana, jeśli wystąpi ona razem z flagą + # towarzysząc znakom typu o, x lub X powoduje, odpowiednio, dopisanie 0, 0x lub 0X do kaŝdej niezerowej wartości wyjściowej towarzysząc znakom typu e, E lub f wymusza wystąpienie przecinka dziesiętnego w kaŝdym przypadku towarzysząc znakom typu g lub G wymusza pojawienie się przecinka dziesiętnego we wszystkich przypadkach i zabezpiecza przed obcinaniem zer. Jest ignorowana, kiedy występuje razem z c, d, i, u lub s. spacje nie są dodawane nie występują znaki puste przecinek dziesiętny, jeśli są jakieś liczby po przecinku przecinek dziesiętny, jeśli są jakieś liczby po przecinku. Zera są obcinane szerokość jest nieujemną, dziesiętną liczbą całkowitą, określającą minimalną liczbę wypisywanych znaków. Jeśli liczba wypisywanych znaków wartości wyjściowej jest mniejsza niŝ zadeklarowana szerokość, do wypisywanej wartości dodawane są znaki puste do lewej lub do prawej strony (zaleŝnie od obowiązującego sposobu wyrównania) aŝ do osiągnięcia minimalnej liczby znaków. Jeśli szerokość poprzedzona jest znakiem 0, puste pola są wypełniane zerami, aŝ do osiągnięcia minimalnej liczby znaków. Jeśli parametr szerokość jest zadeklarowany jako gwiazdka (*), wtedy wartość dziesiętna określająca minimalną liczbę wypisywanych znaków jest pobierana z listy argumentów. Wartość ta musi poprzedzać argument, który aktualnie będzie formatowany. Zadeklarowanie małej szerokości nigdy nie powoduje obcinania wartości. Jeśli liczba znaków wartości wyjściowej przekracza szerokość lub gdy szerokość nie jest zdefiniowana, to są wypisywane wszystkie znaki (zgodnie z zadeklarowaną precyzją). precyzja jest nieujemną, dziesiętną liczbą całkowitą określającą liczbę znaków, które mają być wypisane, liczbę miejsc dziesiętnych lub liczbę cyfr znaczących. Deklaracja precyzji moŝe powodować obcinanie wypisywanych wartości wyjściowych lub zaokrąglanie wartości zmiennoprzecinkowych (zaleŝnie od znaku_typu). Jeśli precyzja jest określona jako 0 i wartość do wypisania jest równa 0, to Ŝaden znak nie jest wypisywany (jak w przypadku printf( "%.0d", 0 );). Jeśli parametr precyzja jest zadeklarowany jako gwiazdka (*), jego wartość jest pobierana z listy argumentów. Wartość ta musi

poprzedzać argument, który aktualnie będzie formatowany. Domyślna wartość precyzji dla liczb całkowitych jest równa 1, zaś dla liczb zmiennoprzecinkowych jest równa 6. znak_typu określa sposób, w jaki potraktowany zostanie odpowiadający mu argument funkcji printf. W ogólności liczba specyfikacji formatowania (tj. fragmentów ciągu_formatującego zaczynających się od %) powinna odpowiadać liczbie argumentów funkcji printf (tj. liczbie argumentów występujących za ciągiem_formatującym). Jeśli argumentów w wywołaniu printf jest więcej niŝ specyfikacji formatowania, nadmiarowe argumenty nie zostaną wypisane. Jeśli argumentów jest mniej, wypisane zostaną śmiecie. Ponadto argumentem funkcji printf moŝe być wyraŝenie, którego wartość jest wyliczana. znak_typu i typ argumentu musza ze sobą korelować. Na przykład: specyfikacji formatowania %c powinien odpowiadać argument typu char, %d argument typu int lub short, %ld argument typu long, %s argumentu typu tablica znaków itd. PoniŜsza tabela zawiera listę znaków typu oraz ich znaczenie. Znaki formatujące i ich znaczenie znak Znaczenie d, i liczba całkowita ze znakiem w kodzie dziesiętnym u liczba całkowita bez znaku w kodzie dziesiętnym o liczba całkowita w kodzie ósemkowym x, X liczba całkowita (bez znaku) w kodzie szesnastkowym (x dla małych liter, X dla duŝych liter). c pojedynczy znak (odpowiadający argument powinien być kodem ASCII znaku) e, E liczba zmiennoprzecinkowa w notacji naukowej, zgodnie z podaną precyzją, gdzie e stosuje się dla wypisania małej litery wykładnik, E dla litery duŝej. Dla domyślnej wartości precyzji 123.45 wyświetlone będzie jako 1.234500e+002. f liczba zmiennoprzecinkowa w kodzie dziesiętnym, zgodnie z podaną precyzją. Dla domyślnej wartości precyzji 123.45 wyświetlone będzie jako 123.450000. g, G g działa jak e, lub f, zaś G jak E lub f, wybierając format dający bardziej zwarty zapis dla bieŝącej wypisywanej wartości. Format e uŝyty zostanie, jeśli wykładnik wartości jest mniejszy niŝ 4 albo większy lub równy zadeklarowanej precyzji, w przeciwnym razie uŝyty zostanie format f. Zera na końcu są obcinane, przecinek wystąpi, jeśli istnieje przynajmniej jedna cyfra po przecinku. n Nic nie wypisuje. Odpowiadający argument powinien być wskaźnikiem do int. Funkcja printf wpisze pod ten wskaźnik liczbę dotychczas wyprowadzonych znaków (np. przy deklaracji int licznik; wykonaniu funkcji printf("1234%n567,&licznik); sprawi, Ŝe licznik będzie równy 5). s łańcuch znaków (argument powinien być wskaźnikiem do char). Znaki są wypisywane aŝ do napotkania znaku null ( \0 ) lub przekroczenia limitu wypisanych znaków określonego przez precyzję (standardowo jest to 32767). Kończący ciąg znak null nie jest wypisywany. l przedrostek (long) stosowany przed: d u x o (nie odpowiada mu Ŝaden argument) Jeśli po znaku % wystąpi jakiś znak nieodgrywający roli w formatowaniu, znak ten zostanie wypisany bez Ŝadnych zmian. Dlatego printf("%%"); wypisuje pojedynczy znak %. Szerokość i precyzja decydują o wielkości pola przeznaczonego na wypisywaną liczbę oraz ilości cyfr uwzględnianych po przecinku. Na przykład specyfikacja %4d mówi, Ŝe argument będzie wypisany jako liczba dziesiętna na czterech pozycjach, %4f jako liczba rzeczywista na 4 pozycjach, %5.3 jako liczba rzeczywista na 5 pozycjach z dokładnością do 3 miejsc po przecinku itd.

Przykład: kod źródłowy #include <stdio.h> int a = 2, b = 10; char c = '$'; float f = 1.05, g = 25.5, h = -0.1; main() { printf("1:a = %d, f = %f\n", a, f); printf("2:\t%d \t%c \t%s\n", a, c, "wyraz"); printf("3:\t%f\t%f\n", f, g, h); printf("4:\t%f\n\t%f\n", f, g); printf("%f%%, b/a = %d", f, b/a); return 0; wynik 1:a = 2, f = 1.050000 2: 2 $ wyraz 3: 1.050000 25.500000 4: 1.050000 25.500000 5:1.050000%, b/a = 5 scanf jest funkcją słuŝącą do wczytywania pod zadany adres pamięci sformatowane danych ze strumienia stdin, zdefiniowaną w stdio.h. Funkcja ta moŝe mieć zmienną liczbę parametrów. Jej składnia wygląda następująco: int scanf( const char * ciąg_formatujący[,argument] ); ciąg_formatujący w wywołaniu scanf musi pojawić się zawsze, natomiast obecność kolejnych argumentów jest uzaleŝniona od postaci ciągu_formatującego. ciąg_formatujący jest stałą łańcuchową, tj. ciągiem znaków ujętych w podwójne cudzysłowie, definiującą sposób interpretacji danych w strumieniu wejściowym. ciąg_formatujący jest przeglądany od lewej strony do prawej. Podobnie jak w przypadku funkcji printf, moŝe on zawierać: znaki puste (spacje (' '); tabulatory ('\t'); znaki nowej linii ('\n')); znaki niepuste (ale bez %); specyfikacje formatowania. Pojedynczy znak pusty w ciągu formatującym powoduje, Ŝe scanf pomija w strumieni wejściowym wszystkie pojawiające się znaki puste, aŝ do wystąpienia znaku niepustego. Mówiąc inaczej, jednemu znakowi pustemu w ciągu formatującym odpowiada dowolna liczba (włącznie z 0) pustych znaków lub ich kombinacji w strumieniu. Znaki niepuste (jak np. 'a',..., '9') powodują, Ŝe scanf czyta odpowiadające im niepuste znaki ze strumienia wejściowego (choć i w tym wypadku nigdzie ich nie zapisuje). Jeśli któryś z niepustych znaków w strumieniu wejściowym nie pokrywa się z niepustym znakiem w ciągu formatującym, scanf kończy swoje działanie, pozostawiając ten znak w strumieniu wejściowym. Obecność specyfikacji formatowania w ciągu_formatującym świadczy o tym, Ŝe funkcja scanf ma: wczytać znaki ze standardowego wejścia, przekonwertować je zgodnie z podanym formatem, zapisać otrzymane dane pod adres podany w argumencie. Argumenty powinny być adresami w pamięci, pod które wartości danych mają być wczytywane. Kolejne specyfikacje formatowania odpowiadają kolejnym argumentom. Składnia specyfikacji formatowania jest następująca: %[*] [szerokość] [{h l L]znak_typu Jeśli po % występują jakieś znaki, które nie decydują o formatowaniu, znaki te (aŝ do następnego znaku %) muszą wystąpić w strumieniu wejściowym. Jeśli w strumieniu wejściowym jest spodziewany znak %, moŝna go przeskoczyć uŝywając %%. gwiazdka * występująca zaraz za znakiem % nie pozwala przypisać wartości pod adres podany w bieŝącym argumencie, choć wartość ta jest wczytana zgodnie z podaną specyfikacją. UmoŜliwia to przeskoczenie wybranej wartości w strumieniu wejściowym. Pole w strumieniu wejściowym jest zdefiniowane jako ciąg znaków, które czytane są: aŝ do pierwszego wystąpienia znaku pustego (spacji, tabulatora, znaku nowej linii); lub aŝ do pierwszego znaku, który nie

moŝe być skonwertowany zgodnie z podaną specyfikacją; lub aŝ do osiągnięcia limitu zdefiniowanego parametrem szerokość (tj. maksymalnej liczby znaków dla danego argumentu). znak_typu mówi o tym, jakiego typu danych naleŝy spodziewać się w strumieniu. Lista znaków typu funkcji scanf jest podobna do znaków typu funkcji printf: Znaki formatujące scanf i i ich znaczenie znak Znaczenie d, i liczba całkowita ze znakiem w kodzie dziesiętnym u liczba całkowita bez znaku w kodzie dziesiętnym o liczba całkowita w kodzie ósemkowym (bez znaku) x, X liczba całkowita (bez znaku) w kodzie szesnastkowym c pojedynczy znak s łańcuch znaków f, e liczba zmiennoprzecinkowa Przedrostki znaku typu (l, h, L) są modyfikatorami typu argumentu. l (przed d u x o ) oznacza, Ŝe będzie on traktowany jako long int; l (przed f e ) - jako double; h - jako short int; L (przed: f e ) jako long double. Funkcja scanf zwraca liczbę poprawnie wczytanych danych, tj. liczbę wartości, które zostały poprawnie skonwertowanych i przypisanych argumentom. Jeśli jakaś dana została wczytana, a nie została przypisana argumentowi, to nie jest ona zliczana. Jeśli funkcja zwróci 0, to znaczy, Ŝe nie została wykonana Ŝadna operacja przypisania. W przypadku wystąpienia błędu wartością zwracaną jest EOF. Wartość EOF jest równieŝ zwracana, jeśli napotkany został znak końca pliku lub znak końca ciągu znaków podczas próby czytania pierwszego znaku. Jeśli argumentów w wywołaniu scanf jest zbyt wiele (więcej niŝ specyfikacji formatowania), nadmiarowe argumenty są ignorowane. Jeśli argumentów jest za mało, wynik działania scanf jest nieprzewidywalny. Przykład: kod źródłowy wynik #include <stdio.h> void main(void){ int a; float b; double c; char d; printf("podaj liczby typu: int, float, double, char:" ); scanf( "%d %f %le %c", &a, &b, &c, &d); printf(("wynik wczytywania: a=%d b=%f c=%e d=%c", a, b, c, d); > Podaj liczby typu: int, float, double, char: > 123 (Enter) > 456.789 12e-10 (Enter) > z (Enter) > Wynik wczytywania: a=123, b=456.789, c=1.200000e-009 znak == a Strumienie w C++ W języku C++ wykonywanie operacji we/wy zaimplementowano w sposób obiektowy. Operacje na strumieniach są dostępne poprzez obiekty odpowiednich klas. Wszystkie klasy obsługujące we/wy (klasy iostream) bazują na koncepcji strumienia, w której strumień jest przedstawiany jako rozszerzony plik. Rozszerzony plik moŝe być zarówno źródłem bajtów, jak teŝ miejscem ich zapisu. W systemie operacyjnym urządzenia we/wy (jak klawiatura, monitor, drukarka oraz porty komunikacyjne) są widziana poprzez ich sterowniki właśnie jako rozszerzone pliki (była juŝ o tym mowa na początku tego rozdziału). Klasy odpowiedzialne za wykonywanie operacji wejścia/wyjścia współpracują z tymi plikami. Cechy strumienia, z punktu widzenia implementacji klasy, zaleŝą od moŝliwości klasy (jej metod, parametrów i zaimplementowanych operatorów wstawiania i pobierania danych). Podejście obiektowe pozwoliło uniknąć wielokrotnego definiowania tych samych operacji dla klas działających na róŝnych

strumieniach (odpowiadającym róŝnym urządzeniom). Na przykład składnia operacji czytania z i pisania do strumieni jest taka sama dla strumieni związanych z pamięcią jak i dla strumieni związanych z plikami dyskowymi. Dzięki takiemu podejściu wszystkie klasy strumieni mogły się znaleźć w jednym drzewie dziedziczenia. Choć hierarchiczna struktura klas dokładnie pokazuje drogę dziedziczenia poszczególnych ich parametrów i metod, juŝ na podstawie samych nazw klas moŝna określić ich przeznaczenie: diagram klas fragment nazwy przeznaczenie i... (in) obsługa strumieni wejściowych (jak obiekty klasy: istream, ifstream, istrstream); o... (out) obsługa strumieni wyjściowych (np. ostream, ofstream, ostrstream)..f... (file) obsługa strumieni plikowych (np. ifstream, ofstream, fstream), str.. (string) obsługa strumieni pamięciowych (np. istrstream, strstream) Klasa streambuf jest klasą abstrakcyjną (zdefiniowaną w iostream.h), z której korzystają inne klasy iostream. streambuf udostępnia operacje we/wy na najniŝszym, niezbuforowanym poziomie. Klasa ios (zdefiniowanej w io.h) jest klasą bazową dla wszystkich innych klas iostream. W klasie tej zamodelowano właściwości (tzn. metody, parametry i stałe) wspólne dla wszystkich strumieni. Klasa ios posiada juŝ pewne metody pozwalające na wykonywanie buforowanych i formatowanych operacji we/wy, jednak nie uŝywa się jej bezpośrednio. Do metody klasy ios sięga się z poziomu specjalizowanych klas potomnych. Klasy: istream, ostream oraz iostream są pochodnymi klasy ios (tzn. klasami dziedziczącymi cechy klasy ios). Dwie pierwsze słuŝą, odpowiednio, do tworzenia strumieni wejściowych i strumieni wyjściowych. Trzecia pozwala na tworzenie strumieni wejściowo/wyjściowych. W klasie istream i ostream przeciąŝone są, odpowiednio, operatory << oraz >> (zdefiniowane w iostream.h). W klasie istream jest zdefiniowane wskaźnik połoŝenia do czytania (ustawiany metodą seekg), w klasie ostream jest zdefiniowany natomiast wskaźnik połoŝenia do zapisu (ustawiany metodą seekp). Klasy xxx_withassign są wariantami klas xxx pozwalającymi na przekierunkowanie predefiniowanych strumieni cin, cout, cerr oraz clog. Za ich pomocą moŝna sprawić, aby np. wszystkie dane wysyłane na standardowe wyjście zapisywane były do pliku, a nie wypisywane na ekran. Klasy ifstream i ofstream (zdefiniowane w fstream.h, wywodzące się z klas istream i ostream) oraz klasa fstream (wywodząca się z klasy iostream) słuŝą do wykonywania operacji na plikach. Metody tych klas pozwalają otwierać pliki, tj. pozwalają na połączenie danego strumienia z plikiem fizycznym w charakterze wejścia, wyjścia lub wejścia/wyjścia danych. Klasy istrstream, ostrstream oraz strstream (zdefiniowane w strstrea.h, wywodzące się z klas istream, ostream oraz iostream) pozwalają na pisanie lub czytanie ze strumienia, którym jest zarezerwowany blok pamięci. W przypadku istrstream blok pamięci musi zostać zarezerwowany zanim skonstruowany zostanie obiekt tej klasy. W przypadku pozostałych dwóch klas blok pamięci

moŝna zarezerwować przed skonstruowaniem obiektu albo jego rezerwację powierza się konstruktorowi obiektu. Klasa Iostream_init jest związana z tworzeniem i inicjalizowaniem strumieni standardowych. Strumienie standardowe Język C++ dostarcza czterech predefiniowanych strumieni. Są to: cin (standardowe wejście połączone z klawiatura), cout (standardowe wyjście połączone z ekranem monitora), cerr (standardowe wyjście połączone z monitorem), clog (podobnie do cerr, tylko, Ŝe jest to strumień buforowany). Klasą odpowiedzialną za automatyczne tworzenie i inicjalizowanie predefiniowanych strumieni (tj. tworzenie i inicjalizowanie odpowiednich obiektów) jest statyczna klasa Iostream_init. Normalnie uŝytkownik nie tworzy Ŝadnego obiektu klasy Iostream_init. Obiekt tej klasy jest tworzony niejawnie przy pierwszym pojawieniu się referencji do któregoś z predefiniowanych strumieni. Predefiniowane strumienie są obiektami klas istream (cin) oraz ostream (cout, cerr, clog). Dysponują one wszystkimi moŝliwościami tych klas, a więc dysponują równieŝ moŝliwościami odziedziczonymi z klasy bazowej ios. Wewnątrz klasy ios jest zdefiniowanych szereg parametrów, typów i metod, dzięki którym moŝna sterować własnościami klasy, wykonywać pewne operacje, monitorować osiągane stany. Bity niektórych parametrów są interpretowane jako flagi określające np. sposób formatowania danych, czy teŝ flagi informujące o błędach. W ogólności uŝytkownik nie musi wcale wiedzieć, za co odpowiadają poszczególne bity parametrów. Wystarczy, jeśli znać będzie funkcje operujące na tych bitach oraz typy wyliczeniowe zdefiniowanych w klasie (o nazwach odpowiadających roli bitów). NajwaŜniejsze funkcje, manipulatory, flagi i stałe dostępne w klasie ios są przedstawione poniŝej. Funkcje dostępu do flag i funkcje definiujące sposób formatowania (metody publiczne ios::) long flags( long lflags ); long flags() const; long setf( long lflags ); long setf( long lflags, long lmask ); long unsetf( long lflags ); char fill( char cfill ); char fill() const; int precision( int np ); int precision() const; int width( int nw ); - ustawia flagi formatowania i zwraca stare flagi - odczytuje flagi formatowania - ustawia te flagi formatowania, którym odpowiada 1 w argumencie lflags i zwraca cały stare flagi; - zmienia te wartości flag, którym odpowiada 1 w argumencie lmask, przy czym nowa wartość flagi jest zdefiniowana wartością bitu na odpowiednim miejscu w argumencie lflags; oraz zwraca stare flagi - czyści te flagi formatowania, którym w argumencie lflags odpowiada 1 i zwraca stare flagi - ustawia nowy znak wypełnienia i zwraca stary znak - odczytuje znak wypełnienia - ustawia dokładność wyświetlania liczb zmiennoprzecinkowych i zwraca starą dokładność - odczytuje dokładność wyświetlania liczb zmiennoprzecinkowych. Domyślnie dokładność jest ustawiona na 6 cyfr. Jeśli formatem wyświetlania jest format scientific lub fixed, dokładność określa liczbę cyfr po przecinku. Jeśli formatem jest automatic, precision określa ogólną liczbę cyfr znaczących. - ustawia szerokość pola w strumieniu wyjściowym zwracając starą wartość - odczytuje szerokość pola w strumieniu wyjściowym. Jeśli

int width() const; szerokość wynosi 0 (wartość domyślna), do strumienia wstawiane będą tylko znaki konieczne do reprezentowania wstawianej wartości. Kiedy szerokość jest róŝna od 0, wolne pola uzupełniane są znakami wypełnienia. Deklaracja szerokości mniejszej niŝ liczba wyprowadzanych znaków danej wartości nie powoduje ich obcięcia. Parametr nw jest szerokością minimalną. Maski (statyczne parametry publiczne ios::) static const long basefield; uŝywana do otrzymania flagi podstawy konwersji (dec, oct, lub hex) static const long adjustfield uŝywana do ustawienia flagi wyrównania w polu (left, right, lub internal) static const long floatfield uŝywana do otrzymania flagi formatu numerycznego (scientific lub fixed) Przykład (warunek sprawdzający, czy liczby wypisywane będą szesnastkowo): extern ostream os; if( ( os.flags() & ios::basefield ) == ios::hex )... Funkcje testujące status (metody publiczne ios::) int good() const; zwraca wartość róŝną od zera, jeŝeli nie było błędu (wszystkie bity błędu są zerami) int bad() const; zwraca wartość róŝną od zera, aby pokazać wystąpienie powaŝnego błędu we/wy (co jest równowaŝne z ustawieniem flagi błędu badbit) int eof() const; zwraca wartość róŝną od zera, jeśli osiągnięty został koniec pliku (co jest równowaŝne z ustawieniem flagi błędu eofbit) int fail() const; zwraca wartość róŝną od zera, jeśli wystąpił błąd we/wy (ale nie koniec pliku) (co jest równowaŝne do ustawienia flagi błędu badbit lub failbit). Jeśli funkcja bad zwróci wartość 0, prawdopodobnie wystąpił naprawialny błąd formatowania lub konwersji. int rdstate() const; zwraca aktualny stan błędu (wartość flagi konkretnego błędu uzyskać moŝna przez zastosowanie operatora & (AND) do wartości zwracanej i którejś z masek: ios::goodbit, ios::eofbit, ios::failbit lub.ios::badbit) void clear( int nstate = 0 ); ustawia lub czyści flagi błędu strumienia zgodnie z wartościami bitów nstate (bity te moŝna ustawić stosując operator (OR) z maskami ios::goodbit, ios::eofbit, ios::failbit lub.ios::badbit) Status błędu operacji we/wy jest przechowywany wewnątrz klasy ios. Istnieją dwie metody na sprawdzenie statusu błędu we/wy: 1. MoŜna wywołać metodę rdstate (zwracającą aktualny stan błędu) i odczytać status błędu przez zastosowanie masek ios::goodbit (nie ma błędu), ios::eofbit (osiągnięto koniec pliku), ios::failbit (wystąpił błąd we/wy), ios::badbit (wystąpił powaŝny błąd we/wy). Przykład: if(file.rdstate() & ios::eofbit) { // koniec pliku 2. MoŜna uŝyć funkcji testujących status: bad, eof, fail, good Inne funkcje (metody publiczne ios::) delbuf rdbuf sync_with_stdio steruje powiązaniem usuwania streambuf z destrukcja ios pobiera obiekt streambuf związany ze strumieniem synchronizuje predefiniowane obiekty cin, cout, cerr, oraz clog ze standardowymi strumieniami wejścia/wyjścia systemu (stdin, stdout, stderr). Jeśli w programie występują operacje we/wy zaimplementowane

tie zgodnie ze standardem języka C i języka C++, wtedy naleŝy uŝyć tej metody. wiąŝe podany ostream z bieŝącym strumieniem. Operatory (metody publiczne ios::) operator void* dokonuje konwersji strumienia do wskaźnika, który moŝe być uŝyty jedynie do sprawdzania błędów zwraca wartość róŝną od 0 jeśli wystąpił błąd we/wy. operator! Manipulatory formatowania (publiczne stałe wyliczeniowe ios::) dec hex oct skipws left right powoduje, Ŝe kolejne pola interpretowane są w formacie dziesiętnym (domyślnie) powoduje, Ŝe kolejne pola interpretowane są w formacie szesnastkowym powoduje, Ŝe kolejne pola interpretowane są w formacie ósemkowym opuszczanie znaków pustych (spacji, tabulatorów, znaków końca wiersza) na wejściu wyrównanie do lewej wyrównanie do prawej internal dodaje znak wypełnienia za znakiem prowadzącym lub znakiem podstawy, ale przed wartością showbase wyświetla stałą numeryczną w formacie, który moŝe być przeczytany przez kompilator C++ showpoint pokazuje przecinek dziesiętny oraz pozostałe zera dla liczb zmiennoprzecinkowych uppercase wyświetla duŝe litery A do F w zapisze szesnastkowym oraz duŝe E w zapisie naukowym showpos pokazuje znak + dla wartości pozytywnych scientific wyświetla liczby zmiennoprzecinkowe w notacji naukowej unitbuf powoduje, Ŝe ostream::osfx opróŝnia bufory strumienia po kaŝdej operacji wstawiania (tj. operacje nie są buforowane) stdio powoduje, Ŝe ostream::osfx opróŝnia bufory strumieni stdout i stderr po kaŝdej operacji wstawiania (tj. operacje nie są buforowane) Manipulatory parametryzowane (wymagają iomanip.h) long setiosflags( long lflags ); ustawia flagi formatujące strumienia (flagi mogą być połączone operatorem (OR)) long resetiosflags( long lflags ); czyści flagi formatujące strumienia int setfill( int nfill ); int setprecision( int np ); int setw( int nw ); ustawia znak wypełnienia strumienia ustawia precyzję wypisywania liczb ustawia szerokość pola (waŝne tylko dla następnego pola) Manipulatory trybów otwarcia strumienia (publiczne stałe wyliczeniowe ios::) in out app ate trunc dozwolony odczyt ze strumienia dozwolone zapis do strumienia wskaźnik przesuwany na koniec strumienia przed wykonaniem kaŝdej operacji zapisu wskaźnik przesuwany na koniec strumienia po stworzeniu obiektu obsługującego strumień obcięcie istniejącego strumienia do rozmiaru 0 po stworzeniu obiektu obsługującego strumień binary ustawia tryb otwarcia pliku na tryb binarny (domyślnym trybem jest tryb tekstowy, zobacz ifstream::setmode) nocreate Jeśli plik nie istnieje, otwieranie pliku skończy się niepowodzeniem (zobacz ifstream::open)

noreplace Jeśli plik istnieje, otwieranie pliku skończy się niepowodzeniem, chyba, Ŝe plik jest otwierany do dopisywania lub jego wskaźnik jest ustawiany od razu na koniec (zobacz ifstream::open) Manipulatory określające pozycję odniesienia (publiczne stałe wyliczeniowe ios::) beg cur end względem początku pliku względem pozycji aktualnej względem końca pliku Klasa istream, oprócz metod odziedziczonych z klasy ios, zawiera metody słuŝące odczytywaniu danych wspólne dla wszystkich strumieni wejściowych. Metody te pozwalają odczytywać dane w postaci binarnej i tekstowej. Definicja klasy istream zawarta jest w pliku iostream.h. Do najwaŝniejszych metod tej klasy naleŝą: Metody klasy istream wczytuje jeden znak ze strumienia istream& get( char& znak) istream& getline( char* bufor, int max_dług, char delim = '\n' ); read( char bufor, int ilość_bajtów ) istream& seekg( streampos pos ) istream& seekg( streamoff off, ios::seek_dir dir ) wczytuje do bufora znaki ze strumienia dopóki: albo nie napotka znaku_końca, albo wczytanych zostało juŝ max_dług-1 znaków, albo napotkany został znak końca pliku. Znak delim jest wczytywany ze strumienia, ale nie jest wpisywany do bufora. wczytuje ciąg bajtów do bufora ustawia pozycję czytania ustawia pozycję czytania względem odniesienia istream& ignore( int dł_skok = 1, int delim = EOF ); wczytuje ze strumienia i nigdzie nie zapisuje dł skok znaków. Kończy działanie, jeśli natrafi na znak delim albo na koniec pliku. Jeśli delim = EOF (domyślne ustawienie), wtedy dochodzi do końca pliku. Znak delim jest pobierany ze strumienia. int gcount() const; zwraca liczbę wczytanych symboli dla ostatniej niesformatowanej operacji wejścia int peek(); zwraca bieŝący znak w strumieniu nie przesuwając wskaźnika połoŝenia przeskakuje znaki puste w strumieniu void eatwhite(); istream& putback( char ch ); W klasie tej jest zdefiniowany operator: Operator klasy istream >> operator pobrania/odczytu danych ze strumienia tekstowego zwraca znak do strumienia, przy czym musi to być znak, który uprzednio został wczytany Klasa ostream, oprócz metod odziedziczonych z klasy ios, zawiera metody słuŝące zapisywania danych wspólne dla wszystkich strumieni wyjściowych. Metody te pozwalają zapisywać dane w postaci binarnej i tekstowej. Definicja klasy ostream jest zawarta w pliku iostream.h. Do najwaŝniejszych metod tej klasy naleŝą: Metody klasy ostream put( char& znak) wysyła jeden znak do strumienia

write(char bufor, int ilość_bajtów) ostream& seekp( streampos pos ) ostream& seekp( streamoff off, ios::seek_dir dir ) W klasie ostream jest zdefiniowany operator Operator klasy ostream wysyła ciąg bajtów z bufora do strumienia ustawia połoŝenie pisania ustawia względne połoŝenie pisania << operator wysłania/zapisu danych do strumienia tekstowego oraz manipulatory: Manipulatory klasy ostream endl ends flush wstawia znak nowej linii i opróŝnia bufory wstawia znak null kończący ciąg znaków opróŝnia bufory strumienia W C++ moŝna definiować własne manipulatory formatujące. Wystarczy zdefiniować funkcję, której argumentem będzie strumień przekazany przez referencję, i która zwracać będzie referencję do strumienia. PoniŜej jest pokazany przykład manipulatora gwiazdki, który zastosowany do strumienia klasy ostream wypisuje do niego 4 gwiazdki. ostream &gwiazdki(ostream &wy) { ostream << "****"; return wy; cout << "Tu mamy 4 gwiazdki:" << gwiazdki; Operatory wstawiania i czytania ze strumienia (pobierania i umieszczania) Operatory wstawiania i czytania ze strumienia zaimplementowane w C++ potrafią radzić sobie ze wszystkimi standardowymi typami danych. Pozwalają przy tym uŝytkownikowi elastycznie formatować dane za pomocą funkcjami składowych klasy ios i manipulatorów (zdefiniowanymi w iomanip.h). Przykład: kod źródłowy wynik float f = 12.345 cout << f << "\n"; cout.setf(ios::scientific); cout << f << "\n"; cout.setf(ios::uppercase); cout << f << "\n"; 12.345 1.2345e+01 1.2345E+01 Przykład: wczytywanie danych z klawiatury i wydruk na ekranie // podejście proceduralne # include <stdio.h> void main( void ) { char znak; int x; long y; double z; char tekst[ 20 ]; scanf( "%c", &znak ); scanf( "%d", &x ); // podejście obiektowe # include <iostream.h> void main( void ) { char znak; int x; long y; double z; char tekst[ 20 ]; cin >> znak; // cin.get(znak); cin >> x;

scanf( "%ld", &y ); scanf( "%lf", &z ); scanf( "%19s", tekst ); cin >> y; cin >> z; cin >> tekst; //cin.getline(tekst,19) printf( "znak = %c \n", znak ); printf( "int = %d \n", x ); printf( "long = %d \n", y ); printf( "double = %f \n", z ); printf( "tekst = %s \n", tekst ); cout << "znak =" << znak << "\n"; cout << "int =" << x << "\n"; cout << "long =" << y << "\n"; cout << "double = " << z << "\n"; cout << "tekst = " << tekst << "\n"; W przypadku typów złoŝonych zdefiniowanych przez uŝytkownika operatory standardowe okazują się za słabe. Przy ich uŝyciu operacje na złoŝonych strukturach mają postać wielokrotnych wywołań, tak jak to się dzieje przy wypisywaniu pól złoŝonej struktury na stdout przy uŝyciu funkcji printf. Na szczęście język C++ pozwala w łatwy sposób przeciąŝać operatory, a co za tym idzie, pozwala zwiększyć ich moŝliwości. W ogólności prototyp funkcji operatora wstawiania lub czytania ze strumienia wygląda następująco: typ operatorx(strumień, obiekt); gdzie X reprezentuje przeciąŝany operator. W szczególności implementacja operatora pobierania >> musi odnosić się do strumienia wejściowego oraz musi dysponować adresem obiektu, do którego wpisywane będą wczytywane dane. Zaś implementacja operatora wstawiania << musi odnosić się do strumienia wyjściowego oraz moŝe dysponować tylko kopią obiektu. Oba przypadki najlepiej zobrazować na przykładzie. Niech Punkt będzie klasą zdefiniowaną jak niŝej: class Punkt { public: int x, y; Punkt(int _x, int _y){x=_x; y=_y; Punkt(){ ; Aby wypisać współrzędne jakiegoś obiektu klasy Punkt do standardowego strumienia wyjściowego moŝna posłuŝyć operatorem zaimplementowanym jak niŝej (implementację to moŝna wzbogacić np. o funkcje formatowania): ostream &operator<<(ostream &wy, Punkt obiekt) { wy << obiekt.x << "\n"; wy << obiekt.y << "\n"; return wy; Pierwszym argumentem w powyŝszym operatorze jest obiekt typu ostream (przekazany przez referencję). Dlatego moŝna uŝywać tego operatora dla wszystkich strumieni, które znajdują się w drzewie dziedziczenia klasy ostream (dotyczy to w szczególności cout). Drugim argumentem jest obiekt klasy Punkt (przekazany przez wartość). Operator zwraca strumień wyjściowy (referencję do tego samego strumienia, który podany został w argumencie), co pozwala uŝyć go sekwencyjnie: Punkt p1(1,-1), p2(2,-2) ; cout << p1 << p2; Implementacja operatora słuŝącego wczytywaniu jakiegoś obiektu klasy Punkt ze standardowego strumienia wejściowego moŝe wyglądać następująco: istream &operator>>(istream &we, Punkt &obiekt) { we >> obiekt.x; we >> obiekt.y ; return we;

Operator ten ma dwa argumenty przekazywane przez referencje. Pierwszym argumentem jest obiekt typu istream. Dlatego moŝna go uŝywać dla wszystkich strumieni, które znajdują się w drzewie dziedziczenia klasy istream (a w szczególności dla cin). Drugim argumentem jest obiekt, do którego, dzięki przekazanej referencji, będą wprowadzane wczytywane dane. Operator zwraca strumień wyjściowy (ten sam, który podany został w jego argumencie), co pozwala uŝyć go sekwencyjnie: Punkt p1, p2 ; cin >> p1 >> p2; W przedstawionym przykładzie wszystkie parametry, do których odnosiły się operatory, były parametrami publicznymi. Nie było więc Ŝadnych problemów z prawami dostępu. Jeśli jednak operator ma mieć dostęp do parametrów prywatnych jakiejś klasy, musi on być zadeklarowany w tej klasie jako friend. class Punkt { int x, y; Punkt(int _x, int _y){x=_x; y=_y; Punkt(){ public: friend istream &operator>>(istream &we, Punkt &obiekt); friend ostream &operator<<(ostream &wy, Punkt obiekt) ; Strumienie i pliki Tryby dostępu do plików i typy plików Proste programy napisane w C czy teŝ w C++ komunikują się z uŝytkownikiem poprzez standardowe urządzenia we/wy (wywołując funkcje printf, scanf lub wykonując operacje na strumieniach cin, cout). Jednak w bardziej złoŝonych przypadkach samo wprowadzanie danych z klawiatury i wyświetlanie ich na ekran monitora juŝ nie wystarcza. Koniecznym staje się archiwizacja danych, z moŝliwością ich przeglądania i modyfikacji. Zazwyczaj dane w systemach komputerowych są przechowywane w postaci plików zapisanych na dyskach. Dyski twarde typowych komputerów mają duŝo większe pojemności niŝ dostępna pamięć operacyjna. Stąd teŝ mogą one przechowywać znacznie większe ilości danych niŝ pomieściłaby pamięć operacyjna. Co więcej, dane zapisane na dyskach nie znikają w chwili wyłączenia zasilania. MoŜna je przenosić pomiędzy komputerami, moŝna je współdzielić pomiędzy róŝnymi systemami, moŝna je wymieniać pomiędzy programami. Podczas pracy z plikami nie trzeba zbytnio obciąŝać pamięci operacyjnej. Wystarczy do niej wczytać część danych z pliku, przetworzyć je, i, jeśli to konieczne, wczytać kolejną ich porcję. Aby moŝna było pliki tworzyć i z nich korzystać, zarówno w języku C jak i w C++ zaimplementowano szereg narzędzi funkcji umoŝliwiających odczytywanie, modyfikację i zapisywanie danych na dysku oraz zadeklarowano szereg zmiennych globalnych parametrów określających sposób wykonywanych operacji. W ogólności programy mogą sięgać do zasobów dyskowych na dwa sposoby: sekwencyjny i bezpośredni. Funkcje umoŝliwiające te dwa sposoby dostępu pozwalają zaimplementować praktycznie kaŝdą operację zapisu lub odczytu. Jednak zanim rozpocznie się jakiekolwiek przetwarzanie danych, sam plik powinien zostać otworzony, a po zakończeniu przetwarzania zamknięty (podobnie jak to jest z robieniem notatek w notesie. Jeśli chce się coś w notesie zapisać, najpierw naleŝy go otworzyć, a po dokonaniu zapisu, notes naleŝy zamknąć). Ponadto dane w plikach mogą mieć dwojaki charakter. MoŜna je traktować jako zestaw znaków (pliki tekstowe) lub teŝ jako zestaw bajtów (pliki binarne). O tym, w jakim trybie dostępu dane z pliku będą odczytywane, zapisywane bądź usuwane, decyduje sam programista. W części z przypadków dostęp do plików moŝe być zrealizowany dwojako: zarówno sekwencyjnie i jak i bezpośrednio. W takich razach do programisty naleŝeć będzie obowiązek zapewnienia poprawności wykonywania operacji zapisu i odczytu danych. Uwaga: Ilość na raz otwartych plików nie moŝe być nieskończona. Nie pozwalają na to systemy operacyjne (gdzie się określa maksymalną liczbę otwartych plików - w systemie DOS liczba ta jest ukryta w zmiennej środowiskowej FILES, zadeklarowanej w pliku CONFIG.SYS) oraz same biblioteki

wejścia/wyjścia (np. w Borland C++ maksymalną liczbę otwartych plików określa stała HANDLE_MAX, przy czym maksymalna liczba otwartych plików jest większa dla deskryptorów niŝ dla strumieni). Pliki o dostępie sekwencyjnym Dane muszą być odczytywane w tej samej kolejności, w jakiej zostały zapisane. Jest to tak jak przy zapisie i odczycie znaków wykonywanym na przesuwającej się taśmie w jakiej kolejności znaki zostały na taśmie zapisane, w takiej kolejności moŝna je odczytać. Podobnie teŝ jak w przypadku taśmy, w środek pliku sekwencyjnego nie moŝna wstawiać nowych danych - taśma jest juŝ zapisana i wstawianie danych w jej środek spowodowałoby zapisanie (utratę) starych danych. Aby wstawić coś w środek taśmy naleŝy właściwie stworzyć nową taśmę, przepisując na nią dane wszystkie dane, wstawiając po drodze w zadanym miejscu nowe dane. Pliki o dostępie bezpośrednim W ich przypadku dane mogą być odczytywane lub zapisywane w dowolnej kolejności i miejscu. Pewną analogią to tego typu dostępu do danych są płyty CD z muzyką. Jeśli interesuje nas jakiś utwór na płycie, wybieramy go, a sam odtwarzacz przeskakuje do wybranej pozycji, pomijając wszelkie inne utwory. Plikowe operacje we/wy w C Istnieją dwa mechanizmy słuŝące reprezentacji połączenia pomiędzy programem a plikiem. Są to: deskryptory plików i strumienie. Deskryptory plików reprezentowane są jako zmienne (obiekty) typu int, podczas gdy strumienie są reprezentowane przez zmienne (obiekty) typu FILE *. Zarówno deskryptory plików jak i strumienie mogą reprezentować połączenia z fizycznymi urządzeniami (jak terminal), jak równieŝ połączenia programowe (gniazdka do komunikacji z innymi procesami) czy teŝ połączenia z plikami dyskowymi. Deskryptory plików są uŝywane do wykonywania podstawowych operacji wejścia/wyjścia. Funkcje korzystające z deskryptorów pozwalają na wykonywanie jedynie prostych transferów bloków znaków. Deskryptory plików są uŝywane głównie w przypadkach, kiedy wykonywane mają być operacje sterujące, specyficzne dla danych urządzeń lub zaawansowane operacje wejścia/wyjścia (np. operacje nieblokujące). Wartości dla deskryptorów odpowiadających standardowym strumieniom stdin, stdout, stderr to, odpowiednio, 0, 1, 2. Strumienie dysponują zaś znacznie bogatszymi moŝliwościami. Operując na strumieniach moŝna formatować dane wejściowy jak i wyjściowe, zarówno dla pojedynczych znaków, jak i całych linii. Ponadto w przypadku uŝycia strumieni wszystkie związane z nimi pliki mogą być traktowane jednakowo (uwzględniając trzy style buforowania). PoniewaŜ strumienie są zaimplementowane z uŝyciem deskryptorów, jest moŝliwe pobranie deskryptora pliku ze strumienia i przeprowadzenie operacji niskiego poziomu na uzyskanym deskryptorze. MoŜna teŝ otworzyć połączenie za pomocą deskryptora pliku i następnie powiązać z nim strumień. Jednak do normalnego programowania jest zalecane uŝycie strumieni. Deskryptory plików wymagają większej wiedzy przy posługiwaniu się nimi, nie są tak elastyczne i mogą sprawiać więcej problemów przy przenoszeniu kodu programu niŝ strumienie. Strumienie bowiem są implementowane przez większość kompilatorów, zaś funkcje związane z deskryptorami plików są implementowane częściowo lub nawet wcale. Przetwarzanie plików (otwieranie, zapisywanie, odczytywanie i zamykanie) Przebieg niektórych operacji wykonywanych na plikach zaleŝy od wartości parametrów zadeklarowanych jako zmienne globalne (jak np. _fmode - zmienna całkowita globalna zdefinowana w stdlib.h czy teŝ zmienna globalna errno). W stdio.h jest zadeklarowana funkcja void perror(const char *s). SłuŜy ona do wypisania na stderr odpowiedniego komunikatu i jest wywoływana zazwyczaj po zakończeniu się jakiejś funkcji błędem. Ciąg znaków wypisywany przez perror składa się z dwóch części. Pierwszą jest ciąg znaków podany w jej argumencie (funkcja wstawia przecinek na jego koniec). Drugą jest systemowa wiadomość o błędzie (zakończona znakiem nowej linii). Systemowe

wiadomości są ukryte w tablicy sys_errlist. Zmienna errno, z której korzysta perror, jest uŝywana jako indeks w tej tablicy. Deskryptory: Funkcje operujące na deskryptorach są zdefiniowane w pliku nagłówkowym io.h. Aby z nich korzystać, wystarczy dołączyć do kody źródłowego tylko ten plik. Jeśli jednak w kodzie źródłowym pojawiają się pewne stałe (jak np. EOF), to naleŝy dodatkowo dołączyć plik stdio.h zawierający definicje tych stałych. Funkcje niskiego poziomu (operujące na deskryptorach) nie buforują danych ani nie posługują się danymi sformatowanymi. Ustawiają natomiast zmienną globalną errno, jeśli wystąpi błąd. Najczęściej uŝywanymi funkcjami niskiego poziomu są (zdefiniowane w io.h): funkcja int open ( char nazwa_pliku, int tryb_dostepu ) int close ( int handle ) int write ( int handle, void adres_bufora, unsigned ilosc_bajtow ) int read ( int handle, void adres_bufora, unsigned ilosc_bajtow ) int eof ( int handle ) long tell ( int handle ) int _commit( int handle ) long filelength ( int handle ) long lseek ( int handle, long przesuniecie, int odniesienie ) rola funkcji - otwiera plik zgodnie z trybem_dostepu (zwraca deskryptor otwartego pliku lub 1 gdy wystąpi błąd (kod błędu zapisany zostaje errno)) zamyka plik (zwraca 0 kiedy operacja powiodła się lub -1 gdy wystąpi błąd (kod błędu zapisany zostaje errno)) zapisuje dane do pliku (zwraca ilość zapisanych bajtów lub 1, gdy wystąpił błąd (kod błędu zapisany zostaje errno)) - czyta dane z pliku (danym przez handle) wpisując je pod wskazany adres (adres_bufora). Rozmiar danych określa argument ilosc_bajtow. sprawdza koniec pliku zwraca wskaźnik pozycji pliku o podanym deskryptorze (liczba bajtów począwszy od początku pliku) lub 1 w przypadku błędu. wymusza zapis pliku przez system operacyjny (jeśli operacja powiodła się, to zwraca 0, w przeciwnym wypadku zwraca 1 oraz ustawia errno) zwraca długość pliku związanego z deskryptorem, wyraŝoną w bajtach (jeśli zaś wystąpił błąd zwraca 1 oraz ustawia errno) - ustawia wskaźnik pozycji pliku (danym przez handle) na podanym miejscu (przesunięcie) względem miejsca odniesienia; zwraca 1 w przypadku błędu (dla plików nieprzewijalnych wartość jest zwracana nieokreślona) Składnia funkcji open: int open(const char *ścieŝka, int dostęp [, unsigned mod ] ); dostęp: argument, który moŝe być wynikiem połączenia wielu flag binarnym operatorem binarnej alternatywy (OR). Najczęściej są uŝywane flagi określające tryb dostępu czytania/pisania (O_xxxx). W ogólności flag tych moŝe być więcej. Jednak tylko jedna flaga definiująca tryb dostępu czytania/pisania moŝe wystąpić w argumencie dostęp. Pozostałe flagi mogą zaś wystąpić w dowolnej kombinacji. Jeśli tryb dostępu czytania/pisania nie jest zdefiniowany przez którąś z flag O_BINARY lub O_TEXT, plik otwarty zostanie godnie z trybem ustawionym w _fmode. (Znaczniki) Flagi odczytu/zapisu O_RDONLY otwarcie tylko do odczytu O_WRONLY otwarcie tylko do zapisu O_RDWR otwarcie do odczytu i zapisu Inne flagi (open, sopen) O_NDELAY (w Borland C++ nie uŝywane, zachowane dla zgodności z UNIX)

O_APPEND O_CREAT O_EXCL O_TRUNC dołączanie do końca pliku (jeśli ustawione, przed wskaźnik pozycji pliku ustawiony zostaje na jego koniec przed kaŝdą operacją zapisu stwórz i otwórz (nowy plik zostaje utworzony, jeśli dany plik nie istnieje; jeśli dany plik juŝ istnieje, nie ma efektu) (wyłączne otwarcie: uŝywane tylko z O_CREAT jeśli plik istnieje, jest zwracany błąd) otwarcie z obcięciem pliku do rozmiaru 0 (jeśli plik istnieje, jego długość jest obcinana do 0, atrybuty pliku pozostają natomiast niezmienione) Flagi trybu binarnego/testowego (fdopen, fopen, freopen, _fsopen, open, sopen) O_BINARY tryb binarny (nie ma Ŝadnych translacji, uŝywane do otwarcia pliku w trybie binarnym) O_TEXT tryb tekstowy (translacja znaków CR-LF, uŝywane do otwarcia pliku w trybie tekstowym) mod: argument, w którym określa się typ zezwolenia na otwarcie pliku. Podobnie jak poprzedni argumentu mod moŝe być wynikiem połączenia wielu flag binarnym operatorem binarnej alternatywy (OR). Najczęściej uŝywane flagi to flagi zezwoleń (S_Ixxx), choć mogą pojawić się i inne flagi (np. flagi współdzielenia SH_xxx). flagi zezwoleń S_IWRITE S_IREAD S_IREAD S_IWRITE zezwolenie do zapisu zezwolenie do odczytu zezwolenie do zapisu i odczytu Aby otworzyć plik w określonym trybie naleŝy: albo przypisać wartość do _fmode albo uŝyć funkcji open (lub sopen) z flagą O_CREAT oraz połączonych operatorem binarnej alternatywy flag: O_TRUNC, O_BINARY, O_TEXT. Przykładowo: open("xmp", O_CREAT O_TRUNC O_BINARY S_IREAD) otwiera plik xmp w trybie binarnym, tylko do odczytu (jeśli ten plik istnieje) oraz obcina jego długość do 0 bajtów. Strumienie: Funkcje wykonujące operacje wejścia/wyjścia wysokiego poziomu zostały zaprojektowane dla strumieni. Deklaracje tych funkcji zawiera plik nagłówkowy stdio.h. Podczas pracy z plikiem dyskowym jego połączenie ze strumieniem następuje przez otwarcie pliku. Do otwierania pliku słuŝy funkcja: FILE *fopen( const char *nazwa_pliku, const char *mod ); Typ FILE jest specjalną strukturą zdefiniowaną w pliku stdio.h. Typ ten słuŝy do deklarowania zmiennych będących wskaźnikami plików (wskaźniki te umoŝliwiają wykonywanie operacji na plikach). nazwa_pliku jest dopuszczalną nazwą pliku (nazwa moŝe zawierać pełną ścieŝkę dostępu do pliku). mod jest trybem otwarcia pliku (zestaw znaków ujętych w cudzysłowie). W poniŝszej tabeli wymieniono stosowane tryby otwarcia pliku wraz z krótkim ich opisem. Tryb Opis RównowaŜny zestaw flag w funkcji open r otwarcie (istniejącego) pliku do odczytu O_RDONLY w otwarcie pustego pliku do zapisu (jeśli O_WRONLY (zazwyczaj O_WRONLY plik istnieje, jego zawartość jest O_CREAT O_TRUNC) kasowana) a otwarcie pliku do rozszerzenia (jeśli plik O_WRONLY O_APPEND (zazwyczaj

nie istnieje, to jest utworzony nowy plik) r+ otwarcie (istniejącego) pliku do odczytu i zapisu w+ otwarcie pustego pliku do odczytu i zapisu (jeśli plik istnieje, jego zawartość jest kasowana) a+ otwarcie pliku do zapisu i rozszerzenia (jeśli plik nie istnieje, to jest utworzony nowy plik) b tryb binarny t tryb tekstowy c natychmiastowy zapis brak n zapis w chwilach wybranych przez system brak O_WRONLY O_CREAT O_APPEND) O_RDWR O_RDWR (zazwyczaj O_RDWR O_CREAT O_TRUNC) O_RDWR O_APPEND (zazwyczaj O_RDWR O_APPEND O_CREAT ) O_BINARY O_TEXT UŜycie opcji "a+" przy otwieraniu pliku powoduje, Ŝe znacznik końca pliku EOF jest usuwany zanim dokonana zostanie jakakolwiek operacja zapisu. Po wykonaniu operacji zapisu znacznik EOF jest wstawiany na koniec pliku. Z tego powodu opcja "a+" powinna być uŝywana do otwierania plików zakończonych znacznikiem CTRL-Z. Takiego przenoszenia znacznika EOF nie zapewnia natomiast opcja "a". W tym przypadku nowe dane dopisywane będą do pliku za znacznikiem EOF. Jednak obie opcje otwarcia pliku do rozszerzenia gwarantują, Ŝe istniejące dane w pliku nie zostaną nadpisane nowymi danymi. Bo niezaleŝnie od tego, gdzie znajdował się wskaźnik pliku (przesunięty na przykład funkcją fseek lub rewind), zapisywanie danych zawsze odbywać się będzie na końcu pliku (gdzie teŝ powracać będzie wskaźnik pliku w chwili zapisu). Najczęściej uŝywane funkcje we/wy: funkcja znaczenie tryb oczyszczenie błędu dla strumienia void clearerr( FILE *stream ) int fclose ( FILE strumien ) int fcloseall (void ) int feof ( FILE strumien ) int ferror( FILE *stream ); int fflush ( FILE strumien ) int flushall ( void ) int fgetc ( FILE strumien ) int fgetpos( FILE *stream, fpos_t *pos ); char fgets ( char tekst, int dlugosc, FILE strumien ) FILE fopen ( char nazwa_pliku, char rodzaj_operacji ) int fprintf ( FILE strumien, char format,... ) int fputc ( int znak, FILE strumien ) zamykanie strumienia zamykanie wszystkich strumienie za wyjątkiem stdin, stdout, oraz stderr test znacznika końca pliku test błędu strumienia opróŝnienie buforów strumieni opróŝnienie buforów wszystkich strumieni czytanie znaków ze strumienia (funkcja, działa podobnie do getc) odczytanie pozycji wskaźnika pliku czytanie ciągu znaków ze strumienia otwieranie strumienia zapisanie sformatowanych danych do strumienia zapisanie znaku do strumienia (funkcja, działa podobnie do putc) int fputs ( char tekst, FILE strumien ) zapisanie ciągu znaków do strumienia t int fread ( void adres, size_t rozm_bl, size_t il_blokow, FILE strumien ) odczytanie niesformatowanych danych ze strumienia FILE *freopen( const char *path, const char przekierowanie strumienia (zamknięcie t t t t b

*mode, FILE *stream ) int fscanf ( FILE strumien, char format,... ) int fseek ( FILE strumien, long przesuniecie, int wzgledem) int fsetpos( FILE *stream, const fpos_t *pos ); long ftell ( FILE strumien ) int fwrite ( void adres, size_t rozm_bl, size_t il_blokow, FILE strumien ) int getc( FILE *stream ) int getchar(void) strumienia stream i jego skojarzenie z nowo otwartym plikiem w trybie mode o nazwie path) czytanie sformatowanych danych ze strumienia przesunięcie wskaźnika pliku na daną pozycję ustawienie bieŝącej pozycji w pliku odczytanie bieŝącej pozycji w pliku zapisanie niesformatowanych danych do strumienia odczytanie znaku ze strumienia (makro, działa podobnie do fgetc) pobranie znaku ze strumienia stdin (makro, działa podobnie do fgetchar) char *gets( char *buffer ) odczytanie linii ze strumienia stdin t int printf( const char *format [, argument]... ) int putc( int c, FILE *stream ) int putchar(int c) zapisanie sformatowanych danych do strumienia stdout zapisanie znaku do strumienia (makro, działa podobnie do fputc) zapisanie znaku do strumienia stdout (makro, działa podobnie do fputchar) int puts( const char *string ) zapisanie linii do strumienia t void rewind( FILE *stream ) int scanf( const char *format [,argument]... ) void setbuf( FILE *stream, char *buffer ) int setvbuf( FILE *stream, char *buffer, int mode, size_t size ) int sprintf( char *buffer, const char *format [, argument]... ) int sscanf( const char *buffer, const char *format [, argument ]...) FILE *tmpfile( void ) char *_tempnam( char *dir, char *prefix ) przesunięcie wskaźnika pliku do początku odczytanie sformatowanych danych ze strumienia stdin sterowanie buforowaniem w strumieniu sterowanie buforowaniem w strumieniu i rozmiarem bufora zapisanie sformatowanych danych do bufora znaków (ciągu znaków) odczytanie sformatowanych danych z bufora znaków (ciągu znaków) utworzenie pliku tymczasowego wygenerowanie nazwy pliku tymczasowego int ungetc( int c, FILE *stream ) wstawienie znaku na powrót do strumienia t int vfprintf( FILE *stream, const char *format, va_list argptr ) int vprintf( const char *format, va_list argptr ) int vsprintf( char *buffer, const char *format, va_list argptr ) zapisanie sformatowanych danych do pliku zapisanie sformatowanych danych do stdout zapisanie sformatowanych danych do bufora t t t t t t t t Uwagi: 1. Domyślnie strumienie standardowe są związane z konsolą (klawiaturą i monitorem). Aby przekierować któryś ze strumieni stdin, stdout lub stderr do pliku lub innego urządzenia, naleŝy uŝyć funkcji freopen.