background image

Podstawy programowania. Wykład 15 –wejście /wyjście 

Małgorzata Nalbach-Moszyńska 

 

   

15.

 

Wejście / wyjście ............................................................................................................ 2

 

15.1

 

Informacje ogólne .................................................................................................... 2

 

15.2

 

Wyjście standardowe ............................................................................................... 2

 

15.3

 

Podstawowa obsługa plików .................................................................................... 2

 

15.3.1

 

Otwieranie pliku - fopen ...................................................................................... 3

 

15.3.2

 

Zamykanie pliku - fclose ...................................................................................... 3

 

15.4

 

Przykłady funkcji obsługi wyjścia ........................................................................... 4

 

15.4.1

 

Funkcja printf /fprintf ........................................................................................... 4

 

15.4.2

 

Funkcja puts /fputs ............................................................................................... 5

 

15.4.3

 

Funkcja putchar/putc ............................................................................................ 6

 

15.5

 

Wejście ..................................................................................................................... 6

 

15.5.1

 

Wejście formatowane scanf/fscanf ....................................................................... 6

 

15.5.2

 

Czytanie po znaku getchar/getc ............................................................................ 7

 

15.5.3

 

Czytanie tablicy znaków ...................................................................................... 8

 

 

background image

Podstawy programowania. Wykład 15 –wejście /wyjście 

Małgorzata Nalbach-Moszyńska 

 

 

15. 

 Wejście / wyjście  

 

15.1 Informacje ogólne 

W odróżnieniu od innych języków programowania mechanizmy obsługi wejścia / wyjścia w 
C i C++ nie są zawarte w standardzie języka – ich obsługą zajmują się funkcje z bibliotek 
dołączanych na początku programu. 
 
 
#include <stdio.h>  
 
Biblioteka funkcji wejścia / wyjścia. 
 

15.2 Wyjście standardowe 

W  zasadzie  standard  C  nie  definiuje  czegoś  takiego  jak  ekran  i  klawiatura  -  mowa  w  nim 
o standardowym  wyjściu i standardowym  wejściu.  Zazwyczaj  jest  to  właśnie  ekran  i 
klawiatura,  ale  nie  zawsze.  W  szczególności  użytkownicy  Linuksa  lub  innych  systemów 
uniksowych  mogą  być  przyzwyczajeniu  do  przekierowania  wejścia/wyjścia  z/do  pliku  czy 
łączenie  komend  w  potoki  (ang.  pipe).  W  takich  sytuacjach  dane  nie  są  wyświetlane  na 
ekranie, ani odczytywane z klawiatury. 
 

15.3 Podstawowa obsługa plików 

Istnieją dwie metody obsługi czytania i pisania do plików: 

•  wysokopoziomowa, 
•  niskopoziomowa. 

Nazwy funkcji z pierwszej grupy zaczynają się od litery "f" (np. fopen(), fread(), fclose()), a 
identyfikatorem pliku jest wskaźnik na strukturę typu FILE. Owa struktura to pewna grupa 
zmiennych, która przechowuje dane o danym pliku - jak na przykład aktualną pozycję w nim. 
Szczegółami nie musisz się przejmować, funkcje biblioteki standardowej same zajmują się 
wykorzystaniem struktury FILE, programista może więc zapomnieć, czym tak naprawdę jest 
struktura FILE i traktować taką zmienną jako "uchwyt", identyfikator pliku. 
Druga grupa to funkcje typu read(), open(), write() i close(). 
Podstawowym identyfikatorem pliku jest liczba całkowita, która jednoznacznie identyfikuje 
dany plik w systemie operacyjnym. Liczba ta w systemach typu UNIX jest 
nazywana deskryptorem pliku. 
Należy pamiętać, że nie wolno nam używać funkcji z obu tych grup jednocześnie w 
stosunku do jednego, otwartego pliku, tzn. nie mo
żna najpierw otworzyć pliku za 
pomoc
ą fopen(), a następnie odczytywać danych z tego samego pliku za pomocą read(). 
Czym różnią się oba podejścia do obsługi plików? Otóż metoda wysokopoziomowa ma swój 
własny bufor, w którym znajdują się dane po odczytaniu z dysku a przed wysłaniem ich do 
programu użytkownika. W przypadku funkcji niskopoziomowych dane kopiowane są 
bezpośrednio z pliku do pamięci programu. W praktyce używanie funkcji 
wysokopoziomowych jest prostsze a przy czytaniu danych małymi porcjami również często 
szybsze. 
 

