Г. Шилтд - Самоучитель C++ (PDF) (1114887), страница 40
Текст из файла (страница 40)
Манипулятор должен возвращать этот поток.То, что манипулятор возвращает ссылку на вызывающий поток весьма важно.Если этого не сделать, то ваши манипуляторы нельзя будет использовать в последовательностях операций ввода или вывода.1. Рассмотрим первый простой пример. В следующей программе создается манипулятор setup(), который устанавливает ширину поля вывода, равную 10,точность, равную 4, и символ заполнения *.#include <iostream>using namespace std;Само учитель274ostream fisetup (ostrearn fistream)fstream.width(10);stream.precision{4) ;1stream.filK *'} ;return stream;int main()cout « setup « 123.1234^6:return 0;Как можно заметить, созданный вами манипулятор setup используется в качестве части выражения ввода/вывода точно так же, как это делается с любым встраиваемым манипулятором.2.
Пользовательские манипуляторы не обязательно должны быть сложными.Например, простые манипуляторы atn() и note() обеспечивают простой иудобный способ вывода часто встречающихся слов и фраз.^include <iostream>using namespace std;// Внимание:ostream Satn (ostream sstream)istream « "Внимание: ";return stream;}// Пожалуйста, не забудьте:ostream Snote (ostream ^stream){stream « "Пожалуйста, не забудьте: ";return stream;}int main ( ){cout « atn « "Высокое напряжениеХп";cout « note « "Выключить свет\п";return 0;Несмотря на простоту, такие манипуляторы оградят вас от необходимостичастого набора одних и тех же слов и фраз.Глава_9.Дополнительныевозможностиввода/выводавC++_2753.
В следующей программе создается манипулятор getpass(), который вызываетгудок динамика и затем предлагает ввести пароль:#include ,<io3tream>^include <cstring>using namespace std;// Простой манипулятор вводаistream bgetpass (istream Sstream){cout « ' \ a ' ; // гудок динамикаcout « "Введите пароль : " ;return stream;int main ( ){char p w [ 8 0 ] ;do {cin » getpass » pw;} while (strcmp(pw, "пароль"));cout « "Пароль введен верноХп";return 0;1. Создайте манипулятор вывода для отображения текущего системного времени и даты. Назовите манипулятор td().2.
Создайте манипулятор вывода sethex(), который осуществляет вывод в шестнадцатиричной системе счисления и устанавливает флаги uppercase иshowbase. Кроме того, создайте манипулятор вывода resetQ, который отменяет изменения, сделанные манипулятором sethex().3. Создайте манипулятор ввода skipchar(), который поочередно то считывает, топропускает каждые десять символов потока ввода.9.2. Основы файлового ввода/выводаКак было отмечено в предыдущей главе, файловый и консольныйввод/вывод очень близко связаны. Фактически файловый ввод/вывод поддерживается той же иерархией классов, что и консольный ввод/вывод.276Самоучитель C++Таким образом, все, что вы уже узнали о вводе/выводе, вполне применимои к файлам. Естественно, что обработка файлов предполагает и кое-что новое.Для реализации файлового ввода/вывода, необходимо включить в программузаголовок <fstream>. В нем определено несколько классов, включая классыifstream, ofstream и fstream.
Эти классы являются производными от классовistream и ostream. Вспомните, что классы istream и ostream, в свою очередь,являются производными от класса ios, поэтому классы ifstream,. ofstream иfstream также имеют доступ ко всем операциям, определяемым классом ios(это обсуждалось в предыдущей главе).В C++ файл открывается посредством его связывания с потоком. Имеетсятри типа потоков: ввода, вывода и ввода/вывода. Перед тем как открытьфайл, нужно, во-первых, создать поток. Для создания потока ввода необходимо объявить объект типа ifstream. Для создания потока вывода — объекттипа ofstream. Потоки, которые реализуют одновременно ввод и вывод,должны объявляться как объекты типа fstream.
Например, в следующемфрагменте создается один поток для ввода, один поток для вывода и ещеодин поток одновременно для ввода и для вывода:ifstream in; // вводofstream out; // выводfstream io;// ввод и выводПосле создания потока, одним из способов связать его с файлом являетсяфункция ореп(). Эта функция является членом каждого из трех потоковыхклассов. Здесь показаны ее прототипы для каждого класса:void ifstream::open(const char *#мя_файла,openmode режим = ios: : in) ;void ofstream::open(const char *имя файла,openmode режим = ios: :out I ios: : trunc) ;void fstream::open(const char *имя_фаяла,Openmode режим = ios: : in | ios: : out) ;Здесь UMxjpaUAa — имя файла, в которое может входить и спецификаторпути.
Значение режим задает режим открытия файла. Оно должно быть значением типа openmode, которое является перечислением, определенным вклассе ios. Значение режим может быть одним из следующих:юзiosiosiosiosios:app:ate: binary: in:out: truncВы можете объединить два или более этих значения с помощью оператораOR. Рассмотрим, что означает каждое из этих значений.Глава 9. Дополнительные возможности ввода/вывода в C++277Значение ios::app вызывает открытие файла в режиме добавления в конецфайла? Это значение может применяться только к файлам, открываемым длявывода. Значение ios::ate задает режим поиска конца файла при его открытии.Хотя значение ios::ate вызывает поиск конца файла, тем не менее, операцииввода/вывода могут быть выполнены в любом месте файла.Значение ios::in задает режим открытия файла для ввода.
Значение ios::outзадает режим открытия файла для вывода.Значение ios::binary вызывает открытие файла в двоичном режиме. По умолчанию все файлы открываются в текстовом режиме. В текстовом режимеимеет место преобразование некоторых символов, например, последовательность символов "возврат каретки/перевод строки" превращается в символ новой строки. Если же файл открывается в двоичном режиме, такогопреобразования не выполняется. Запомните, что любой файл, независимо оттого, что в нем содержится — отформатированный текст или необработанные данные — может быть открыт как в текстовом, так и в двоичном режиме.
Отличие между ними только в отсутствии или наличии упомянутогосимвольного преобразования.Значение ios::trunc приводит к удалению содержимого ранее существовавшего файла с тем же названием и усечению его до нулевой длины. При создании потока вывода с помощью ключевого слова ofstream любой ранеесуществовавший файл с тем же именем автоматически усекается до нулевойдлины.В следующем фрагменте для вывода открывается файл test:.ofstream mystream;mystream.open("test");В этом примере параметр режим функции ореп() по умолчанию устанавливается в значение, соответствующее типу открываемого потока, поэтому нет необходимости указывать его явно.Если выполнение функции ореп() завершилось с ошибкой, в булевом выражении поток будет равен значению false. Этот факт можно использовать дляпроверки правильности открытия файла с помощью, например, такой инструкции:if(!mystream) {cout « "Файл открыть невозможно\п";// программа обработки ошибки открытия файла)Как правило, перед тем как пытаться получить доступ к файлу, следует проверить результат выполнения функции ореп().Проверить правильность открытия файла можно также с помощью функцииis_open(), являющейся членом классов ifstream, ofstream и fstream.
Ниже показан прототип этой функции:bool is o p e n { ) ;278___Самдучитель_С++Функция возвращает истину, если поток удалось связать с открытым файлом, в противном случае функция возвращает ложь. Например, в следующем фрагменте проверяется, открыт ли файл, связанный с потоком mystream:iff !mystream.is_open() ) {cout « "Файл не открытЛп";Хотя использовать функцию openQ для открытия файла в целом правильно,часто вы этого делать не будете, поскольку у классов ifstream, ofstream иfstream есть конструкторы, которые открывают файл автоматически. Конструкторы имеют те же параметры, в том числе и задаваемые по умолчанию,что и функция орел(). Поэтому чаще вы будете пользоваться таким способом открытия файла:ifstream mystream ("rnyfile") ; // открытие файла для вводаКак уже установлено, если по каким-то причинам файл не открывается, переменная, соответствующая потоку, в условной инструкции будет равна значению false.
Поэтому, независимо от того, используете ли вы конструкторили явно вызываете функцию ореп(), вам потребуется убедиться в успешномоткрытии файла путем проверки значения потока.Для закрытия файла используйте функцию-член close(). Например, чтобызакрыть файл, связанный с потоком mystream, необходима следующая инструкция:mystream. close ( ) ;Функция close() не имеет параметров и возвращаемого значения.С помощью функции eof(), являющейся членом класса ios, можно определить, был ли достигнут конец файла ввода. Ниже показан прототип этойфункции:bool eof () ;Функция возвращает истину, если был достигнут конец файла; в противномслучае функция возвращает ложь.После того как файл открыт, очень легко считать из него или записать внего текстовые данные.
Просто используйте операторы « и » так же, какэто делалось для консольного ввода/вывода, только замените поток cm илиcout тем потоком, который связан с файлом. Так же, как и операторы « и» для чтения из файла и записи в файл годятся функции С — fprintfQ иfscanfQ. Вся информация в файле хранится в том же формате, как если быона находилась на экране. Следовательно, файл, созданный с помощьюоператора «, представляет из себя файл с отформатированным текстом, иГлава 9. Дополнительные возможности ввода/вывода в C++279наоборот, любой файл, содержимое которого считывается с помощью оператора », должен быть файлом с отформатированным текстом.