Г. Шилтд - Самоучитель C++ (PDF) (1114887), страница 43
Текст из файла (страница 43)
Перепишите программу из примера I так, чтобы вместо функции getlineQиспользовать функцию get(). Будет ли отличаться работа программы?292Самоучитель C++2. Напишите программу для построчного считывания текстового файла и вывода каждой считанной строки на экран. Используйте функцию getlineQ.3. Подумайте о ситуациях, в которых может оказаться полезным вызов функции flush().9.5. Произвольный доступВ системе ввода/вывода C++ произвольный доступ (random access) реализуется спомощью функций seekg() и seekp(), являющихся соответственно потоковымифункциями ввода и вывода. Здесь показаны их основные формы:istream fiseekg(off_type смещение, seekdir задание);ostream Sseekp(off_type смещение, seekdir задание);Здесь off_type -- это целый тип данных, определенный в классе ios и совместимый с максимальным правильным значением, которое способен хранить параметр смещение.
Тип seekdir — это перечисление, определенное вклассе ios и содержащее следующие значения:ЗначениеСмыслios:: begПоиск с начала файлаios: :curПоиск от текущей позиции в файлеios: :endПоиск с конца файлаСистема ввода/вывода C++ управляет двумя указателями, связанными сфайлом. Первый — это указатель считывания (get pointer), который задаетследующее место в файле, откуда будет вводиться информация. Второй это указатель записи (put pointer), который задает следующее место в файле,куда будет выводиться информация. При каждом вводе или выводе соответствующий указатель последовательно продвигается дальше. Однако с помощью функций seekg() и seekpQ возможен непоследовательный доступ кфайлу.Функция seekgQ устанавливает указатель считывания соответствующегофайла в позицию, отстоящую на величину смещение от заданного местазадание.
Функция seekp() устанавливает указатель записи соответствующегофайла в позицию, отстоящую на величину смещение от заданного местазадание.Как правило, файлы, доступные для функций seekg() и seekp(), должны открываться в режиме операций для двоичных файлов. Таким образом предотвращается возможное неожиданное преобразование символов внутри файла.Определить текущую позицию каждого из двух указателей можно с помощью функций:Глава 9. Дополнительные возможности ввода/вывода в C++293pos_type tellgO;pos_type tellpO;Здесь pos_type — это целый тип данных, определенный в классе ios и способный хранить наибольшее возможное значение указателя.Для перемещения файловых указателей считывания и записи на позицию,заданную возвращаемыми значениями функций tellgQ и tellp(), используются перегруженные версии функций seekgQ и seekpQ.
Прототипы этих функций представлены ниже:istream Sseekg{pos_type позиция) ;ostream fiseekp(pos type позиция) ;Примеры JВ следующей программе показана работа функции seekpQ. Она позволяет заменить в файле заданный символ. Укажите в командной строке имя файла, затемномер байта в файле, который вы хотите изменить, и, наконец, новый символдля замены. Обратите внимание: файл открывается для операций чтения изаписи.^include <iostream>^include <fstream>^include <cstdlib>using namespace std;int mainlint argc, char *argv[]){if{argc!=4} {cout « "Замена: <файл> <байт> <символ>\п";return 1;fstream o u t ( a r g v [ l ] , i o s : : i n | ios::out | ios : : binary ) ;if ( l o u t ) {cout « "Файл открыть невозможно \п";return 1;out .seekp (atoi (arqv[2] ) , ios: :beg) ;out .put (*argv[3] ) ;out, close () ;return 0;294___Самоучитель С++_1, В следующей программе функция seekgQ используется для установки указателя считывания в заданную позицию внутри файла и для вывода содержимого файла, начиная с этой позиции.
Имя файла и позиция началасчитывания задаются в командной строке.// Демонстрация работы функции seekg()^include <iostream>^include <fstream># include <cstdlib>using namespace std;int main(int argc, char *argv[]}char ch;if(argc!=3) {cout « "Поиск: <файл> <позиция>\п";return 1;if stream in(argv[l] , ios: :in I ios: : binary) ;if(!in) {cout « "Файл открыть невозможно \п";return 1;in.seekgfatoi (argv[2] ) , ios: :beg) ;while (lin.eofO) {in. get (ch) ;cout « ch;in.
close () ;return 0;Упражненияения]1. Напишите программу для вывода на экран содержимого текстового файла вобратном порядке. (Подсказка: Обдумайте задание перед началом программирования. Решение проще, чем может показаться на первый взгляд.)2. Напишите программу, которая попарно меняет местами символы в текстовом файле. Например, если в файле содержится "1234", то после выполненияпрограммы там должно содержаться "2143". (Для простоты считайте, что вфайле содержится четное число символов.)Глава 9. Дополнительные возможности ввода/вывода в C++2959.6. Контроль состояния ввода/выводаВ системе ввода/вывода C++ поддерживается информация о состоянии после каждой операции ввода/вывода.
Текущее состояние потока ввода/вывода, которое хранится в объекте типа iostate, является перечислением,определенным в классе ios и содержащим следующие члены:НазваниеЗначениеgoodbitОшибок нетeofbitДостигнут конец файлаfailbitbadbitИмеет место нефатальная ошибкаИмеет место фатальная ошибкаВ устаревших компиляторах флаги состояния ввода/вывода хранятся какцелые, а не как объекты типа iostate.Имеются два способа получения информации о состоянии ввода/вывода.Во-первых, можно вызвать функцию rdstate(), являющуюся членом классаios.
Прототип этой функции:iostate rdstateO;Функция возвращает текущее состояние флагов ошибки. Как вы, вероятно,догадываетесь, глядя на приведенный выше список флагов, функцияrdstate() возвращает флаг goodbit при отсутствии какой бы то ни былоошибки. В противном случае она возвращает флаг ошибки.Другим способом определения того, имела ли место ошибка, является использование одной или нескольких следующих функций — членов класса ios:bool bad () ;bool eof () ;bool fail () ;bool goodО;Функция eof() уже обсуждалась. Функция bad() возвращает истину, еслиустановлен флаг badbit. Функция fail() возвращает истину, если установленфлаг failbit. Функция good() возвращает истину при отсутствии ошибок.
Впротивном случае функции возвращают ложь.После появления ошибки может возникнуть необходимость сбросить этосостояние перед тем, как продолжить выполнение программы. Для этогоиспользуется функция с!еаг(), являющаяся членом класса ios. Ниже приведен прототип этой функции:void clear(iostate фляга = ios::goodbit);Самоучитель C++296Если параметр флаги равен goodbit (значение по умолчанию), то сбрасываются флаги всех ошибок. В противном случае переменной флаги присваиваются значения тех флагов, которые вы хотите сбросить.Примеры""' " ''•%j/J1. В следующей программе иллюстрируется выполнение функции rdstateQ.Программа выводит на экран содержимое текстового файла.
При наличииошибки функция сообщает об этом с помощью функции checkstatus().^include <iostream>finclude <fstream>using namespace std;void checkstatus(ifstream S i n ) ;int m a i n f i n t argc,char * a r g v [ ] )if(argc!=2) {cout « "Содержимое: <имя_файла>\п";return 1;ifstream in(argv[l]);if(!in) Icout « "Файл открыть невозможной";return 1;char с;while(in.get(c)) {cout « c;checkstatus(in);checkstatus (in); // контроль финального состоянияin.close () ;• return 0;void checkstatus(ifstream sin)ios::iostate i;i = in.rdstate();if(i & ios::eofbit)cout « "Достигнут EOF\n";else if(i & ios::failbit)cout « "Нефатальная ошибка ввода/вывода\п";Глава 9. Дополнительные возможности ввода/вывода в C++297else i f ( i S ios::badbit)cout « "Фатальная ошибка ввода/вывода\n";Эта программа всегда будет выводить сообщение по крайней мере об однойошибке.
После окончания цикла while последний вызов функции checkstatus(),как и ожидается, выдаст сообщение о достижении конца файла (символа EOF).2. В следующей программе с помощью функции good() файл проверяется наналичие ошибки:tinclude <iostream>#include <fstream>using namespace std;int main(int argc, char * a r g v [ ] )'char ch;if(argc!=2) {cout « "Содержимое: <имя_файла>\п";return 1;}ifstream in(argv[l]);if (!in) {cout « "Файл открыть невозможной";return 1;while(lin.eof0} {in.get(ch);// контроль ошибкиif(!in.good() && lin.eof()) {cout « "Ошибка ввода/вывода ... прерывание работы\п"return 1;}cout « ch;}in.close();return 0;Упражнения1. Добавьте контроль ошибок в ваши ответы на вопросы предыдущего раздела.•298Самоучитель C++9.7.
Пользовательский ввод/выводи файлыВ предыдущей главе вы изучили перегрузку операторов ввода и вывода длясоздаваемых вами классов. При этом рассматривался только консольныйввод/вывод. Однако поскольку все потоки C++ одинаковы, то одинаковоперегруженная, например, функция вывода, может использоваться без каких-либо изменений для вывода как на экран, так и в файл. Это одна изнаиболее важных и полезных возможностей ввода/вывода в C++.Как установлено в предыдущей главе, перегруженные функции ввода/вывода так же, как и манипуляторы ввода/вывода могут использоваться слюбым потоком.
Если вы "жестко" зададите конкретный поток в функцииввода/вывода, область ее применения, несомненно, будет ограничена толькоэтим потоком. Следует, по возможности, разрабатывать такие функции ввода/вывода, чтобы они могли одинаково работать с любыми потоками.ПримерыВ следующей программе относительно класса coord перегружаются операторы « и ». Обратите внимание, что одни и те же оператор-функции можноиспользовать для вывода как на экран, так и в файл.tinclude <iostream>ttinclude <fstream>using namespace std;class coord {int x, y;public:coordfint i, int j) { x = i; у = j; }friend ostream £operator«(ostream &stream, coord ob);friend istream &operator»(istream &stream, coord Sob);i;ostream &operator« (ostream Sstream, coord ob)stream « ob.x « ' ' « ob.y « ' \ n ' ;return stream;istream soperator» (istream Sstream, coord Sob){stream » ob.x » ob.y;return stream;Глава9.Дополнительныевозможностиint ma in ()ввода/выводавC++_299.coord ol(l, 2), o2(3, 4);of stream out ("test");if (lout) {cout « "Файл открыть невозможной";return 1;out « ol « o2;out.
close (} ;ifstream in ("test");if(!in) {cout « "Файл открыть невозможно \п"return 1;1coord o3(0, 0), o4(0, 0) ;in » o3 » o4;cout « o3 « o4;in. close () ;return 0;2. Все манипуляторы ввода/вывода подходят и для файлового ввода/вывода.Например, в представленной ниже переработанной версии одной из программ этой главы, тот манипулятор, который выводит информацию на экран, используется и для ее записи в файл.^include <iostream>ttinclude <fstream>ttinclude <iomanip>using namespace std;// Внимание:ostream &atn(ostream Sstream){stream « "Внимание: ";return stream;}// Пожалуйста, не забудьте:ostream ¬e (ostream Sstream)stream « "Пожалуйста, не забудьте: ";300Самоучитель C++return stream;}int main(){ofstream out("test"};if(lout) {cout « "Файл открыть невозможной";return 1;}// вывод на экранcout « atn « "Высокое напряжение \п";cout « note « "Выключить свет\п";// вывод в файлout « atn « "Высокое напряжение\п";out « note « "Выключить свет\п";out.close();return 0;Упражнения1.