Категории: ДомЗдоровьеЗоологияИнформатикаИскусствоИскусствоКомпьютерыКулинарияМаркетингМатематикаМедицинаМенеджментОбразованиеПедагогикаПитомцыПрограммированиеПроизводствоПромышленностьПсихологияРазноеРелигияСоциологияСпортСтатистикаТранспортФизикаФилософияФинансыХимияХоббиЭкологияЭкономикаЭлектроника |
Замечание: Никогда не изменяйте содержимое заголовочных файлов. Это может привести к ошибкам компиляции в каждой создаваемой вами программе.
Работа с файлами Небольшой объем информации можно передавать в программу с помощью клавиатуры, а результаты работы программы выводить на экран дисплея. Однако скоро становится ясным, что многие задачи требуют организации ввода/вывода информации из/в файл. Язык С++ поддерживает как старый способ работы с файлами, унаследованный от С, так и более новый, основанный на понятии потокового ввода/вывода. Файловый ввод/вывод в этом случае во многом подобен стандартному вводу/выводу (cin и cout) , основанному на понятии класса. Кратко о классах будет сказано далее, пока же мы рекомендуем запомнить некоторые формальные правила. Простой файловый ввод/вывод Для использования файлов следует: - подключить заголовочный файл fstream.h - создать объект класса fstream; - поставить этот объект в соответствие определенному файлу; - использовать его так же, как объект cin (для ввода) или cout (для вывода). Имя объекта, предназначенного для работы с файлом, может быть любым, допустимым в С++. Например, fout, outFile, didi и т.д. Рассмотрим возможные варианты работы с файлами на примерах. Вот так можно записать текст в файл. fstream fin; // создаем объект класса fstream fin.open("test",ios::in); // ставим ему в соответствие файл, открываем //для чтения fstream(fout);// допускается и такой тип объявления fout.open (”a.dat”, ios::out); // а в этот файл будем записывать char* str=”test string”; fout>>str; // записываем строку в файл // по окончанию работы с файлами, их следует закрыть: fin.close(); fout.close();
В приведенном примере можно совместить объявление и инициализацию файловой переменной: fstream fin("test",ios::in); fstream fout(”a.dat”, ios::out); Организовать корректное чтение из файла немного сложнее. Дело в том, что текстовый по типу файл заканчивается служебным символом eof – конец файла. При попытке прочесть информации больше, чем есть в файле, произойдет ошибка. Чтобы правильно произвести чтение из файла обычно используют цикл while() с проверкой конца файла встроенной функцией eof(). Следующий листинг показывает, как подсчитать количество символов в текстовом файле. setlocale(LC_ALL,"Russian"); fstream fin("test.txt",ios::in); char temp; int counter=0; while(!fin.eof()) // пока не конец файла { fin>>temp; //считываем символ в temp counter++; //подсчет символов } cout<<”всего символов в файле равно ”<<counter<<endl;
При записи следует выполнить схожие действия. Предположим, в файле 1.txt содержится последовательность целых чисел. Следует переписать их в другой файл – 2.txt.
#include <fstream.h> void main() { int temp, i=0; fstream f("1.txt", ios::in); fstream f2("2.txt", ios::out); while(!f.eof) // чтение в цикле с проверкой конца файла { f>>temp; i++; f2<<i<<" - "<<temp<<endl; } f.close(); f2.close(); }
В следующем примере рассмотрен процесс «пузырьковой» сортировки элементов массива, которые считываются из одного файла, например, 1.txt и уже отсортированные по возрастанию записываются в другой файл (2.txt).
#include <fstream.h> void main() { //Объявление вспомогательной переменной temp и счетчика, //счетчик в начале равен нулю int temp, counter=0; //Открываем файл для чтения fstream f("1.txt", ios::in); while(!f.eof) { f>>temp; counter++; } f.close(); //Объявление динамического массива типа int // с количеством элементов counter int *b=new int[counter]; // снова открываем файл и считываем числа в массив f.open("1.txt", ios::in); for(int i=0; i<counter; i++) { f>>b[i]; } // мы последовательно сравниваем // соседние элементы массива и, если надо, меняем их местами // Сортировку повторить // counter раз for(i=0; i<counter-1; i++) for(int j=i+1; j<counter; j++) if(b[i]>b[j]) { temp=b[i]; b[i]=b[j]; b[j]=temp; }
//Открываем второй файл на запись fstream f2("2.txt", ios::out);
//Выполняем запись в файл for(i=0; i<counter; i++) { f2<<b[i]<<" "; } f.close(); f2.close(); }
Тонкости работы с файлами Открывая файл на чтение, мы подразумеваем, что файл реально существует и находится в текущей папке с проектом (если мы запускаем программу из Visual Studio) или в папке с exe-файлом программы (если программа запускается вне Visual Studio). þ Помните – в имя файла можно включать и путь к нему, если это, конечно, нужно. Например: “c:\tmp|test.txt” А что произойдет, если файл по указанному пути не найден? В приведенных выше примерах, объявленные на чтение файлы будут созданы пустыми, а значения переменных, которые из него считываются – неопределенными. В результате при выполнении программы возникнет ошибка. Поможет предотвратить эту ситуацию использование функции is_open(). Функция возвращает значение TRUE, если файл был корректно открыт и FALSE в противном случае[7]. Вот как можно улучшить код чтения из файла, добавив проверку: fstream fin("test.txt",ios::in); if(!fin.is_open()) // если файл не открыт… { cout<<”Ошибка открытия файла”<<endl; return; // окончание работы программы } Пока мы ограничивались случаями только чтения (in) или только записи (out) из/в файлы. А как быть в других случаях, например, добавления данных в конец файла? В таблице 6.1 приведены константы режимов работы с файлом. Таблица 6.1. Константы режимов работы с файлами.
Комбинация режимов чтения/записи создается при помощи оператора | (или):
Очевидно, есть множество комбинаций режимов. Некоторые комбинации недопустимы: ios::in|ios::trunc - нельзя открыть файл для чтения, удалив его содержимое. 7. Классы в C++. Определение классов. Одним из основных отличий C++ от С является концепция классов. Классы похожи на структуры, но структура описывает только данные, связанные с ней, или свойства. Например: #include <iostream.h> // объявление структуры: struct circle Void main() { circle MyCircle; // переменная типа circle } Класс в C++ имеет как ассоциированные с ним свойства, так и функции (методы), которые выполняют некоторые действия. Например, вывода окружности на экран. Следовательно, в программе, которая использует объект MyCircle класса circle, можно написать следующий код: MyCircle.radius = 20; & Имя класса, согласно общепринятому, но не обязательному правилу, начинается с заглавной буквы. Первые два оператора присваивают значения свойствам radius и color объекта MyCircle, а третий ‑ вызывает функцию DisplayCircle().Перед тем как работать с классом, его следует объявить. Вот возможное объявление класса Сircle: class Circle { public: Circle () ; // конструктор void SetRadius(void) ; // прототипы функций классов (методов) void GetRadius(void) ; ~Circle () ; // деструктор private: void CalculateArea(void); // прототип функции класса (метода) int color; }; // не забывайте про точку с запятой!
Ключевое слово class показывает компилятору, что все находящееся в фигурных скобках принадлежит объявлению класса. Объявление класса содержит объявление элементов данных (например, int radius) и прототипы функций ‑ элементов класса. В объявлении класса Circle содержатся следующие элементы данных: int radius; Объявление также содержит пять прототипов функций-элементов: Circle(); void SetRadius(void) ; Первый и четвертый прототипы выглядят странно. Первый из них является прототипом функции конструктора[8]: Circle(); а другой – деструктора: ~Circle (); Обратите внимание на символ тильды (~), который предшествует прототипу функции деструктора. Запомните синтаксические правила для конструктора: - каждое объявление класса должно включать прототип функции конструктора; - имя функции конструктора должно совпадать с именем класса, а после него должны следовать круглые скобки; - не упоминайте никакого возвращаемого значения для функции конструктора (функция конструктора должна иметь тип void, но не нужно это указывать.); - функция конструктора должна располагаться под ключевым словом public. и деструктора: - имя функции деструктора должно совпадать с именем класса и ему должен предшествовать символ ~; - не указывайте никакого возвращаемого значения для функции деструктора; - функция деструктора не имеет никаких параметров; Прототипы функций и объявления элементов данных включаются в объявлении класса в разделы public (открытый) или private (закрытый). Ключевые слова public и private говорят компилятору о доступности элементов-функций и данных. Например, функция SetRadius()определена в разделе public, и это означает, что любая функция программы может вызвать функцию SetRadius(). Функция CalculateArea() определена в разделе private, и эту функцию можно вызвать только в коде функций-элементов класса Circle. Аналогично, поскольку элемент данных radius объявлен в разделе private, прямой доступ к нему (для установки или чтения его значения) возможен только в коде функций-элементов класса Circle. После того, как в программе дано определение класса, можно объявить и другой объект, класса Circle, например, с именем HerCircle.Делается это так: Circle HerCircle; Следующие операторы присваивают значения элементам данных HerCircle- radius и color: HerCircle.radius = 30; |
|||||||||||||||||||
Последнее изменение этой страницы: 2016-07-22 lectmania.ru. Все права принадлежат авторам данных материалов. В случае нарушения авторского права напишите нам сюда... |