![]() Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Решение. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include stdafx.h#include
Чтение информации из текстового файла Для того чтобы прочитать информацию из текстового файла, необходимо описать переменную типа ifstream. После этого нужно открыть файл для чтения с помощью оператора open. Если переменную назвать F, то первые два оператора будут такими:
После открытия файла в режиме чтения из него можно считывать информацию точно так же, как и с клавиатуры, только вместо cin нужно указать имя потока, из которого будет происходить чтение данных. Например, для чтения данных из потока F в переменную a, оператор ввода будет выглядеть так: F> > a;
Два числа в текстовом редакторе считаются разделенными, если между ними есть хотя бы один из символов: пробел, табуляция, символ конца строки. Хорошо, когда программисту заранее известно, сколько и какие значения хранятся в текстовом файле. Однако часто известен лишь тип значений, хранящихся в файле, при этом их количество может быть различным. Для решения данной проблемы необходимо считывать значения из файла поочередно, а перед каждым считыванием проверять, достигнут ли конец файла. А поможет сделать это функция F.eof(). Здесь F - имя потока функция возвращает логическое значение: true или false, в зависимости от того достигнут ли конец файла. Следовательно, цикл для чтения содержимого всего файла можно записать так:
//организуем для чтения значений из файла, выполнение ПРОВЕРКА ПОТОКА Каждый поток (istream или ostream) имеет ассоциированное с ним состояние, и обработка ошибок и нестандартных условий осуществляется с помощью соответствующей установки и проверки этого состояния. Поток может находиться в одном из следующих состояний: enum stream_state (* _good, _eof, _fail, _bad *); Если состояние _good или _eof, значит последняя операция ввода прошла успешно. Если состояние _good, то следующая опрация ввода может пройти успешно, в противном случае она зкончится неудачей. Другими словами, применение операции ввода к потоку, который не находится в состоянии _good, является пустой операцией. Если делается попытка читать в переменную v, и операция оканчивается неудачей, значение v должно отаться неизменным (оно будет неизменным, если v имеет один из тех типов, которые обрабатываются функциями членами istream или ostream). Отличие между состояниями _fail и _bad очень незначительно и предсавляет интерес только для разработчиков операций ввода. В состоянии _fail предполагается, что поток не испорчен и никакие символы не потеряны. В состоянии _bad может быть все что угодно. Состояние потока можно проверять например так: switch (cin.rdstate()) (* case _good: // последняя операция над cin прошла успешно break; case _eof: // конец файла break; case _fail: // некоего рода ошибка форматирования // возможно, не слишком плохая break; case _bad: // возможно, символы cin потеряны break; *) Для любой переменной z типа, для которого определены операции «„ и “», копирующий цикл можно написать так: while (cin»»z) cout «„ z «««\n“; Например, если z – вектор символов, этот цикл будет брать стандартный ввод и помещать его в стандартный вывод по одному слову (то есть, последовательности символов без пробла) на строку. Когда в качестве условия используется поток, происходит проверка состояния потока, и эта проверка проходит успешно (то есть, значение условия не ноль) только если состояние _good. В частности, в предыдущем цикле проверялось состояние istream, которое возвращает cin»»z. Чтобы обнаружить, почему цикл или проверка закончились неудачно, можно исследовать состояние. Такая проверка потока реализуется операцией преоразования (#6.3.2). Делать проверку на наличие ошибок после каждого ввода или вывода действительно не очень удобно, и обычно источником ошибок служит программист, не сделавший этого в том месте, где это существенно. Например, операции вывода обычно не проверяются, но они могут случайно не сработать. Парадигма потка ввода/вывода построена так, чтобы когда в С++ появится (если это произойдет) механизм обработки исключительных ситаций (как средство языка или как стандартная библиотека), его будет легко применить для упрощения и стандартизации обрабоки ошибок в потоках ввода/вывода.
РАБОТА С БИНАРНЫМИ ФАЙЛАМИ В отличие от текстовых файлов доступ к элементам бинарных файлов выполняется в произвольном порядке, а не последовательно. Поэтому бинарные файлы называют файлами произвольного доступа. Приложение, в котором предполагается использовать файлы произвольного доступа, должно их создавать. Все записи в таком файле должны быть одинаковой фиксированной длины. Данные могут быть вставлены в файл прямого доступа без разрушения других данных, изменены или удалены без перезаписи всего файла.
Для записи в файл использован класс ofstream, для чтения из файла использован класс ifstream · ifstream – класс, функции которого используются для чтения файлов · ofstream – класс, функции которого используются для записи файлов Название класса эквивалентно типу переменной, поэтому после названия класса объявляется объект, тип которого будет соответствовать классу.
1. Связать его с файлом данных и открыть (open) для работы в определенном режиме, с обязательным указанием двоичного режима ios:: binary (по умолчанию потоки открываются в текстовом режиме): void ifstream:: open(const char *имя_файла, openmode режим=ios:: in| ios:: binary); void ofstream:: open(const char *имя_файла, void fstream:: open(const char *имя_файла,
где имя_файла – имя файла, в которое может входить спецификатор пути; режим – задает режим открытия файла (см. лаб. раб. №10).
Для записи в поток в C++ используется метод write: basic_ostream< _Elem, _Tr> & write (const char_type *_Str, streamsize _Count);
Для чтения из потока используется метод read: basic_istream< _Elem, _Tr> & read(const char_type *_Str, streamsize _Count); _Count число выводимых (вводимых) в поток байт _Str символы выводимые(вводимые) в (из) поток(а) Произвольный доступ к файлу осуществляется путем установки текущей позиции в файле с помощью методов: для потоков открытых на ввод: basic_istream< _Elem, _Tr> & seekg(pos_type _Pos); basic_istream< _Elem, _Tr> & seekg(off_type _Off, ios_base:: seekdir _Way);
для потоков открытых на вывод в C++ пишется так: basic_ostream< _Elem, _Tr> & seekp(pos_type _Pos); basic_ostream< _Elem, _Tr> & seekp(off_type _Off, ios_base:: seekdir _Way);
_Pos позиция в потоке для чтения (номер байта) _Off позиция относительно _Way. _Way одно из перечислений ios_base (beg, cur, end):
Например: ofstream fout(“my.dat”, ios:: ate|ios:: binary); //устанавливаем указатель на начало потока fout.seekp(0); fout.write((char *) & el, sizeof el);
ifstream fin(“my.dat”, ios:: ate|ios:: binary); //передвигаем указатель на 10 байт перед концом потока fin.seekg(-10, ios_base:: end); fin.read((char *) & el, sizeof el);
В языке Си с помощью функции booleof(); можно определить, был ли достигнут конец файла ввода. 1. Для закрытия потока используется функция close(). РАБОТА С МАНИПУЛЯТОРАМИ Система ввода/вывода С++ включает второй способ изменения параметров форматирования потока. Для этого используются специальные функции, называемые манипуляторами (manipulators), которые могут включаться в выражения ввода/вывода. Стандартные манипуляторы показаны в таблице.
Для использования манипуляторов с параметрами в программу необходимо включить заголовочный файл iomanip.h. #include < iostream.h> Программа выводит следующие данные: 1000.24
Обратим внимание, как манипуляторы появляются в последовательности операторов ввода/вывода. Когда манипуляторы не имеют аргументов, как манипулятор endl в этой программе, за ними не следуют скобки. Причина этого в том, что оператору < < передается адрес манипулятора. Следующая программа использует функции setiosflags() для установки флагов scientific и showpos потока cout: #include < iostream.h> Следующая программа использует манипулятор ws для пропуска идущих вначале символов- разделителей при вводе строки в переменную s: #include < iostream.h> манипуляторы форматирования используются совместно с данными операторами ввода/вывода. Различие между функциями флагами и манипуляторами форматирования состоит в способе их применения. Доступ к функциям осуществляется через операцию точка, а в круглых скобочках передаётся аргумент. Аргумент функции fill()может передаваться в виде символа, обрамленного одинарными кавычками, или в виде числа(код символа). Одних функций не достаточно для форматирования потоков ввода/вывода, поэтому в С++ предусмотрен ещё один способ форматирования — флаги. Флаги форматирования позволяют включить или выключить один из параметров ввода/вывода. Чтобы установить флаг ввода/вывода, необходимо вызвать функцию setf(), если необходимо отключить флаг вывода, то используется функция unsetf(). Далее показаны конструкции установки и снятия флагов вывода.
Форматированный ввод/вывод в С++ это одна из самых простых тем в программировании. Как использовать те или иные средства форматирования показано в таблицах, поэтому затруднений по данной теме возникнуть не должно.
Ещё один способ форматирования — форматирование с помощью манипуляторов. Манипулятор — объект особого типа, который управляет потоками ввода/вывода, для форматирования передаваемой в потоки информации. Отчасти манипуляторы дополняют функционал, для форматирования ввода/вывода. Но большинство манипуляторов выполняют точно, то же самое, что и функции с флагами форматирования. Есть случаи, когда проще пользоваться флагами или функциями форматирования, а иногда удобнее использовать манипуляторы форматирования. Именно по этому в С++ предусмотрено несколько средств форматирования ввода/вывода. В таблице 2 показаны основные манипуляторы форматирования С++. МЕХАНИЗМ ОБРАБОТКИ ИСКЛЮЧЕНИЙ Механизм исключений позволяет легко отследить различные ошибки в программе. Оператор try определяет блок, в котором необходимо отследить исключения. Оператор throw вызывает исключение указанного типа. Оператор catch определяет блок обработки исключения указанного типа. Подобных блоков может быть несколько для каждого типа. Если же тип исключения не важен или нужно обработать исключения по умолчанию, то в качестве аргумента используется троеточие. В современном C++ в большинстве случаев предпочтительный способ уведомления и обработки логических ошибок и ошибок среды выполнения — использование исключений. Это особенно заметно, когда стек может содержать несколько вызовов функции между функцией, которая обнаруживает ошибку и функцией, которая содержит контекст для получения сведений о его обработки. Исключения предоставляют формальный, четко определенный способ для передачи обнаружившим ошибку кодом сведений вверх по стеку вызовов. Ошибки программы обычно делятся на две категории: логические ошибки, вызванные ошибками программирования (ошибка " индекс вне диапазона"), а также ошибки среды выполнения, которые не может контролировать программист, например ошибка " сетевая служба недоступна". В стиле программирования C и в модели COM отчеты об ошибках управляются возвратом значения, представляющего код ошибки или код статуса для определенной функции, или заданием глобальной переменной, которая может дополнительно извлекаться вызывающим объектом после каждого вызова функций, чтобы посмотреть, был ли составлен отчет об ошибках. Исключения являются предпочтительными в современном языке C++ по следующим причинам: · Исключение вынуждает вызывающий код признать состояние ошибки и обработать его. Необработанные исключения останавливают выполнение программы. · Исключение перескакивает в точку в стеке вызовов, которая способна обработать ошибку. Промежуточные функции могут разрешить распространение исключения. Они не должны в соответствии с другими уровнями. · Механизм освобождения стека исключения уничтожает все объекты в области в соответствии с правилами чётким после создания исключения. · Исключение обеспечивает четкое разделение между кодом, который обнаруживает ошибку, и кодом, который обрабатывает ошибку. Давайте же разберем основы обработки исключений в С++. Чтобы комфортно работать с исключениями в С++ вам нужно знать лишь три ключевых слова:
|