Программирование >>  Унарные и бинарные операторы 

1 ... 29 30 31 [ 32 ] 33 34 35 ... 37


Как уже говорилось, ввод-вывод данных основан на потоках ввода-вывода - последовательностях символов. Такой последовательностью можно считать и файл, поэтому к файлам применимы те же функции, операторы и манипуляторы, что и к объектам cin и cout. Формально это происходит потому, что вся система ввода-вывода в С++ построена иерархически. На вершине стоит класс ios, от которого происходят классы istream и ostream, порождающие такие объекты-, как cin и cout. В свою очередь, файлы в С++ описываются классами i fstream, of stream и f stream, производными от i stream и ofstrefm. Вот почему они так похожи па обычные потоки.

Посмотрим, например, как выводятся в файл целые числа и как они читаются из ({)айла Профамма, которая это проделывает, показана в листигп-е 12.6.

вен нулю, когда переменная i равна 9,19,29 и т. д. То есть профамма выводит элемент массива под номером 9,19, 29, ... и т. д., а затем переводит строку - именно этого мы и добиваемся!

Кроме манипуляторов setwO и endl, упомянутых в этом ра.зделс, есть довольно много других, объявленных в файлах <iomanip> и <iostream>. Заголовочные файлы компилятора - своеобразный справочник по языку, именно они открывают нам устройство стандартных объектов, функций и операторов. Этими файлами обязательно нужно пользоваться, хотя на первых порах они немного пугают.

Задача 12.1. Начните знакомство с заголовочными файлами прямо сейчас. Для начала постарайтесь выяснить, какие бывают манипуляторы, как они устроены и что делают.

Файлы

Решим для примера простую задачу: вывести на экраи сто целых чисел так, чтобы в одной строке их было 10. Естественно, числа на экране должны стоять стройными рядами, образуя что-то вроде таблицы. Эту простую задачу решает программа, показаьн1ая в листинге 12.5.

Листинг 12.5

#include <1ostream> #inc1ude <iomanip using namespace std: int main(){ int m[100]:

forCint i=0:i<100:i++){ m[i>i:

for(int i=0:i<100:i++){ cout setwO) m[i]: if(!((i+l)X10)) cout endl:

return 0: }

В этой программе на экран выводятся сто идущих подряд чисел, храня1цихся в массиве т[]. Количество позиций, занимаемых на экране одним числом, определяет манипулятор setwO). В нашем случае максимальное выводимое число равно 99, поэтому достаточно трех позиций, чтобы числа стояли ровными столбцами и не сливались.

Остается тол ько научиться вовремя переводить строку, чтобы числа образовали прямоугольную таблицу с десятью столбцами. Делает это следуюн1ая инструкция, которая определяет момент перевода строки (когда операция (i+DXlO дает ноль):

if(!((i+imO)) cout endl:

Оператор %, до сих пор нам не встречавптйся, означает остаток от деления. Например, 100%3 равно 1, потому что 100 - 33 X 3 + 1. В наиюм примере вычисляется остаток от деления i+1 на 10. Очевидно, он ра-



Листинг 12.6

#include <iostrearr> #include <fstream> #include <lomanip> using namespace std; int main(){ int a[100]: ofstream outCdigs ); forCint i=0;i<100:i++)

out setwO) i: out.closeO; ifstream inCdigs ): forCint 1=0;i<lOO;i++)

in a[i]: forCint i=0:i<100;i++)

cout a[i] endl: in.closeC); return 0;

Сначала в этой программе создается объект out класса ofstream. Его конструктору указывается имя файла digs. Класс ofstream описывает файлы, созданные только для записи, что нам и нужно.

Запись в файл ста последовательных чисел выполняет цикл:

forCint 1=0;1<100:1++) out setw(3) i;

В этом цикле объект out ничем, по сути, не отличается от cout, хотя первый описывает файл, а второй - экран монитора.

Манипулятор setw(3) здесь необходим, чтобы создать пробелы между последовательными числами. Пробелы показывают оператору , где кончается одно чиаю и начинается другое.

После вывода чисел файл digs закрывается функцией out.closeO и тут же открывается вновь. На этот раз с ним связан объект in класса ifstream, то есть файл digs теперь можно только читать, что и делается в цикле:

forCint i=0;1<100:i++) in a[i]:

