- •Учебное пособие
- •Введение
- •Объектно-ориентированный подход
- •Объектно-ориентированное программирование Абстрактные типы данных
- •Базовые принципы объектно-ориентированного программирования
- •Простейший ввод и вывод
- •Объект cout
- •Манипуляторы hex и oct
- •Другие манипуляторы
- •Объект cin
- •Операторы для динамического выделения и освобождения памяти (new и delete)
- •Базовые конструкции объектно-ориентированных программ Объекты
- •Понятие класса
- •Конструктор копирования
- •Конструктор explicit
- •Указатели на компоненты класса
- •Встроенные функции (спецификатор inline)
- •Организация внешнего доступа к локальным компонентам класса (спецификатор friend)
- •Вложенные классы
- •Static-члены (данные) класса
- •Указатель this
- •Компоненты-функции static и const
- •Proxi-классы
- •Параметры ссылки
- •Независимые ссылки
- •Практические приемы ограничения числа объектов класса
- •Наследование (производные классы)
- •Конструкторы и деструкторы при наследовании
- •Виртуальные функции
- •Абстрактные классы
- •Виртуальные деструкторы
- •Множественное наследование
- •Виртуальное наследование
- •Перегрузка функций
- •Перегрузка операторов
- •Перегрузка бинарного оператора
- •Перегрузка унарного оператора
- •Дружественная функция operator
- •Перегрузка оператора []
- •Перегрузка оператора ()
- •Перегрузка операторов new и delete
- •Преобразование типа
- •Явные преобразования типов
- •Преобразования типов, определенных в программе
- •Шаблоны Параметризированные классы
- •Передача в шаблон класса дополнительных параметров
- •Шаблоны функций
- •Совместное использование шаблонов и наследования
- •Шаблоны класса и friend
- •Некоторые примеры использования шаблона класса Реализация smart-указателя
- •Классы поддерживающие транзакции
- •Задание значений параметров класса по умолчанию
- •Пространства имен
- •Ключевое слово using как директива
- •Ключевое слово using как объявление
- •Псевдоним пространства имен
- •Организация ввода-вывода
- •Состояние потока
- •Строковые потоки
- •Организация работы с файлами
- •Организация файла последовательного доступа
- •Создание файла произвольного доступа
- •Основные функции классов ios, istream, ostream
- •Основы обработки исключительных ситуаций
- •Перенаправление исключительных ситуаций
- •Исключительная ситуация, генерируемая оператором new
- •Генерация исключений в конструкторах
- •Задание собственной функции завершения
- •Спецификации исключительных ситуаций
- •Задание собственного неожиданного обработчика
- •Иерархия исключений стандартной библиотеки
- •Стандартная библиотека шаблонов (stl) Общее понятие о контейнере
- •Общее понятие об итераторе
- •Категории итераторов
- •Основные итераторы
- •Вспомогательные итераторы
- •Операции с итераторами
- •Контейнерные классы Контейнеры последовательностей
- •Контейнер последовательностей vector
- •Контейнер последовательностей list
- •Контейнер последовательностей deque
- •Ассоциативные контейнеры
- •Ассоциативный контейнер multiset
- •Ассоциативный контейнер set
- •Ассоциативный контейнер multimap
- •Ассоциативный контейнер map
- •Адаптеры контейнеров
- •Адаптеры stack
- •Адаптеры queue
- •Адаптеры priority_queue
- •Пассивные и активные итераторы
- •Алгоритмы
- •Алгоритмы сортировки sort, partial_sort, sort_heap
- •Алгоритмы поиска find, find_if, find_end, binary_search
- •Алгоритмы fill, fill_n, generate и generate_n
- •Алгоритмы equal, mismatch и lexicographical_compare
- •Математические алгоритмы
- •Алгоритмы работы с множествами
- •Алгоритмы swap, iter_swap и swap_ranges
- •Алгоритмы copy, copy_backward, merge, unique и reverse
- •Примеры реализации контейнерных классов Связанные списки
- •Реализация односвязного списка
- •Реализация двусвязного списка
- •Реализация двоичного дерева
- •Литература
- •Вопросы по курсу ооп
- •220013, Минск, п.Бровки, 6.
Состояние потока
Потоки istream или ostream имеют связанное с ними состояние. В классе ios, базовом для классов istream и ostream, имеется несколько public функций, позволяющих проверять и устанавливать состояние потока:
inline int ios::bad() const { return state & badbit; }
inline int ios::eof() const { return state & eofbit; }
inline int ios::fail() const { return state & (badbit | failbit); }
inline int ios::good() const { return state == 0; }
Состояние потока фиксируется в элементах перечисления, объявленного в классе ios:
public:
enum io_state { goodbit = 0x00,
eofbit = 0x01,
failbit = 0x02,
badbit = 0x04 };
Кроме отмеченных выше функций в классе ios есть еще несколько функций, позволяющих прочитать (rdstate) и очистить (clear) состояние потока:
inline int ios::rdstate() const { return state; }
inline void ios::clear(int _i=0){ lock(); state = _i; unlock(); }
Так, если было установлено состояние ошибки, то попытка выполнить ввод/вывод будет игнорироваться до тех пор, пока не будет устранена причина ошибки и биты ошибки не будут сброшены функцией clear().
#include "iostream.h"
main()
{ int i, flags;
char c;
do{ cin >> i;
flags=cin.rdstate(); // чтение состояния потока cin
if(flags & ios::failbit)
{ cout << "error in stream"<< endl;
cin.clear(0); // сброс всех состояний потока
cin>>c; // удаление не int значения из потока
}
else cout << i<<endl;
} while(flags); // пока ошибка во входном потоке
return 0;
}
В приведенном примере функция cin.clear(0) выполняет сброс всех установленных бит ошибки. Если требуется сбросить, например, только badbit, то clear(ios::badbit). На примере ниже показано, что состояние потока может быть проанализировано также при работе с файлами.
#include "fstream.h"
#include "iostream.h"
main()
{ ifstream in("file");
int state;
char ss[10];
while(1)
{ state=in.rdstate(); // чтение состояния потока in (файла)
if (state) // ошибка в потоке
{ if(state&ios::badbit) cout<<"ошибка открытия файла"<<endl;
else if(state&ios::eofbit) cout<<"в файле больше нет данных"<<endl;
return 0;
}
else in >> ss;
}
}
Необходимо также отметить, что в классе ios выполнена перегрузка операции ! :
inline int ios::operator!() const { return state&(badbit|failbit); }
то есть операция ! возвращает ненулевое значение в случае установки одного из бит badbit или failbit, иначе нулевое значение, например:
if(!cin) cout << ”ошибка потока cin”<<endl; // проверка состояния
else cin>>i; // входного потока
Строковые потоки
Особой разновидностью потоков являются строковые потоки, представленные классом strstream:
class strstream : public iostream
{ public:
strstream();
strstream(char *s, streamsize n,
ios_base::openmode=ios_base::in | ios_base::out);
strstreambuf *rdbuf() const;
void freeze(bool frz=true);
char *str();
streamsize pcount() const;
};
Важное свойство класса strstream состоит в том, что в нем автоматически выделяется требуемый объем памяти для хранения строковых данных. Все операции со строковыми потоками происходят в памяти в специально выделенном для них буфере strstreambuf. Строковые потоки позволяют облегчить формирование данных в памяти. В примере демонстрируется ввод данных в буфер, копирование их в компоненту s класса string и их просмотр.
#include "strstrea.h"
class string
{ char s[80];
public:
string(char *S) {for(int i=0;s[i++]=*S++;);}
void see(){cout<<s<<endl;}
};
void fun(const char *s)
{ strstream st; // создание объекта st
st << s << ends; // вывод данных в поток (в буфер)
string obj(st.str()); // создание объекта класса string
st.rdbuf()->freeze(0); // освобождение памяти в буфере
obj.see(); // просмотр скопированной из буфера строки
}
main()
{ fun("1234");
}
Вначале создается объект st типа strstream. Далее при выводе переданной в функцию символьной строки в поток добавлен манипулятор ends, который соответствует добавлению ’\0’. Функция str() класса strstream обращается непосредственно к хранимой в буфере строке. Следует отметить, что при обращении к функии str() объект st перестает контролировать эту память и при уничтожении объекта память не освобождается. Для ее освобождения требуется вызвать функцию st.rdbuf()>freeze(0).
Далее в примере показывается проверка состояния потока, чтобы убедиться в правильности выполняемых операций. Это позволяет, например, легко определить переполнение буфера.
#include "strstrea.h"
void fun(const char *s,int n)
{ char *buf=new char[n]; // входной буфер
strstream st(buf,n,ios::in|ios::out); // связывание потока st и буфера byf
st << s << ends; // ввод информации в буфер
if(st.good()) cout << buf<<endl; // проверка состояния потока
else cerr<<"error"<<endl; // вывод сообщения об ошибке
}
main()
{ fun("123456789",5);
fun("123456789",15);
return 1;
}
В результате выполнения программы получим:
error
123456789