background image

Podstawy programowania. Wykład 15 –wejście /wyjście 

Małgorzata Nalbach-Moszyńska 

 

15.3.1 

Otwieranie pliku - fopen 

FILE *fopen(const char *filename, const char *mode);

 

 

Opis 
Funkcja fopen() otwiera plik, którego nazwa podana jest w pierwszym argumencie. Drugim 
jest łańcuch znaków zwierający litery oznaczające sposób otwarcia pliku: 

•  "r" - otwiera plik do czytania 
•  "r+" - otwiera plik do czytania i nadpisywania (aktualizacja) 
•  "w" - otwiera plik do nadpisywania (zamazuje starą treść) 
•  "w+" - otwiera plik do nadpisywania i czytania 
•  "a" - otwiera plik do dopisywania (jeśli plik nie istnieje, to jest tworzony) 
•  "a+" - otwiera plik do dopisywania i odczytu (jeśli plik nie istnieje, to jest tworzony) 
•  "t" - otwiera plik w trybie tekstowym 
•  "b" - otwiera plik w trybie binarnym 

 
Litery można ze sobą łączyć, np. "rwb" albo "wt". 
 
Wartość zwracana 

Wskaźnik do pliku 

(FILE *)

 lub 

NULL

, gdy pliku nie udało się otworzyć. 

 

Przykład użycia 

#include <stdio.h>

 

int

 main

()

 

{

 

    FILE 

*

=

 fopen

(

"notatki.txt"

,

 

"r"

)

;

 

        

// otwiera plik do odczytu (musi istniec)

 

    

if

 

(

==

 NULL

)

 

    

{

 

        perror

(

"Nie udalo sie otworzyc pliku notatki.txt"

)

;

 

        

return

 

1

;

 

    

}

 

    puts

(

"Plik otwarty pomyslnie!"

)

;

 

    fclose

(

f

)

;

 

    

return

 

0

;

 

}

 

 

15.3.2 

Zamykanie pliku - fclose 

 

Deklaracja 
int fclose (FILE *plik); 
Opis 
Funkcja fclose() zamyka otwarty funkcją fopen() plik. Jeśli plik nie zostanie zamknięty, a 
program zakończy działanie, zmiany nie zostaną zapisane. 

background image

Podstawy programowania. Wykład 15 –wejście /wyjście 

Małgorzata Nalbach-Moszyńska 

 

 

   Wartość zwracana 
Funkcja zwraca 0, a w przypadku błędu EOF. 
 
  Przykład użycia 

#include <stdio.h> 
 
int main() 

    FILE *f = fopen("plik.txt", "w");/* otworzenie pliku do zapisu 

 */ 

    if (f) 
    { 
        fputs("Przyklad z podrecznika C na Wikibooks!", f); 
/* zapisanie do pliku */ 
        fclose(f);   /* zamknięcie pliku i zapisanie zmian */ 
    } 
    return 0; 

 
 

15.4 Przykłady funkcji obsługi wyjścia 

15.4.1 

Funkcja printf /fprintf 

 
printf(format, argument1, argument2, ...); 
fprintf(plik, format, argument1, argument2, ...); 
 
