|
Программирование >> Процедурные приложения
[ 1] А [ 2] 65 [ 3] Z [ 4] 2322 [ 5] 4d2 [ 6] 4D2 [ 7] А [ 8] А [ 9] Строка для экспериментов [10] Строка для экспериментов [11] Строка для экспериментов [12] Строка для экспериментов [13]1234 [14]+1234 [15]1234 [16]1234 [17] 1234 [18] 0000001234 [19] 3.14159 [20] 3.14159 [21] 00000000000003.14159 [22] 3.14159 [23] 3.141590000000000000 [24] Строка для эксперим [25] Ст [26] Ст [27] Ст [28] 3.14159265 [29] 3.1 [30] 3.142 [31]3.142 [32] 3.1416e+000 В этой программе следует обратить внимание на использование класса ostrstream в пунктах 24 и 25, а также неявно в пунктах 26 и 27. Этот класс управляет выводом строк. Необходимость в нем возникла в связи с тем, что флаги форматирования оказывают влияние на работу оператора <<, но не функции write() класса ostream(класс ostrstream является его потомком и наследует данную функцию), которая записывает в поток указанное число символов строки. Выводимые ею данные всегда прижимаются к левому краю. Поэтому мы поступаем следующим образом: ostrstream(strbuffer, 2 0).write(psz,19) ends; cout.width(19); cout << strbuffer; Разберем этот фрагмент шаг за шагом. Сначала вызывается конструктор класса ostrstream, создающий временный безымянный объект данного класса, автоматически уничтожаемый по завершении строки. Если вы еще не знакомы с понятием конструктора, то поясним, что это особая функция, предназначенная для динамического создания объектов своего класса. Конструктор класса ostrstreamтребует указания двух аргументов: буферной строки, в которую будет осуществляться вывод, и размера буфера. Особенность заключается в том, что реальный размер буферного массива может быть больше указанного, но все данные, записываемые сверх лимита, будут отсекаться. Итак, конструктор создал требуемый объект, связанный с буфером strbuffer. Этот объект является обычным потоком в том смысле, что им можно управлять как и любым другим потоком вывода, только данные будут направляться не на экран, а в буфер. Вторым действием вызывается функция write() объекта, записывающая в поток первые 19 символов строки psz. Оператор точка (.) в данном случае обозначает операцию доступа к члену класса. Здесь тоже есть своя особенность: функция write() возвращает адрес потока, из которого она была вызвана. А это, в свою очередь, означает, что мы можем тут же применить к потоку оператор вывода <<. Итого, три действия в одном выражении! Манипулятор endsкласса ostreamвставляет в поток символ \0,служащий признаком завершения строки. Именно поэтому в буфере было зарезервировано 20 ячеек - на единицу больше, чем количество выводимых символов строки psz. В результате выполненных действий в буфере оказалась сформированной готовая строка, которая, в конце концов, и направляется в поток cout. Теперь рассмотрим, что происходит в пункте 25: ostrstream (strbuf fer, 3) .write (psz, 2) << ends; cout << strbuffer; Последовательность действий та же, но резервируется не весь буфер, а только первые три ячейки. Трюк в том, что объект cout воспринимает массив strbuffer как обычную строку, но поскольку в третьей ячейке стоит символ \0,то получается, что строка состоит из двух символов! В пунктах 26 и 27 используется содержимое буфера, полученное в пункте 25. Важно также помнить, что функция width( ) оказывает влияние только на следующий за ней оператор вывода, тогда как, например, действие функции precision() останется в силе до тех пор, пока она не будет выполнена снова либо не будет вызван манипулятор setprecision( ) . Файловый ввод-вывод Во всех программах на языке C++, рассмотренных до сих пор, для ввода и вывода данных применялись стандартные потоки cin и cout. Если для этих же целей удобнее работать с файлами, следует воспользоваться классами ifstream и ofstream, которые порождены от классов istream и ostream и унаследовали от них функции, соответственно, чтения и записи. Необходимо также подключить файл FSTREAM.H (он, в свою очередь, включает файл IOSTREAM.H). В следующей программе демонстрируется работа с файлами посредством классов ifstream и ofstream: fstream. cpp Эта программа на языке C++ демонстрирует, как создавать потоки ifstream и ofstream для обмена данными с файлом. #include <fstream.h> int main(void) { char c; ifstream ifsin( text.in , ios::in); if(lifsin) cerr<< \nНевозможно открыть файл text.in для чтения. ; ofstream ofsout( text.out , ios::out); if(!ofsout) cerr<< \nНевозможно открыть файл text.outдля записи. ; while (ofsout && ifsin.get(c) ) ofsout.put (c); if sin. close (); ofsout. close () ; return(0); } Программа создает объект ifsin класса ifstream и связывает с ним файл TEXT. IN, находящийся в текущем каталоге. Всегда следует проверять доступность указанного файла. В данном случае проверка осуществляется достаточно оригинальным образом. Оператор ! в потоковых классах перегружен таким образом, что, будучи примененным к соответствующему объекту, при наличии каких-либо ошибок в потоке возвращает ненулевое значение. Аналогичным образом создается и объект ofsoutкласса ostream, связываемый с файлом TEXT.OUT. В цикле whileосуществляется считывание и запись отдельных символов в выходной файл до тех пор, пока в ряду символов не попадется EOF. При завершении программы закрываются оба файла. Особенно важно закрыть файл, в который записывались данные, чтобы предупредить потерю информации, еще находящейся в буфере. Иногда возникают ситуации, когда необходимо отложить процесс спецификации файла или когда с одним объектом нужно последовательно связать сразу несколько потоков. В следующем фрагменте показано, как это сделать: ifstream ifsin; ifsin.open( weekl.in ); if sin.close () ; ifsin.open( week2.in ) if sin. close () ; Если необходимо изменить режим доступа к файлу, то это можно сделать путем модификации второго аргумента конструктора соответствующего файлового объекта, Например: ofstream ofsout( file.out , ios::app ios::nocreate); В данном выражении делается попытка создать объект ofsout и связать его с файлом FILE.OUT. Поскольку указан флаг ios::nocreate, подключение не будет создано, если файл FILE.OUT не существует. Флаг ios::app означает, что все выводимые данные будут добавляться в конец файла. В следующей таблице перечислены флаги, которые можно использовать во втором аргументе конструкторов файловых потоков (допускается
Для обмена данными с файлом можно также использовать объект класса fstream. Например, в следующем выражении файл UPDATE.DAT открывается для чтения и записи данных: fstream io( update.dat , ios::in ios::app); К объектам класса iostream(а класс fstream является его потомком) можно применять функции seekg() и seekp(), позволяющие управлять положением маркера текущей позиции файла. Функция seekg() задает положение маркера, связанного с чтением данных из файла, а функция seekg() - с записью. Обе функции требуют указания одного или двух аргументов. Если указан один аргумент, он считается абсолютным адресом маркера. Если два, то первый задает относительное смещение, а второй - направление перемещения. Существует также функция tellg(), возвращающая текущее положение маркера чтения, и функция tellp(), возвращающая текущее положение маркера записи. Рассмотрим небольшой фрагмент программы: streampos current position = io.tellp(); io << objl << obj2 << obj3; io.seekp(current position); io.seekp(sizeof(objl), ios::cur); io<< newobj2; Сначала создается указатель current positionтипа streampos, который инициализируется текущим адресом маркера записи. Во второй строке в поток io записываются три объекта. В третьей строке с помощью функции seekp() указатель перемещается в сохраненную позицию.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |