Потоки
ввода-вывода.
Содержание статьи:
Вступление.
Консольный
ввод/вывод.
Форматирование.
Потоковый
ввод/вывод пользовательских типов.
Файловый
ввод/вывод.
Вступление.
к началу статьи
Всем доброго времени суток. Если вы посмотрите на предыдущие статьи, то
заметите что в них использовалась как С-шная система ввода/вывода, так
и ввод/вывод С++. Они ни в чём не уступают друг другу по
функциональности, хотя, на мой взгляд, последней пользоваться удобнее
(например в силу того, что она объектно-ориентированная). В этой статье
я попытаюсь убедить Вас в этом.
Консольный
ввод/вывод.
к началу статьи
Когда запускается программа на С++, автоматически
создается несколько
стандартных потоков – cin (стандартный ввод с клавиатуры),
cout (стандартный вывод на экран). Есть еще 2 стандартных потока, но в
данной статье мы их не будем рассматривать (cerr и clog –
потоки для ошибок). Чтобы начать ими пользоваться нужно всего лишь
подключить заголовочный файл iostream.h. Теперь можно рассмотреть
простенький пример: |
int i; cout<<"Input i : "; cin>>i; cout<<"i = "; cout<<i;
|
В нем мы просто вводим
число, а затем
выводим его на экран. Хочу обратить Ваше внимание на то, что потоки
используют перегруженные операторы >> и <<,
которые возвращают стандартный поток. Это приводит к одному интересному
эффекту: |
int i(1),j(2); cout<<i<<" "<<j;
|
Данная конструкция
работает следующим
образом: сначала бинарный оператор << применяется к cout
и переменной i (тем самым осуществляется вывод i на экран), после чего
возвращается временная копия потока. Теперь уже она инициирует второй
вызов оператора <<. Тот же саамы принцип используется
и в потоке ввода.
Форматирование.
к началу статьи
Формат выводимых данных задается с помощью достаточно большого числа
флагов, но мы остановимся на наиболее полезных. Да, чуть не забыл,
флаги устанавливаются с помощью метода setf(fmtflags) и сбрасываются
методом unsetf(fmtflags) (это методы потоковых классов).
oct, dec, hex
– вывод чисел в восьмеричной, десятеричной и
шестнадцатеричной системах счисления соответственно. Рассмотрим
предыдущий пример, слегка изменив его: |
int i; cout<<"Input i : "; cin>>i; cout.setf( ios::oct ); cout<<"i = "<<i<<endl;
|
Теперь если Вы введете
8, то увидите на
экране “i = 10”.
uppercase
– вывод символа е (при выводе чисел в научной нотации) и x
(при выводе чисел в шестнадцатеричной системе счисления) в верхнем
регистре.
showpos
– если установлен, то перед положительными числами в
десятеричной системе счисления будет ставиться знак +.
left, right
– выравнивание.
showpoint
– появление десятичной точки и последующих нулей при выводе
вещественных чисел. Например: |
float i; cout<<"Input i : "; cin>>i; cout.setf( ios::showpoint ); cout<<"i = "<<i<<endl; getch();
|
showbase
– вывод основания системы счисления.
scientific,
fixed – установка
вывода чисел в научной нотации или с фиксированной точкой. |
float i; cout<<"Input i : "; cin>>i; cout.setf( ios::scientific ); cout<<"i = "<<i<<endl; cout.setf( ios::fixed ); cout<<"i = "<<i<<endl;
|
boolalpha
– булевые значения выводятся как true или false.
Установку нескольких флагов можно объединить в один вызов setf(): |
cout.setf( ios::showbase | ios::showpos );
|
Так же для
форматирования используются
следующие методы потоков – width(), precision() и fill().
width()
– задаёт число знаков отводимое под выводимое число.
precision()
– задает сколько знаков после запятой будет выводиться у
вещественных чисел
fill()
– задает какими символами будут заполняться неиспользованные
позиции в строке вывода.
Сейчас рассмотрим пример, и все будет ясно как день: |
cout.setf( ios::fixed ); cout.width( 10 ); cout.precision( 3 ); cout.fill( '%' ); cout.setf( ios::right ); cout<<12.3456<<endl; cout.width( 10 ); cout.precision( 3 ); cout.fill( '%' ); cout.setf( ios::left ); cout<<12.3456<<endl;
|
на экран выведется: |
%%%%12.345 12.345%%%%
|
Потоковый
ввод/вывод пользовательских типов.
к началу статьи
Хоть стандартные потоки и позволяют выводить только встроенные типы,
эту проблему можно с легкостью обойти. Надо просто для класса, который
мы хотим выводить в поток, определить дружественный оператор
<<, у которого первый параметр и возвращаемое значение
– поток, второй параметр - объект данного класса: |
include <iostream.h> include <conio.h>
class cVector{ public: float x,y; cVector( void ){x=1;y=2;} friend ostream &operator<<( ostream& , cVector & ); };
ostream &operator<<( ostream & ostr , cVector &v ){ cout<<"x:"<<v.x<<endl; cout<<"y:"<<v.y<<endl; return( ostr ); }
int main( void ){ cVector v;
cout<<v<<endl;
getch(); return 0; }
|
Файловый
ввод/вывод.
к началу статьи
Работа с файловыми потоками практически ничем не отличается от работы с
любым другим потоком. Как всегда есть класс входного потока –
ifstream, есть класс выходного потока – ofstream (на самом
деле есть ещё универсальный файловый поток ввода/вывода - fstream).
Для открытия потока используется метод open(), в который передаются
путь к файлу и режим. Например: |
ifstream istr; istr.open( “file.txt” , ios::binary );
|
В этом примере мы
открыли файл file.txt в
двоичном режиме (по умолчанию все файлы открываются в текстовом
режиме), вот так: |
ifstream istr; istr.open( “file.txt” );
|
Надеюсь Вы не забыли
подключить файл
fstream.h?
Теперь рассмотрим основные методы для работы с файловыми потоками:
close()
– закрытие потока.
eof()
– возвращает true, если был достигнут конец файла.
get(char)
– читает символ из файла
put(char)
– записывает символ в файл
read( char
*str , int
size ) – читает буфер
str длиной size из файла
write( char
*str , int
size ) – записывает
буфер str длиной size в файл
seekg( int
offset , seekdir ) –
устанавливает смещение указателя считывания в зависимости от seekdir.
seekp( int
offset , seekdir ) –
устанавливает смещение указателя считывания в зависимости от seekdir.
seekdir может принимать значения ios::beg, ios::cur, ios::end. Таким
образом что бы передвинуть указатель считывания в конец файла, а затем
снова в начало нужно сделать следующее: |
ifstr.seekg( 0 , ios::end ); //смещение от конца = 0, //переходим в конец файла ifstr.seekg( 0 , ios::cur ); //смещение от текущего положения = 0, //соответственно просто топчемся на месте ifstr.seekg( 0 , ios::beg ); //смещение от начала = 0, //соответственно переходим в начало файла
|
tellg()
– позиция указателя считывания.
tellp()
– позиция указателя записи.
Вот пожалуй
все, что я хотел рассказать о потоках ввода/вывода, и самое грустное,
что это, наверное, последняя статья по С++ :(. Самая простая часть
Вашего пути позади – синтаксис усвоен, осталось только
научиться эффективно его использовать. Но вместо точки хочу поставить
жирное многоточие – наверное мы с Вами встретимся на уроках
по Java’e а может быть я организую несколько уроков по C :)
Мы только в начале нашего великого пути!
к началу
статьи
ЗЫ: связаться
со мной можно по почте dodonov_a_a (__AT) inbox.ru
Смежные вопросы:
Урок 1. Основы классов.
Урок 2. Конструкторы
копий, оператор присваивания.
Урок 3. Перегрузка
функций.
Урок 4. Друзья.
Урок 5. Перегрузка
операторов.
Урок 6. Наследование
(часть первая).
Урок 7. Наследование
(часть вторая).
Урок 8. Шаблоны.
|