Format to napis ujęty w cudzysłowy, który określa ogólny kształt, schemat tego, co ma być 
wyświetlone. Format jest drukowany tak, jak go napiszemy, jednak niektóre znaki specjalne 
zostaną w nim podmienione na co innego.  
Przykładowo, znak specjalny \n jest zamieniany na znak nowej linii ( Zmiana ta następuje w 
momencie kompilacji programu i dotyczy wszystkich literałów napisowych. Nie jest to jakaś 
szczególna własność funkcji printf(). ).  
Natomiast procent jest podmieniany na jeden z argumentów. Po procencie następuje 
specyfikacja, jak wyświetlić dany argument. W tym przykładzie %i (od int) oznacza, że 
argument ma być wyświetlony jak liczba całkowita. W związku z tym, że znaki \ i % mają 
specjalne znaczenie, aby wydrukować je, należy użyć ich podwójnie: 
Plik – to wskaźnik do struktury typu FILE – musi być otwarty do czytania przez fopen. 
 
Przykład: 

int

 i 

=

 

500

;

 

 

printf

(

"Liczbami całkowitymi są na przykład %i oraz %i.

\n

"

,

 

1

,

 i

)

 

wypisze 

Liczbami całkowitymi są na przykład 1 oraz 500. 

 
Najczęstsze użycie printf(): 

background image

Podstawy programowania. Wykład 15 –wejście /wyjście 

Małgorzata Nalbach-Moszyńska 

 

•  printf("%i", i); gdy i jest typu int; zamiast %i można użyć %d 
•  printf("%f", i); gdy i jest typu float lub double 
•  printf("%c", i); gdy i jest typu char (i chcemy wydrukować znak) 
•  printf("%s", i); gdy i jest napisem (typu char*) 

 

15.4.2 

Funkcja puts /fputs 

int puts(const char *s); 
int fputs (const char *s, FILE *stream); 
Funkcja wysyła na standardowe wyjście/ plik napis s, a następnie (tylko funkcja puts) znak 
nowej linii. 
 
Funkcja zwraca liczbę nieujemną w przypadku sukcesu. W przypadku błędu zwraca wartość 
EOF. 
 
W ten sposób, nasz pierwszy program moglibyśmy napisać w ten sposób: 

 

#include <stdio.h>

 

  

 

int

 main

()

 

 

{

 

   

puts

(

"Hello world!"

)

;

 

   

return

 

0

;

 

 

}

 

W swoim działaniu funkcja ta jest w zasadzie identyczna do wywołania:  

printf("%s\n", argument); 

jednak prawdopodobnie będzie działać szybciej. Jedynym jej mankamentem może być fakt, 
ż

e zawsze na końcu podawany jest znak przejścia do nowej linii. Jeżeli jest to efekt 

niepożądany (nie zawsze tak jest) należy skorzystać z funkcji fputs() opisanej niżej lub 
wywołania printf("%s", argument); 

background image

Podstawy programowania. Wykład 15 –wejście /wyjście 

Małgorzata Nalbach-Moszyńska 

 

 

15.4.3 

Funkcja putchar/putc 

putchar (char znak); 
putc(char znak, FILE *plik); 
 
Funkcje putchar() i putc() służy do wypisywania pojedynczych znaków. Przykładowo, jeżeli 
chcielibyśmy napisać program wypisujący w prostej tabelce wszystkie liczby od 0 do 99 
moglibyśmy to zrobić tak: 
 

 

#include <stdio.h>

 

  

 

int

 main

(

void

)

  

 

{

 

   

int

 i 

=

 

0

;

 

   

for

 

(

;

 i

<

100

;

 

++

i

)

  

   

{

 

     

/* Nie jest to pierwsza liczba w wierszu */

 

     

if

 

(

%

 

10

)

  

     

{

 

       

putchar

(

' '

)

;

 

     

}

 

     

printf

(

"%2d"

,

 i

)

;

 

     

/* Jest to ostatnia liczba w wierszu */

 

     

if

 

((

%

 

10

)

==

9

)

  

     

{

 

       

putchar

(

'

\n

'

)

;

 

     

}

 

   

}

 

   

return

 

0

;

 

 

}

 

15.5 Wejście 

15.5.1 

Wejście formatowane scanf/fscanf 

 
int scanf(const char *format, ...); 
int fscanf(FILE *stream, const char *format, ...); 
 
Funkcje odczytują dane zgodnie z podanym formatem. Funkcja scanf odczytuje dane ze 
standardowego wejścia (tj. stdin); fscanf ze strumienia podanego jako argument. 

background image

Podstawy programowania. Wykład 15 –wejście /wyjście 

Małgorzata Nalbach-Moszyńska 

 

 

#include <stdio.h>

 

  

 

int

 main 

()

 

 

{

 

   

int

 liczba 

=

 

0

;

 

   

printf

 

(

"Podaj liczbę: "

)

;

 

   

scanf

 

(

"%d"

,

 

&

liczba

)

; /* parametr liczba jest wyjściowy dla scanf */

 

   

printf

 

(

"%d*%d=%d

\n

"

,

 liczba

,

 liczba

,

 liczba

*

liczba

)

;

  

   

return

 

0

;

 

 

 

Funkcja scanf() zwraca liczbę poprawnie wczytanych zmiennych lub EOF, jeżeli nie ma już 
danych w strumieniu lub nastąpił błąd. 
 Załóżmy dla przykładu, że chcemy stworzyć program, który odczytuje po kolei liczby i 
wypisuje ich 3 potęgi. W pewnym momencie dane się kończą lub jest wprowadzana 
niepoprawna dana i wówczas nasz program powinien zakończyć działanie. Aby to zrobić, 
należy sprawdzać wartość zwracaną przez funkcję scanf() w warunku pętli: 
 

 

#include <stdio.h>

 

  

 

int

 main

(

void

)

 

 

{

 

   

int

 n

;

 

   

while

 

(

scanf

(

"%d"

,

 

&

n

)

==

1

)

  

   

{

 

     

printf

(

"%d

\n

"

,

 n

*

n

*

n

)

;

 

   

}

 

   

return

 

0

;

 

 

}

 

 

15.5.2 

Czytanie po znaku getchar/getc 

 
int getchar(void); 
int getc(FILE *file); 
 
Funkcja getchar() / getc czyta znak ze standardowego wejścia/strumienia file i go stamtąd 
usuwa. Wywołanie getchar() jest równoważne wywołaniu getc(stdin). 
W wielu przypadkach dane mogą być buforowane, przez co wysyłane są do programu 
dopiero, gdy bufor zostaje przepełniony lub na wejściu jest znak przejścia do nowej linii. Z 
tego powodu po wpisaniu danego znaku należy nacisnąć klawisz enter, aczkolwiek trzeba 
pamiętać, że w następnym wywołaniu zostanie zwrócony znak przejścia do nowej linii. Gdy 
nastąpił błąd lub nie ma już więcej danych funkcja zwraca wartość EOF (która ma jednak 
wartość logiczną 1 toteż zwykła pętla while (getchar()) nie da oczekiwanego rezultatu): 
 
 
 
 

background image

Podstawy programowania. Wykład 15 –wejście /wyjście 

Małgorzata Nalbach-Moszyńska 

 

 

#include <stdio.h>

 

  

 

int

 main

(

void

)

 

 

{

 

   

int

 c

;

 

   

while

 

((

=

 

getchar

())

!=

EOF

)

 

{

 

     

if

 

(

c

==

' '

)

 

{

 

       c 

=

 

'_'

;

 

     

}

 

     

putchar

(

c

)

;

 

   

}

 

   

return

 

0

;

 

 

 

Ten program wczytuje dane znak po znaku i zamienia wszystkie spacje na znaki podkreślenia. 
Może wydać się dziwne, że zmienną c zdefiniowaliśmy jako trzymającą typ int, a nie char. 
Właśnie taki typ (tj. int) zwraca funkcja getchar() i jest to konieczne ponieważ wartość EOF 
wykracza poza zakres wartości typu char (gdyby tak nie było to nie byłoby możliwości 
rozróżnienia wartości EOF od poprawnie wczytanego znaku).  
 

15.5.3 

Czytanie tablicy znaków 

char *fgets(char *str, int size, FILE *stream); 

 

Opis 
Funkcja fgets() czyta kolejne znaki ze strumienia stream i umieszcza je w tablicy znakowej 
wskazywanej przez str. Czytanie przerywa, gdy przeczyta size - 1 znaków, natrafi na koniec 
pliku lub znak końca linii (znak ten jest zapisywany do str). Na końcu fgets() dopisuje znak 
'\0'. 
 
Istnieje funkcja gets, ale nie sprawdza rozmiaru bufora. Nie wolno jej używać!! 
 
Wartość zwracana 
Wartością funkcji fgets(str, size, stream) jest str w przypadku sukcesu. W przypadku błędu 
lub natrafienia na koniec pliku przed przeczytaniem jakiegokolwiek znaku wartością funkcji 
jest NULL. 
 
Uwagi 
Funkcja fgets() nie odróżnia sytuacji osiągnięcia końca pliku od błędu odczytu pliku. Jeśli 
potrzebne jest ich rozróżnienie użyj funkcji 

feof()

 lub 

ferror()

 
Przykład użycia 

#include <stdio.h>

 

  

int

 main

()

 

{

 

    

int

 i

;

 

    

const

 

int

 max_n

=

 

50

;

 

background image

Podstawy programowania. Wykład 15 –wejście /wyjście 

Małgorzata Nalbach-Moszyńska 

 

    

const

 

int

 linie

=

 

2

;

 

    

char

 napis

[

max_n

+

1

]

,

 

*

result

;

 

    

for

 

(

=

 

1

;

 i 

<=

 linie

;

 

++

i

)

  

    

{

 

        result 

=

 

fgets

 

(

napis

,

 max_n

,

 stdin

)

;

    

    

/* czytamy ze standardowego wejścia */

 

        

if

 

(

result 

!=

 NULL

)

  

        

{

 

            

printf

 

(

"%d %s"

,

 i

,

 napis

)

;

 

            

if

 

(

feof

 

(

stdin

))

 

                

printf

 

(

"

\n

%d koniec pliku

\n

"

,

 i

)

;

 

        

}

 

        

else

 

            

printf

 

(

"

\n

%d blad odczytu

\n

"

,

 i

)

;

 

    

}

 

    

return

 

0

;

 

}

 

Program wczytuje 2 linie i, w przypadku wystąpienia, sygnalizuje koniec pliku lub błąd 
odczytu. 
 
Napisz program, który wczytuje dane z pliku tekstowego wierszami i wyświetla je na ekranie.  
Do przechowywania napisów zastosuj tablice typu char.  
Przykładowe rozwiązanie: 

 
#include <stdio.h> 
const int DLWIERSZA = 80; /* 80 znakow w wierszu */ 
/* program bedzie dzielil dluzsze wiersze */ 
 
int main() { 
char nazwaPliku[40]; 
FILE *f; 
char wiersz[DLWIERSZA+1]; /* +1 dla konca napisu */ 
printf( "Nazwa pliku: "); 
scanf("%s", &nazwaPliku); 
printf("Otwieram plik: %s\n",nazwaPliku ); 
f = fopen(nazwaPliku, "r"); /* Otworz plik tekstowy do czytania */ 
if (!f) { 
fprintf(stderr, "Nie moge otworzyc %s.\n", nazwaPliku); 
return 1; 

/* Wczytuj wiersze do napotkania konca pliku. */ 
while (fgets(wiersz, DLWIERSZA+1,f)) { 
      printf( "%s", wiersz); 
                                   } 
printf( "*** KONIEC PLIKU ***\n"); 
return 0;