- •Сборник методических указаний к лабораторным работам
- •Цель работы
- •Теоретические сведения
- •Основные окна ide
- •Редактор текста
- •Список задач
- •Окно решения
- •Окно свойств
- •Контрольные вопросы
- •Управление потоком кода.
- •1. Цель работы
- •2. Теоретические сведения
- •If (условие) оператор1; else оператор2
- •3. Порядок выполнения работы
- •4. Задание на работу
- •6. Контрольные вопросы
- •1. Цель работы
- •2. Теоретические сведения
- •Управление динамической памятью с помощью new и delete
- •3. Порядок выполнения работы
- •4. Задание на работу
- •Функции без возвращаемого значения (процедуры)
- •Функции, возвращающие значение
- •Функции с параметрами.
- •Формальные и фактические параметры
- •Перегрузка функций
- •Значения параметров по умолчанию
- •Использование библиотек функций
- •3. Порядок выполнения работы
- •4. Требования к оформлению отчета
- •5. Задание на работу
- •Порядок выполнения работы
- •Требования к оформлению отчета
- •Задание на работу
- •Форматный ввод
- •Пример работы с форматным выводом
- •3. Порядок выполнения работы
- •4. Требования к оформлению отчета
- •5. Задание на работу
- •6. Контрольные вопросы
- •1. Цель работы
- •2. Теоретические сведения
- •Сортировка пузырьком
- •Сортировка вставками
- •«Быстрая» сортировка
- •Обход деревьев
- •3. Порядок выполнения работы
- •4. Требования к оформлению отчета
- •5. Задание на работу
- •Поиск в ширину
- •Поиск в глубину
- •Алгоритм Беллмана-Форда
- •Алгоритм Дейкстры
- •Int X; // координаты центра
- •Int r; // значение радиуса
- •Int X; // координаты центра
- •Int r; // значение радиуса
- •Int X; // координаты центра
- •Int r; // значение радиуса
- •Порядок выполнения работы.
- •Требования к отчету.
- •Варианты заданий.
- •Контрольные вопросы.
- •Порядок выполнения работы.
- •Требования к отчету.
- •Варианты заданий.
- •Контрольные вопросы.
- •Цели и задачи работы
- •Теоретические положения.
- •Вывод встроенных типов
- •Вывод пользовательских типов
- •Ввод встроенных типов
- •Состояния потока
- •Ввод пользовательских типов
- •Форматирование
- •Класс ios
- •Связывание потоков
- •Поля вывода
- •Состояние формата
- •Вывод целых
- •Выравнивание полей
- •Вывод плавающих чисел.
- •Манипуляторы
- •Стандартные манипуляторы ввода-вывода
- •Члены ostream
- •Члены istream
- •Файлы и потоки
- •Закрытие потоков
- •Строковые потоки
- •Буферизация
- •Ввод-вывод в с
- •Порядок выполнения работы.
- •Требования к отчету.
- •Варианты заданий.
- •Функции-шаблоны
- •Шаблоны классов
- •"Интеллигентный указатель"
- •Задание свойств класса
- •Порядок выполнения работы.
- •Требования к отчету.
- •Варианты заданий.
- •Порядок выполнения работы.
- •Требования к отчету.
- •Варианты заданий.
- •Порядок выполнения работы.
- •Требования к отчету.
- •Варианты заданий.
- •Порядок выполнения работы.
- •Требования к отчету.
- •Варианты заданий.
- •Порядок выполнения работы.
- •Требования к отчету.
- •Варианты заданий.
- •Контрольные вопросы. Список литературы
Строковые потоки
Как было показано, поток может быть привязан к файлу, т.е. массиву символов, хранящемуся не в основной памяти, а, например, на диске. Точно так же поток можно привязать к массиву символов в основной памяти.Например, можно воспользоваться выходным строковым потоком ostrstreamдля форматирования сообщений, не подлежащих немедленной печати:
char* p = new char[message_size];
ostrstream ost(p,message_size);
do_something(arguments,ost);
display(p);
С помощью стандартных операций вывода функция do_something может писать в поток ost, передавать ost подчиняющимся ей функциям и т.п. Контроль переполнения не нужен, поскольку ost знает свой размер и при заполнении перейдет в состояние, определяемое fail(). Затем функция display может послать сообщение в "настоящий" выходной поток. Такой прием наиболее подходит в тех случаях, когда окончательная операция вывода предназначена для записи на более сложное устройство, чем традиционное,ориентированное на последовательность строк, выводное устройство.Например, текст из ost может быть помещен в фиксированную область на экране.
Аналогично, istrstream является вводным строковым потоком,читающим из последовательности символов, заканчивающейся нулем:
void word_per_line(char v[], int sz)
/*
печатать "v" размером "sz" по одному слову в строке
*/
{
istrstream ist(v,sz); // создать istream для v
char b2[MAX]; // длиннее самого длинного слова
while (ist>>b2) cout <<b2 << "\n";
}
Завершающий нуль считается концом файла.
Строковые потоки описаны в файле <strstream.h>.
Буферизация
Все операции ввода-вывода были определены без всякой связи с типом файла, но нельзя одинаково работать со всеми устройствами без учета алгоритма буферизации. Очевидно, что потоку ostream, привязанному к строке символов, нужен не такой буфер, как ostream, привязанному к файлу. Такие вопросы решаются созданием во время инициализации разных буферов для потоков разных типов. Но существует только один набор операций над этими типами буферов, поэтому в ostream нет функций, код которых учитывает различие буферов. Однако, функции, следящие за переполнением и обращением к пустому буферу, являются виртуальными.Это хороший пример применения виртуальных функций для единообразной работы с эквивалентными логически, но различно реализованными структурами, и они вполне справляются с требуемыми алгоритмами буферизации.Описание буфера потока в файле <iostream.h> может выглядеть следующим образом:
class streambuf { // управление буфером потока
protected:
char* base; // начало буфера
char* pptr; // следующий свободный байт
char* gptr; // следующий заполненный байт
char* eptr; // один из указателей на конец буфера
char alloc; // буфер, размещенный с помощью "new"
//...
// Опустошить буфер:
// Вернуть EOF при ошибке, 0 - удача
virtual int overflow(int c = EOF);
// Заполнить буфер:
// Вернуть EOF в случае ошибки или конца входного потока,
// иначе вернуть очередной символ
virtual int underflow();
//...
public:
streambuf();
streambuf(char* p, int l);
virtual ~streambuf();
int snextc() // получить очередной символ
{
return (++gptr==pptr) ? underflow() : *gptr&0377;
}
int allocate(); // отвести память под буфер
//...
};
Подробности реализации класса streambuf приведены здесь только для полноты представления. Не предполагается, что есть общедоступные реализации, использующие именно эти имена. Обратите внимание на определенные здесь указатели, управляющие буфером; с их помощью простые посимвольные операции с потоком можно определить максимально эффективно (и причем однократно) как функции-подстановки. Только функции overflow() и underflow() требует своей реализации для каждого алгоритма буферизации, например:
class filebuf : public streambuf {
protected:
int fd; // дескриптор файла
char opened; // признак открытия файла
public:
filebuf() { opened = 0; }
filebuf(int nfd, char* p, int l)
: streambuf(p,l) { /* ... */ }
~filebuf() { close(); }
int overflow(int c=EOF);
int underflow();
filebuf* open(char *name, ios::open_mode om);
int close() { /* ... */ }
//...
};
int filebuf::underflow() // заполнить буфер из "fd"
{
if (!opened || allocate()==EOF) return EOF;
int count = read(fd, base, eptr-base);
if (count < 1) return EOF;
gptr = base;
pptr = base + count;
return *gptr & 0377; // &0377 предотвращает размножение знака
}
За дальнейшими подробностями обратитесь к руководству по реализации класса streambuf.