После ввода в массиве а[] оказываются те же числа, что и в файле. В этом нас убеждает последний цикл, выводящий числа из массива на экран.

Задача 12.2. Скомпилируйте и запустите программу, показанную в листинге 12.6. С помощью текстового редактора посмотрите, что записано в файле digs.

То, что файлы происходят от потоков, вовсе не значит, что в них нет ничего нового. Родители часто недоумевают, откуда у них такие дети и в кого. Как мы только что видели, у файлов много общего с родительскими классами, но много и различий, связанных с их иной природой. Файлы устойчивее потоков. Их можно хранить, что-то менять в любой части файла, добавлять данные в конец файла и т. д.

Возможные операции с файлом определяются при его открытии. Делается это с помон1ЬЮ специальных констант, определенных в классе ios. До сих пор мы порождали файлы из классов ifstream (для чтения) и ofstream (для записи). Попробуем для разнообразия объявлять файлы как объекты класса f stream, порождающего файлы, пригодные как для чтения, так и для записи.

Итак, следующее объявление открывает файл name для чтения, а константа ios::out означает открытие для записи:

fstream nameC digs .ios::in):

Можно указать сразу несколько констант, разделенных знаком I. Так, показанное ниже объявление открывает файл name как для чтения, так и для записи:

fstream nameC digs .ios::in ios::out);

Открытие для записи требует осторожности, потому что можно уничтожить уже существующий файл. Именно так действует одинокая константа ios:: out.



Файлы 223

цепочку несколько операций, например ci п .getCch) chl. Но условие выполнения цикла while О - это, как мы знаем, булево выражение, принимающее только два значения - true и false.

Разрешается то противоречие просто: как только компилятор видит, ч го выражение, в котором есть объекты, принадлежащие системе ввода-вывода, по своему смыслу должно принимать только два значения, true и false, он превращает их в булево значение. Так, например, функция in.getO, попав в круглые скобки после whi 1е(), преврап1ается компилятором в true, если чтение было успешным, и в fal se - в противном случае*. Обычно значение false получается, когда достигнут конец файла. В этом случае цикл whileO прервется, не дойдя до функции putO, потому что последгни ! символ уже прочитан и записан в файл out при предыдуп1см проходе цикла.

Теперь попробуем написать программу копирования файлов. Исходя из того, что до сих пор пам известно, выглядеть она будет так, как в листинге 12.8.

Листинг 12.8

#include <fstream>

using namespace std:

int maindnt argc. char **argv){

char ch;

fstream in(argv[l]. ios::in); fstream out(argv[2].ios;:out);

while(in.get(ch)) out.put(ch);

В разделе Питание iipoipa.\iM* главы 4 .мы уже сталкивались с подобным выражением \vhile(cin buf). но. пс имея достаточных зна1И111, просто говорили, что оно равно true или false в зависимости от введенно1о символа.

Чтобы сохранить файл, можно открывать его одновременно для чтения и записи или использовать константу ios: :арр, разрешающую запись только в конец файла (режим добавления). Можно также использовать константу ios: :погер1асе, запрещающую открывать файл, если он уже существует. Программа, пок11занная в листинге 12.7, проверяет, есть ли в текущей папке файл с именем digs.

Листинг 12.7

#include <iostreani> finclude <fstream> #include <iomanip> using namespace std: int mainC){

fstream out( digs .ios::out ios::norep1ace); if(out.faiH))

cout Файл уже существует endl: out.closeO: return 0:

Теперь после знакомства с открытием файлов можно попробовать их копировать с помо1цью собственной версии команды сору операционной системы. Дублировать файлы крайне просто, если воспользоваться их сходством с потоками. Нужно, очевидно, читать символ из одного файла и записывать его в другой. Все это легко проделать в цикле:

whi1e(in.get(ch)) out.put(ch):

Здесь in - файл-источник, а out - файл-копия. Этот цикл кажется крайне простым и поэтому, быть может, требует длинных пояснений. Удивляет, прежде всего, условие выполнения цикла whi 1е(), ведь in.get(ch), как и всякая операция ввода, возвращает ссылку на объект (в наиюм случае - класса i fstream или fstream). Делается это для того, чтобы можно было соединить в одну



1 ... 29 30 31 [ 32 ] 33 34 35 ... 37

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика