Программирование >>  Унарные и бинарные операторы 

1 ... 28 29 30 [ 31 ] 32 33 34 ... 37


Потоки ввода-вывода

Всякая программа (а мы их знаем уже несколько десятков) должна добывать откуда-то данные и посылать их во внешний мир. Нам уже знакомы операторы л , объекты cin и cout, файлы. Настало время получить более систематическое и детальное представление о вводе-выводе в С++.

Прежде всего нужно сказать о потоках ввода-вывода (streams) - последовательностях байтов (символов), создаваемых самыми разными источниками. Всякие ввод и вывод данных связаны с потоками. Когда, например, числа или строки вводятся с клавиатуры, то каждое нажатие клавиши посылает в поток один символ. За поступающими символами следит объект cin, как бы притаившийся в засаде. До определенного момента он безучастен, но стоит появиться в потоке символу перевода строки, посылаемому нажатием клавн-вш Enter, как объект начинает действовать. Причем действия его зависят от того, что стоит справа от оператора . Посмотрим, например, как работает программа из листинга 12.1, в которой объект cin читает с клавиатуры целые числа.

Листинг 12.1

#include <iostream> int main(){ int x=l: while (X != 0){

cout Введите число endl:

cin x;

cout Вы ввели: X endl:

He путать с потоками еыполнеиия (threads).

Потоки ввода-вывода 213

return 0: }

Объект cin следит за входным потоком, куда с клавиатуры поступают символы. Как только появляется символ перевода строки, объект пытается найти среди введенных символов тс, что можно превратить в число. Первым делом он отбрасывает все введенные пробелы, символы табуляции и прочую дребедень . Далее он проверяет все идущие подряд символы 1,9,0 до тех пор, пока не встретится пробел (символ табуляции и т. д.), после чего последовательность символов превращается в целое число и записывается в переменную X.

Пусть, например, с клавиатуры ввели пять пробелов, затем два символа, 1 и 2, и нажали клавишу Enter. Тогда объект cin пошлет в переменную х число 12. Подчеркнем: символы 1 и 2 кодируются числами 49 и 50 соответственно, но объект cin преобразует их в число 12, потому что так велит ему инструкция cin х. Если бы вместо целочисленной переменной х стояла строка или другой объект, объект cin вел бы себя иначе.

А теперь посмотрим, что будет, если ввести вместо цифры какую-нибудь букву, например q. Эксперимент показывает, что программа срывается , бесконечно сооб1цая, что введена единица, то есть значение, присвоенное X еще до входа в 1шкл.

Ясно, что никакого ввода на самом деле не происходит, а случилась ошибка, с которой программа не в состоянии справиться. Чтобы помочь ей, нужно знать, что объект cin умеет следить за состоянием потоков с помощью собственной функции cin. fail О. Ее значение равно true после удачного преобразования и false - в противном случае. Очевидно, ввод буквы q вместо числа привел поток в нерабочее состояние, о чем и должна



жем, последовательности символов или строки. Программа, показанная в листинге 12.3, предназначена для ввода двух строк с клавиатуры. Листинг 12.3

#include <iostreani> #include <string> using namespace std: int main(){ string si.52: Вводим Come together Cin si: cin s2;

cout si endl; Come cout s2 endl: Together }

Ecjui ввести Come, нажать клавишу Enter, a затем ввести together и снова нажать клавишу Enter, то, как и ожидается, в строке si окажется Come, а в с троке s2 - together. По если сразу набрать всю фразу Согпе together и нажать клавишу Enter - резулт>тат будет тем же самым. Дело в том, что, встретив пробел после Come, пс1:)вый оператор прекратит работу, оставив в строке si слово Come. Второй же оператор уже не нуждается во вводе с клавиатуры, потому что в потоке остались символы, которые вывалятся в строку s2 без всякого нашего участия!

Функции ввода-вывода

Операторы и позволяют решить только самые основные задачи ввода-вывода. Более деликатные задачи решаются с помощью собственных функций классов istream и ostream, которым принадлежат объекты cin и cout соответственно.

Мы уже знаем, что операторы и пропускают ненужные символы - пробелы, табуляции и т. д. Но, допустим, что перед нами стой г задача узнать, какими

