Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Разработка комплексов программ на языке С для решения прикладных задач. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
12.08.2026
Размер:
828 Кб
Скачать
☆

input = fopen("D:/c/text.txt", "rt"); if (input == NULL) {

printf("Error opening file"); _getch();

exit(0);

}

while (fscanf(input, "%c", &c) == 1) { fprintf(stdout, "%c", c);

}

fclose(input); _getch();

}

Контрольные вопросы

1.Какие типы файлов существуют в языке С?

2.Каким образом должен быть описан указатель на файл?

3.Какая функция открывает файл?

4.С помощью каких функций можно закрыть открытые

впрограмме файлы?

5.Каким образом указывается тип доступа к файлу (чтение, запись, изменение и т.д.)?

6.Перечислите различия между двоичными и текстовыми файлами.

7.Запишите фрагмент программы, создающий текстовый файл, содержащий n вещественных чисел.

8.Рассмотрим фрагмент программы:

FILE *f;

f = fopen("a1.dat", "r+"); while (!feof(f))

{

fscanf(f, "%d",&k); printf ("%d",k);

}

Укажите:

а) имя открываемого в фрагменте файла;

61

б) с каким атрибутом доступа открыт файл; с) какого типа данные считываются из файла.

9.Возможно ли организовать прямой доступ к файлу в язы-

ке С?

10.Опишите работу функции fread.

11.Опишите работу функции fwrite.

12.В двоичном файле записано 5*8 вещественных чисел.

Скакой позиции расположен элемент, находящийся в строке с номером 3 и столбце с номером 2?

13.Запишите фрагмент программы, создающий двоичный файл, содержащий n вещественных чисел.

62

5. ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ

Объектно-ориентированное или объектное программирование (ООП) – парадигма программирования, в которой основными концепциями являются понятия объектов и классов. Под парадигмой программирования понимается система идей и понятий, определяющая стиль написания компьютерных программ, а также образ мышления программиста.

5.1. Основные понятия

Абстракция данных – подход к обработке данных по принципу «черного ящика». Данные обрабатываются функцией высокого уровня с помощью вызова функций более низкого уровня. Это позволяет работать с объектами, не вдаваясь в особенности их реализации.

Пример задания абстрактной функции (без ее реализации в данном классе) имеет вид:

int Calculate();

Функция уже известна, но ее конкретная реализация будет выполнена на более низком уровне – в классах-потомках.

Класс – это тип, описывающий структуру объектов-эк- земпляров. Под классом подразумевается некая сущность, которая задает общее поведение объектов этого класса (через методы), а также позволяет хранить состояние объекта (используя поля класса). Класс можно сравнить со схемой, согласно которой создаются объекты этого класса. Обычно классы разрабатывают таким образом, чтобы их объекты соответствовали объектам предметной области.

Пример объявления класса class Client {

}

63

Члены класса. Класс определяется как список членов своего класса. К членам класса относятся его поля (свойства) и функции (методы). Для каждого члена класса можно установить соответствующую область доступа (access control level). Область доступа члена класса определяет участки кода, из которых

кэтому члену будет возможно обращение.

Вобъектно-ориентированном расширении языка программирования С поддерживаются следующие области доступа:

private (закрытый, внутренний член класса) – обращения допускаются только из методов класса, в котором этот член определен; наследники класса уже не смогут получить доступ к этому члену;

protected (защищенный, внутренний член иерархии классов) – обращения допускаются из методов класса, в котором этот член определен, или из любых его классов-наследников;

public (открытый член класса) – обращения допускаются из любого кода.

Пример задания членов класса. class Client {

private string firstName; private string lastName; private DateTime birthday;

public Client(string parFirstName, string par LastName, DateTime parBirthday)

{

firstName = parFirstName; lastName = parLastName; birthday = parBirthday;

}

public int CalculateAge(DateTime parDate)

{

return (parDate – birthday).Year;

}

Интерфейс класса – это набор публичных полей и методов класса, к которым можно обращаться из других классов, частей программы. Для рассмотренного выше примера в интерфейс класса будут входить конструктор класса: Client (string

64

parFirstName, string par LastName, DateTime parBirthday) и метод вычисления возраста: public int CalculateAge (DateTime parDate).

Прототип – это объект-образец, по образу и подобию которого создаются другие объекты. Если в класс, описанный в предыдущем примере, добавить метод Clone, который будет возвращать экземпляр объекта, инициированный текущими значениями полей, то можно сказать, что класс является прототипом.

Пример создания класса-прототипа class Client {

publicClientClone()

{

return new Client(this.firstName, this.lastName, this.birthday);

}

Абстрактный класс – класс, содержащий хотя бы один абстрактный метод. Абстрактный метод не реализуется для класса, в котором описан, однако должен быть реализован для его неабстрактных потомков.

В некоторых языках объектно-ориентированного программирования создавать экземпляры абстрактных классов запрещено, в других это допускается, но обращение к абстрактному методу объекта этого класса в процессе выполнения программы приведет к ошибке. Во многих языках допустимо объявить любой класс абстрактным, даже если в нем нет абстрактных методов, именно для запрещения создания экземпляров.

Абстрактный класс можно рассматривать в качестве интерфейса к семейству классов, порожденному им, но в отличие от классического интерфейса абстрактный класс может иметь определенные методы, а также свойства.

Абстрактные методы часто являются и виртуальными (переопределяемыми в потомках), в связи с чем понятия «абстрактный» и «виртуальный» иногда путают.

Пример объявления абстрактного класса. abstract class Client {

private string firstName; private string lastName; private DateTime birthday;

public Client(string parFirstName, string par LastName,

65

DateTime parBirthday)

{

firstName = parFirstName; lastName = parLastName; birthday = parBirthday;

}

public abstract int CalculateAge(DateTime parDate);

}

Объект, наряду с понятием «класс», является основополагающим понятием объектно-ориентированного подхода. Под объектом подразумевается некоторая сущность, обладающая состоянием и поведением. Объекты могут принадлежать одному или нескольким классам, которые, в свою очередь, определяют поведение объекта. Время с момента создания объекта до его уничтожения называется временем жизни объекта.

Инстанцирование – создание экземпляра класса; в отличие от слова «создание» применяется не к объекту, а к классу: говорят «создать экземпляр класса» или «инстанцировать класс».

Экземпляр класса – это конкретный описанный объект (существующий в памяти). Класс описывает свойства и методы, которые будут доступны объекту, относящемуся к этому классу. Экземпляры используют для представления конкретных сущностей реального мира. Создание экземпляра класса может осуществляться операцией new.

Пример объявления экземпляра класса

Client client = new Client("Иван", "Иванов", DateTime. Parse("10.04.1983"));

5.2. Концепции объектно-ориентированного программирования

В центре ООП находится понятие объекта. Объект – это сущность, которой можно посылать сообщения (вызывать методы) и которая может на них реагировать, используя свои данные. Данные объекта скрыты от остальной программы. Сокры-

66

тие данных (объявление для них области видимости «protected» или «private») называется инкапсуляцией. Однако наличие инкапсуляции еще не означает объектной ориентированности языка, для этого требуется наличие наследования. Но в полной мере преимущества ООП проявляются только в том случае, когда в языке программирования реализован полиморфизм – возможность объектов с одинаковой спецификацией иметь различную реализацию.

Кратко суть концепции объектно-ориентированного программирования можно выразить следующими тезисами. Система состоит из объектов. Объекты некоторым образом взаимодействуют между собой. Каждый объект характеризуется своим состоянием и поведением. Состояние объекта задается значением полей данных. Поведение объекта задается методами.

Наследование – один из трех важнейших механизмов объ- ектно-ориентированного программирования (наряду с инкапсуляцией и полиморфизмом), позволяющий описать новый класс на основе уже существующего (родительского), при этом свойства и функциональность родительского класса наследуются новым классом. Другими словами, класс-наследник реализует спецификацию уже существующего (базового) класса. Это позволяет обращаться с объектами класса-наследника точно так же, как с объектами базового класса.

Класс, от которого произошло наследование, называется базовым или родительским. Классы, которые произошли от базового, называются потомками, наследниками или производными классами.

Простейший пример наследования. class Classl {

}

class Class2: Classl {

}

Инкапсуляция – свойство языка программирования, позволяющее объединить данные и код в объект и скрыть реализацию объекта от пользователя. При этом пользователю предоставляется только спецификация (интерфейс) объекта. Пользователь

67

может взаимодействовать с объектом только через этот интерфейс. Инкапсуляция может быть достигнута простейшими организационными мерами. Знание того, что «вот так делать нельзя», иногда является самым эффективным средством инкапсуляции.

Пример класса реализации комплексного числа

//Класс комплексного числа class Complex {

//Целая часть числа private double re;

//Мнимая часть числа private double im;

//Конструктор с инициализацией public Complex (double i_re, double i_im)

{

re = i_re; im = i_im;

}

//Сложение комплексных чисел

//parComplexl – Первое комплексное число

//parComplex2 – Второе комплексное число

public static Complex operator+(Complex parComplexl, Complex parComplex2)

{

return new Complex(parComplexl.re + parComplex2.re, parComplexl.im + parComplex2.im);

}

}

Пример использования класса комплексного числа

Complex complexl = new Complex(1,1); Complex complex2 = new Complex(2,2); Complex complex3 = complexl + complex2;

Следует особо отметить, что одна из наиболее распространенных ошибок заключается в попытке делать сокрытие реализации только ради сокрытия. Целями, достойными усилий, являются: достижение предельной локализации изменений при их необходимости; прогнозируемость изменений (какие изменения в коде надо сделать для заданного изменения функциональности); прогнозируемость последствий изменений.

Полиморфизм – взаимозаменяемость объектов с одинаковым интерфейсом. Язык программирования поддерживает по-

68

лиморфизм, если классы с одинаковой спецификацией могут иметь различную реализацию, например реализация класса может быть изменена в процессе наследования. Кратко смысл полиморфизма можно выразить фразой: «один интерфейс, множество методов».

Полиморфизм позволяет писать более абстрактные программы и повысить коэффициент повторного использования кода. Общие свойства объектов объединяются в систему, которую могут называть по-разному: интерфейс, класс. Общность имеет внешнее и внутреннее выражения. Внешне общность проявляется как одинаковый набор методов с одинаковыми именами и сигнатурами (типами аргументов и результатов). Внутренняя общность есть одинаковая функциональность методов. Ее можно описать интуитивно или выразить в виде строгих законов, правил, которым должны подчиняться методы.

Возможность приписывать разную функциональность одному методу (функции, операции) называется перегрузкой метода.

Пример перегрузки метода для арифметической операции.

//Класс для определения произвольной арифметической операции //с использованием двух переменных class Operation {

//Вычисление произвольной операции с участием двух пе-

ременных public virtual float Calculate(float parArgumentl, float parArgument2);

}

//Сложение двух переменных class Add: Operation {

//Сложение с использованием двух переменных public override float Calculate(float parArgumentl, float parArgument2)

{

return parArgumentl + parArgument2;

}

}

//Сложение двух переменных class Sub: Operation {

//Сложение с использованием двух переменных public override float Calculate(float parArgumentl, float parArgument2)

{

69

return parArgumentl – parArgument2;

}

Вприведенном примере класс «Operation» определяет виртуальный метод, который подразумевает какое-то арифметическое вычисление с использованием двух переменных и возвращение результата. Класс «Add» является наследником «Operaion» и перегружает метод «Calculate» как операцию сложения двух переменных. Класс «Sub» также является наследником «Operation» и перегружает метод «Calculate» как операцию вычитания.

Простейший пример использования полиморфизма.

Operation operation = new Add();

float resultl = operation.Calculate(l.0f, 1.0f); operation = new Sub();

float result2 = operation. Calculate(l.0f, 1.0f);

Впримере объявляется локальная переменная «operation»

стипом родительского класса «Operation» и ей присваивается экземпляр класса «Add». Данное присвоение разрешается и является одним из свойств наследования: переменным с типом родительского класса можно присваивать экземпляры классовнаследников, но не наоборот. В результате вызова метода «Calculate» переменная «resultl» примет значение 2.Of, так как в данный момент переменная «operation» является экземпляром класса «Add», где вычисление определено как сложение. Далее переменной «operation» присваивается значение экземпляра «Sub» и вызов метода «Calculate» возвратит значение O.Of, как результат вызова метода из класса «Sub».

Конструктор – специальный метод в объектно-ориентиро- ванном программировании, служащий для инициализации объекта при его создании (например, выделения памяти). Можно сказать, что конструктором называется тот метод класса, который вызывается автоматически при создании экземпляра класса. В зависимости от варианта объявления конструктора различают следующие их виды:

конструктор по умолчанию – конструктор, не имеющий обязательных аргументов; в отсутствие явно заданного конст-

70

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]