Программирование >>  Составные структуры данных 

1 ... 20 21 22 [ 23 ] 24 25 26 ... 225


Многие операции, связанные со стандартными типами данных (такие как арифметические), встроены в язык С++. Другие операции существуют в виде функций, которые определены в стандартных библиотеках функций. Остальные операции реализуются в функциях С++, которые определены в программах (см. программу 3.1). Таким образом, концепция типа данных связана не только со встроенными типами (целые, значения с плавающей точкой и символы). Разработчики часто задают собственные типы данных, что служит эффективным средством организации программных средств. При описании простой функции С++ в результате создается новый тип данных. Реализуемая функцией операция добавляется к операциям, определенным для типов данных, которые представлены аргументами функции. В некотором смысле, каждая программа С++ является типом данных - списком множеств значений (встроенных или других типов) и связанных с ними операций (функций). Возможно, эта концепция слишком обобщена, чтобы быть полезной, но мы убедимся в ценности упрощенного осмысления программ как типов данных.

Программа 3.1 Описание функций

Механизм, используемый в С++ для реализации новых операций с данными, представляет собой определение функций (function definition), которое демонстрируется ниже.

Все функции имеют список аргументов и, возможно, возвращаемое значение (return value). Рассматриваемая функция Ig имеет один аргумент и возвращаемое значение. И то и другое относится к типу int. Функция main не принимает аргументов и возвращает значение типа int (по умолчанию - значение О, которое указывает на успешное завершение).

Функция объявляется (declare) путем присвоения ей имени и типов возвращаемых значений. Первая строка программы ссылается на библиотечный файл, который содержит объявления cout, << и endl. Вторая строка объявляет функцию Ig. Если функция описана до ее использования (см. следующий абзац), объявление необязательно. Объявление предоставляет информацию, необходимую, чтобы другие функции вызывали данную с использованием аргументов допустимого типа. Вызывающая функция может использовать данную функцию в выражении подобно использованию переменных, имеющих тот же тип возвращаемых значений.

Функции определяются (define) посредством кода С++. Все программы на С++ содержат описание функции main, а данном примере также имеется описание функции Ig. В описании функции указываются имена аргументов (называемых параметрами) и выражения, реализующие вычисления с этими именами, как если бы они были локальными переменными. При вызове функции эти переменные инициализируются, принимая значения передаваемых аргументов, после чего выполняется код функции. Оператор return служит командой завершения выполнения функции и передачи возвращаемого значения вызывающей функции. Обычно вызывающая функция не испытывает других воздействий, хотя нам встретится много исключений из этого правила.

Разграничение описаний и объявлений создает гибкость в организации программ. Например, они могут содержаться в разных файлах (см. текст). Кроме того, в простой программе, подобной примеру, описание функции Ig можно поместить перед описанием main и опустить объявление.

#include <iostreani.h> int Ig (int) ; int mainO {



for (int N = 1000; N <= 1000000000; N *= 10) cout lg{N) N endl;

int lg{int N) {

for (int i = 0; N > 0; i++, N /= 2) ; return i;

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

Программа 3.2 реализует несложные вычисления с использованием простых типов данных, описанных с помощью операции typedef и функции (которая сама реализована посредством библиотеки функций). Главная функция ссылается на тип данных, а не встроенный тип чисел. Не указывая тип чисел, обрабатываемых программой, мы расширяем ее потенциальную область применения. Например, подобный подход может продлить время жизни программы. Когда новое обстоятельство (новое приложение, компилятор или компьютер) приводит к появлению нового типа чисел, который придется использовать, можно будет обновить программу за счет простого изменения типа данных.

Программа 3.2 Типы чисел

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

\<i<N

1</<Л \<i<N

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

Объявление typedef используется для локализации ссылки на тот факт, что данные имеют тип int. Например, typedef и описание функции randNum могут содержаться в отдельном файле (на который ссылается директива include). Впоследствии можно будет использовать программу для тестирования случайных чисел другого типа путем изменения этого файла (см. текст).



Независимо от типа данных программа использует тип int для индексов и тип float для вычисления среднего и среднеквадратичного отклонения. Она действует только при условии, что заданы преобразования данных в тип float.

#include <iostreeuii.h> #include <stdlib.h> #include <math.h> typedef int Niimber; Ntmiber randNmn ()

{ return randO ; } int main(int argc, char *argv[]) { int N = atoi(argv[l]); float ml = 0.0, m2 = 0.0; for (int i = 0; i < N; i++) {

Ntimber x = randNum() ; ml += ((float) x)/N; m2 += ((float) x*x)/N;

cout Avg. : ml endl;

cout Std. dev.: sqrt(m2-ml*ml) endl;

Этот пример не представляет полного решения задачи разработки программ вычисления средних величин и среднеквадратичных отклонений, не зависящих от типа данных; подобная цель и не ставилась. Например, программа требует преобразования чисел типа Number в тип float, чтобы они могли участвовать в вычислении среднего значения и отклонения. В данном виде программа зависима от приведения к типу float, присущего встроенному типу int. Вообще говоря, можно явно описать такое приведение для любого типа, обозначаемого именем Number.

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

Имеет смысл подробно остановиться на способе изменения типа данных таким образом, чтобы программа 3.2 обрабатывала другие типы чисел, скажем, float вместо int. Язык С++ предлагает ряд механизмов, позволяющих воспользоваться тем, что ссылки на тип данных локализованы. Для такой небольшой программы проще всего сделать копию файла, затем изменить объявление typedef int Number на typedef float Number и тело процедуры randNum, чтобы оно содержало оператор return 1.0*rand()/ RAND MAX (при этом будут возвращаться случайные числа с плавающей точкой в диапазоне от О до 1). Однако даже для такой простой программы этот подход неудобен, поскольку подразумевает наличия двух копий программы. Все последующие изменения программы должны быть отражены в обеих копиях. В С++ существует альтернативное решение - поместить описания typedef и randNum в отдельный файл заголовков (header file) с именем, например, Number.h и заменить их директивой

#include Number.h



1 ... 20 21 22 [ 23 ] 24 25 26 ... 225

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