сообщить функция Cin. fa 11 (). Получив известие об этом, программа должна вывести поток из состояния fai 1 (это делает функция cin.clearO) и затем продолжить ввод. Исправленная версия программы ввода чисел показа-па в листинге 12.2.

Листинг 12.2

#include <1ostream> #include <fstream> irt main(){ int X: char chl: do{ -

cout Введи число\п :

Cin X;

if (cin.fail()){ Cin.clearO: cin Chl:

cout Это не число endl:

else{

cout Прочитано число : cout X endl:

} while(x !=0): return 0: }

Заметим, что функция cin.clearO не очищает поток от всех введенных символов. Она лишь выводит его из нерабочего состояния. Инструкция ci п chl забирает из потока один символ. Если до iiero в потоке есть enie символы, не равные цифрам, поток опять попа/ют в состояние fai 1, снова будет выведен из него - и так до тех пор, пока вредных символов не останется. Если, наприме!), вместо числа ввести десять символов q, то программа десять раз выведет на экран фразу Это нечиаю , прежде чем будет готова к приему правильных цифр.

Естественно, лишние символы выплеснутся нз потока и в случае, когда вводятся не целые числа, а, ска-



216 Глава 12. Ввод-вывод

числами кодируются эти символы. Ясно, что оператор для этого не годится.

Тут, видимо, нужно читать каждый символ отдельно, для чего в классе 1 stream есть специальная функция cin.get(ch),гдech - переменная типа char. Но бедавтом, что символы поступают с клавиатуры по меньшей мере парами, потому что при любом вводе нажимается клавиша Enter. Значит, придется воспользоваться функцией ci п .getl ine( s. n), которой можно указать число читаемых символов.

В принципе, функция getlineCchar *s. int n) пре/ща-значена для чтения строки, то есть последовательности символов, завершаемых символом \п (он вводится при нажатии клавиши Enter). После ввода символы оказываются в массиве s, причем символ перевода строки отбрасывается и заменяется нулевым символом \0. Параметр п задает количество читаемых символов. Если п, например, равен трем, с клавиатуры считаются два символа, а на месте третьего в массиве s окажется символ АО .

Вспомнив о нашей задаче - показать на экране число, которым кодируется тот или иной символ, легко понять, что параметр п должен быть равен двум. Программа, решающая эту задачу, показана в листин ге 12.4.

Листинг 12.4

#include <iostream> using namespace std: int main(){ char ch[2]; while(!cin.eof()){ cin.getline(ch.2):

cout static cast<int>(ch[0]) endl:

return 0: J

Мы уже применяли ее в главе 6 для чтения символов из файла.

Манипуляторы 217

Крошечная эта программа содержит, тем не менее, много нового. Начнем с того, как поместятся символы в массиве s, состоящем из двух переменных char. Если ввести с клавиатуры символ и нажать клавишу Enter, то Б потоке окажутся два символа - тот, что нам нужен, и символ перевода строки \п. Символ \п функция getl ine() отбросит, записав вместо него символ \0. Значит, нужный нам символ окажется на нулевом месте (s[0]), а завершающий ноль - на первом. Чтобы показать число, которым кодируется символ s[0], его нужно превратить в целочисленную переменную. Иначе cout воспримет его как переменную char и повторит введенный символ на экране.

Нам осталось понять, как программа завершит работу. Легко догадаться, что это произойдет, когда функция cin.eof () возвратит значение true, то есть когда в поток попадет символ конца ввода. Этот символ нельзя получить нажатием одной клавиши. Чтобы он попал в поток, следует одновременно нажать клавиши Ctrl и 2, то есть Ctrl+Z.

Манипуляторы

у объектов, управляющих потоками ввода-вывода, есть не только собственные функции, но и так называемые манипуляторы. Один из них - endl - хорошо нам знаком. Манипуляторы выглядят как символы, но на самом деле - это функции, принимающие ссылку на поток, изменяющие его и возвращаюпще ссылку на поток но цепочке . Так, например, манипулятор endl при работе с объектом cout принимает поток, вставляет туда символ конца строки и затем выбрасывает все символы потока на экран.

Манипуляторы часто используются вместо функций, потому что они лучше и естественней выглядят.



1 ... 28 29 30 [ 31 ] 32 33 34 ... 37

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика