[lekcja 9] Obsługa strumienia wejściowego Kurs C++ » Poziom 1

background image

Strona 1

[lekcja] Obsługa strumienia wejściowego | Kurs C++ » Poziom 1

2011-11-12 15:32:28

http://cpp0x.pl/kursy/Kurs-C++/Poziom-1/Obsluga-strumienia-wejsciowego/12

Darmowe kursy Online

»

Kurs C++

»

Poziom 1

Autor: Piotr Szawdyński

Obsługa strumienia wejściowego

[lekcja]

Rozdział 9. Omówienie obsługi standardowegowejścia za pomocą strumienia std::cin oraz przedstawieniesposobu walidacji wczytywanychdanych.

Idąc małymi krokami do przodu nadszedł czas na obsługę strumienia wejściowego, czyli mówiąc prościej na wczytywanie danych.

Zagadnienie to o ile jest stosunkowo proste do zrozumienia to wymaga ono sporej otoczki związanej z kontrolowaniem błędnie

wprowadzonych danych. Zanim jednak dojdziemy do tych zagadnień zajmijmy się najpierw podstawami.

Wczytywaniedanych

Wczytywanie danych do zmiennych odbywa się za pomocą strumienia std::cin. Aby móc wczytać dane znajdujące się na standardowym

wejściu, należy wykorzystać do tego celu operator >>. Wczytanie danych wygląda więc następująco:

C/C++

std

::

cin

>>

nazwa_zmiennej

;

W powyższy sposób możemy wczytywać wszystkie podstawowe typy danych - poczynając od liczb całkowitych, przechodząc przez liczby

rzeczywiste oraz znaki, a kończąc na tekście . W niniejszym rozdziale skupimy się tylko i wyłącznie na wczytywaniu liczb całkowitych i

rzeczywistych . Tekstem zajmiemy się w dalszej części kursu.

Rozpatrzmy teraz następujący przykład:

C/C++

#include <iostream>

int

main

()

{

int

a

;

float

b

;

std

::

cout

<<

"Podaj liczbe calkowita: "

;

std

::

cin

>>

a

;

std

::

cout

<<

"Podaj liczbe rzeczywista: "

;

std

::

cin

>>

b

;

std

::

cout

<<

"Liczba a = "

<<

a

<<

std

::

endl

;

std

::

cout

<<

"Liczba b = "

<<

b

<<

std

::

endl

;

return

0

;

}

Powyższy program zapyta się użytkownika o podanie dwóch liczb. Pierwszą z nich ma być liczba całkowita, a drugą liczba rzeczywista .

Jeśli użytkownik będzie posłuszny, program wyświetli przykładowo następującą treść:

Podaj liczbe calkowita: 13

Podaj liczbe rzeczywista: 16.6

Liczba a = 13

Liczba b = 16.6

Problem zaczyna się pojawiać jednak wtedy, gdy mamy do czynienia z Yeti, czyli kimś kto niekoniecznie chce używać programu zgodnie z

wolą programisty.

Sprawdzaniepoprawnościwprowadzonychdanych

Wczujmy się przez chwilę w złośliwego użytkownika i zacznijmy działać tak jak on - wprowadźmy więc zamiast liczby literę. Ja

wprowadziłem literę a i otrzymałem następujący wynik na ekranie:

Podaj liczbe calkowita: a

Podaj liczbe rzeczywista: Liczba a = 4273126

Liczba b = 3.21401e-039

Jak widać już na pierwszy rzut oka program zrobił dwie złe rzeczy. Pierwsza - nie wczytał liczby całkowitej; druga - pominął wczytywanie

liczby rzeczywistej. Jako programiści powinniśmy zadać jednak pytanie: czy udało się wczytać dane?. Dopiszmy więc dwa nowe

wiersze do programu po każdym wczytywaniu danych:

C/C++

std

::

cout

<<

"Czy udalo sie wczytac? "

<<

std

::

cin

.

good

() <<

std

::

endl

;

std

::

cout

<<

"Czy cos nawalilo? "

<<

std

::

cin

.

fail

() <<

std

::

endl

;

Po dokonaniu powyższej zmiany program będzie wyglądał tak:

C/C++

background image

Strona 2

[lekcja] Obsługa strumienia wejściowego | Kurs C++ » Poziom 1

2011-11-12 15:32:28

http://cpp0x.pl/kursy/Kurs-C++/Poziom-1/Obsluga-strumienia-wejsciowego/12

#include <iostream>

int

main

()

{

int

a

;

float

b

;

std

::

cout

<<

"Podaj liczbe calkowita: "

;

std

::

cin

>>

a

;

std

::

cout

<<

"Czy udalo sie wczytac? "

<<

std

::

cin

.

good

() <<

std

::

endl

;

std

::

cout

<<

"Czy cos nawalilo? "

<<

std

::

cin

.

fail

() <<

std

::

endl

;

std

::

cout

<<

"Podaj liczbe rzeczywista: "

;

std

::

cin

>>

b

;

std

::

cout

<<

"Czy udalo sie wczytac? "

<<

std

::

cin

.

good

() <<

std

::

endl

;

std

::

cout

<<

"Czy cos nawalilo? "

<<

std

::

cin

.

fail

() <<

std

::

endl

;

std

::

cout

<<

"Liczba a = "

<<

a

<<

std

::

endl

;

std

::

cout

<<

"Liczba b = "

<<

b

<<

std

::

endl

;

return

0

;

}

W programie pojawiły się dwa nowe zapisy: std::cin.good() oraz std::cin.fail(). good() i fail() są metodami należącymi do

strumienia std::cin. Za pomocą nich możemy odczytać stany strumienia. Są nimi odpowiednio: czy wczytywanie się powiodło (dla

metody good()), oraz czy wystąpiły jakieś błędy (dla metody fail()).

Posiadając wiedzę na temat tego czy udało się wczytać poprawnie dane czy też nie - będziemy mogli podjąć w przyszłości odpowiednie

działania. Na chwilę obecną nie potrafisz jednak sterować przebiegiem programu dlatego też powrócimy do tego zagadnienia ponownie,

gdy będziesz miał odpowiednią wiedzę .

Opis działaniastrumieniawejściowego

Skoro nauczyliśmy się już korzystać ze strumienia wejściowego w podstawowym wymiarze - przyjrzyjmy się teraz jego działaniu.

Wyobraźmy więc sobie, że początkowo strumień jest pusty. Wysyłamy następnie żądanie:

"daj mi liczbę całkowitą"

(czyli:

std::cin>>liczba). Strumień jest pusty, więc nie można z niego pobrać danych, a więc użytkownik musi wprowadzić nowe dane do

strumienia. Wprowadźmy teraz do strumienia następujące dane:

12345, 321. Czy 2+2 wynosi 4?

Po wciśnięciu klawisza ENTER dane te trafiają do bufora strumienia wejściowego, z którego następnie odczytywane są dane. Po

wczytaniu liczby w buforze strumienia wejściowego zostaną następujące dane:

, 321. Czy 2+2 wynosi 4?

Co się teraz stanie, gdy zechcemy wczytać kolejną liczbę? Strumień stwierdzi, że pierwszym znakiem w strumieniu jest znak

,

, który

nie jest liczbą, a więc nie zostanie wczytana liczba. Operacja wczytywania się nie powiedzie , a flaga błędu zostanie ustawiona.

Białe znaki

Białymi znakami nazywamy te, które nie mają swojej reprezentacji wizualnej, a istnieją w tekście . Białe znaki to: spacja, enter i

tabulacja.

Strumień, a białe znaki

Gdy używamy strumienia std::cin>> białe znaki są pomijane. Tak więc gdyby w buforze strumienia nie znajdował się przecinek, tylko

biały znak - strumień by go po prostu pominął i przeszedł do kolejnego znaku. W konsekwencji druga operacja wczytywania liczby

powiodłaby się, a w strumieniu pozostałyby dane:

. Czy 2+2 wynosi 4?

Czyszczeniezawartości strumieniawejściowego

Jeśli chcemy mieć większą kontrolę nad strumieniem wejściowym to powinniśmy czyścić jego zawartość przed każdym wczytaniem

danych. Aby to zrobić musimy wywołać dwie metody strumienia std::cin. Pierwszą z nich jest std::cin.clear(), która czyści flagi błędu.

Drugą metodą jest std::cin.sync(), która czyści bufor strumienia. Kod, który wyczyści zawartość bufora będzie wyglądał następująco:

C/C++

std

::

cin

.

clear

()

;

std

::

cin

.

sync

()

;

Problemy z czyszczeniemstrumieniapod Linuksem

Jeżeli jesteś szczęśliwym posiadaczem Linuksa i uczysz się programowania właśnie pod nim, niestety możesz doświadczyć nieprzyjemnej

sytuacji, w której wiersz

std

::

cin

.

sync

()

;

po prostu nie zadziała. Rozwiązaniem powyższego problemu może być użycie metody

ignore

, dostępnej w strumieniu std::cin. Wspomnianą metodę należy użyć w następujący sposób:

C/C++

//tu wczytanie danych ze strumienia za pomoc

ą

std::cin>>

std

::

cin

.

clear

()

;

std

::

cin

.

ignore

(

1000

,

'\n'

)

;

background image

Strona 3

[lekcja] Obsługa strumienia wejściowego | Kurs C++ » Poziom 1

2011-11-12 15:32:28

http://cpp0x.pl/kursy/Kurs-C++/Poziom-1/Obsluga-strumienia-wejsciowego/12

Architektserwisu: Piotr Szawdyński

© Wszelkieprawa zastrzeżone2005-2011

Powyższy zapis ignoruje do 1000 znaków znajdujących się w strumieniu wejściowym. Jeżeli w strumieniu wejściowym zostanie napotkany

znak nowego wiersza '\n' proces ignorowania znaków zostanie zakończony. Proces ignorowania znaków nie zostanie jednak zakończony

gdy w buforze nie będzie więcej znaków do odczytania. Jeżeli chcesz używać tej techniki to należy czyścić strumień wejściowy po

każdym wczytaniu danych by uniknąć ewentualnych problemów technicznych związanych ze sposobem działania tej metody.

Jeżeli nie chcesz uzależniać się od konkretnej stałej liczbowej , która mówi ile maksymalnie znaków może zostać pominiętych, możesz

użyć poniższego zapisu:

C/C++

#include <limits>

int

liczba

;

std

::

cin

>>

liczba

;

bool

bCzySukces

=

std

::

cin

.

good

()

;

std

::

cin

.

clear

()

;

std

::

cin

.

ignore

(

std

::

numeric_limits

<

std

::

streamsize

>::

max

()

,

'\n'

)

;

//(...) tu dalsza cz

ęść

programu

//INFO: zmienna bCzySukces zawiera informacj

ę

czy udało si

ę

wczyta

ć

dane

Powyższy kod spowoduje wczytanie liczby, a następnie pominie wszystkie znaki znajdujące się w buforze aż do napotkania znaku

przejścia do nowej linii '\n'.

Pamiętaj, że użycie

std::numeric_limits

wymaga dodatkowo dołączenia biblioteki

limits

na początku programu.

Pamiętaj, że:

Efekt działania zapisów

cin

.

clear

()

;

oraz

cin

.

sync

()

;

będzie możliwy do zaobserwowania tylko i wyłącznie po wprowadzeniu

błędnych danych do programu. Przykładem błędnych danych jest wprowadzanie tekstu zamiast liczb.

Zadanie domowe

Napisz program, który wczyta trzy liczby rzeczywiste , a na końcu programu je wszystkie wypisze . Zadbaj o to, by bufor strumienia

wejściowego był za każdym razem czyszczony. Wynik końcowy powinien również zawierać informacje czy wczytanie danej liczby się

powiodło.

Przykładowedane wejściowe

13.3

tak 123

33.22nie

Przykładowedane wyjściowe

Liczba pierwsza to: 13.3. Wczytano? 1.

Liczba druga liczba to: 0. Wczytano? 0.

Liczba trzecie liczba to: 33.22. Wczytano? 1.

Wskazówka

Informacje o poprawnym (albo niepoprawnym) wczytaniu danych należy przechować w dodatkowych zmiennych typu bool.

Wszystkieteksty są chronioneprawami autorskimi. Kopiowanielub rozpowszechnianietreści poza niniejszymserwisem jest

zabronione.

Powyższe ograniczenie nie dotyczy autora opracowania, któremu przysługuje prawo do rozpowszechnianiawłasnego tekstu wedle własnego uznania.


Wyszukiwarka

Podobne podstrony:
[lekcja 6] Obsługa strumienia wyjściowego Kurs C++ » Poziom 1
[lekcja 11] Operacje porównania Kurs C++ » Poziom 1
[lekcja 12] Operacje logiczne Kurs C++ » Poziom 1
[lekcja 7] Przestrzeń nazw std Kurs C++ » Poziom 1
[lekcja 1] Wybieramy środowisko pracy Kurs C++ » Poziom 1
[lekcja 10] Operacje matematyczne Kurs C++ » Poziom 1
[lekcja 3] Uruchamiamy pierwszy program Kurs C++ » Poziom 1
[lekcja 18] Tablice jednowymiarowe Kurs C++ » Poziom 2
[lekcja 22] Pętla for Kurs C++ » Poziom 2
[lekcja 11] Operacje porównania Kurs C++ » Poziom 1
[lekcja 20] Funkcje, a słowo kluczowe return Kurs C++ » Poziom 2
[lekcja 13] Instrukcja warunkowa if else Kurs C++ » Poziom 1
[lekcja 15] Pętla do while Kurs C++ » Poziom 2
[lekcja 17] Funkcje pierwsze starcie Kurs C++ » Poziom 2
[lekcja 16] Pseudolosowe liczby całkowite Kurs C++ » Poziom 2
[lekcja 2] Podstawy programowania teoria i terminologia Kurs C++ » Poziom 1
[lekcja 21] Losowanie bez powtórzeń Kurs C++ » Poziom 2
[lekcja 19] Przekazywanie tablic jednowymiarowych do funkcji Kurs C++ » Poziom 2
[lekcja 4] Podstawy programowania w C++ Kurs C++ » Poziom 1

więcej podobnych podstron