Главная

Категории:

ДомЗдоровьеЗоологияИнформатикаИскусствоИскусствоКомпьютерыКулинарияМаркетингМатематикаМедицинаМенеджментОбразованиеПедагогикаПитомцыПрограммированиеПроизводствоПромышленностьПсихологияРазноеРелигияСоциологияСпортСтатистикаТранспортФизикаФилософияФинансыХимияХоббиЭкологияЭкономикаЭлектроника






Замечание: Никогда не изменяйте содержимое заголовочных файлов. Это может привести к ошибкам компиляции в каждой создаваемой вами программе.


 

Работа с файлами

Небольшой объем информации можно передавать в программу с помощью клавиатуры, а результаты работы программы выводить на экран дисплея. Однако скоро становится ясным, что многие задачи требуют организации ввода/вывода информации из/в файл. Язык С++ поддерживает как старый способ работы с файлами, унаследованный от С, так и более новый, основанный на понятии потокового ввода/вывода. Файловый ввод/вывод в этом случае во многом подобен стандартному вводу/выводу (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::out Открыть файл для записи
ios::ate Переместить указатель в конец файла
ios::app Добавлять информацию к концу файла
ios::trunc Содержимое существующего файла удаляется
ios::binary Двоичный файл

 

Комбинация режимов чтения/записи создается при помощи оператора | (или):

ios::in|ios::out Открыть файл для чтения и записи
ios::out|ios::app Открыть файл для записи, но только для добавления

 

Очевидно, есть множество комбинаций режимов. Некоторые комбинации недопустимы: ios::in|ios::trunc - нельзя открыть файл для чтения, удалив его содержимое.

7. Классы в C++.

Определение классов.

Одним из основных отличий C++ от С является концепция классов. Классы похожи на структуры, но структура описывает только данные, связанные с ней, или свойства. Например:

#include <iostream.h>

// объявление структуры:

struct circle
{
int radius;
int color;
};

Void main()

{

circle MyCircle; // переменная типа circle
MyCircle.radius = 18; // свойство окружности ‑ радиус
MyCircle.color = 255; // свойство цвет
cout<< MyCircle.radius<< MyCircle.color;

}

Класс в C++ имеет как ассоциированные с ним свойства, так и функции (методы), которые выполняют некоторые действия. Например, вывода окружности на экран. Следовательно, в программе, которая использует объект MyCircle класса circle, можно написать следующий код:

MyCircle.radius = 20;
MyCircle.color = 255;
MyCircle.DisplayCircle() ;

& Имя класса, согласно общепринятому, но не обязательному правилу, начинается с заглавной буквы.

Первые два оператора присваивают значения свойствам radius и color объекта MyCircle, а третий ‑ вызывает функцию DisplayCircle().Перед тем как работать с классом, его следует объявить. Вот возможное объявление класса Сircle:

class Circle {

public:

Circle () ; // конструктор

void SetRadius(void) ; // прототипы функций классов (методов)

void GetRadius(void) ;

~Circle () ; // деструктор

private:

void CalculateArea(void); // прототип функции класса (метода)
int radius;

int color;

}; // не забывайте про точку с запятой!

 

Ключевое слово class показывает компилятору, что все находящееся в фигурных скобках принадлежит объявлению класса. Объявление класса содержит объявление элементов данных (например, int radius) и прототипы функций ‑ элементов класса. В объявлении класса Circle содержатся следующие элементы данных:

int radius;
int color;

Объявление также содержит пять прототипов функций-элементов:

Circle();

void SetRadius(void) ;
void GetRadius(void) ;
~Circle () ;
void CalculateArea(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;
HerCircle.color = 0;



Последнее изменение этой страницы: 2016-07-22

headinsider.info. Все права принадлежат авторам данных материалов.