Файл: Сравнительный анализ описания данных для различных языков программирования ( ЯЗЫКИ ПРОГРАММИРОВАНИЯ И ИХ КЛАССИФИКАЦИЯ).pdf
Добавлен: 31.03.2023
Просмотров: 291
Скачиваний: 1
Ортогональность. Ортогональность означает, что любые возможные комбинации различных языковых конструкций будут осмысленными, без непредвиденных ограничений или неожиданного поведения, возникающих в результате взаимодействия конструкций или контекста использования.
Структурированность потока управления в программе. Порядок передач управления между операторами программы должен быть удобен для чтения и понимания человеком. Речь идет об ограниченном использовании оператора безусловного перехода goto и применении специальных структур управления [11].
Легкость создания программ, которая отражает удобство языка для написания программ в конкретной предметной области. Поскольку в каждой предметной области программы имеют свою специфику, очень важно выбирать язык, который ее учитывает. Например, если речь идет об исследовании искусственного интеллекта, следует использовать язык Prolog или LISP, а при решении задач научных вычислений — язык Fortran. Как и следовало ожидать, характеристики, от которых зависит этот показатель, во многом пересекаются с характеристиками читабельности, ведь чтение текста является неотъемлемым атрибутом как процесса создания, так и процесса понимания программы [12].
Естественность для приложений. Синтаксис языка должен способствовать легкому и прозрачному отображению в программах алгоритмических структур предметной области. Любой из типовых алгоритмов (последовательный, разветвляющийся, циклический, параллельный) имеет естественную структуру, которая должна поддерживаться программными операторами реализующего языка. Язык должен предоставлять структуры данных, операции и структуры управления, адекватные решаемой задаче. Естественность — это одна из важнейших причин популярности того или иного языка. Язык, ориентированный на характерные черты предметной области, может сильно упростить создание для нее программных приложений.
Поддержка абстракций. Абстракция является инструментом определения сложных структур данных и действий, при использовании которого гарантируется простота, а также игнорируются многие второстепенные детали. Абстракция устраняет пробел между структурами данных и операциями, характерными для решения задачи, и конкретными структурами данных и операциями, встроенными в язык программирования. Например, при написании информационной системы института требуются абстрактные структуры данных студент, курс, профессор, расписание и абстрактные операции записать студента на курс и спланировать расписание для курса. Программист должен создать программные реализации этих абстракций с использованием реального языка программирования, в котором изначально они отсутствуют. После этого программные абстракции можно использовать как новые элементы и в других частях программы, не вникая в их фактическую реализацию. Ясно, что язык должен обеспечивать такую возможность [13].
Выразительность, которая может характеризовать две возможности. С одной стороны, она означает наличие очень мощных средств для представления структур данных и действий, описывающих большой объем вычислений с помощью очень маленькой программы (языки APL, Snobol, Icon, SETL). С другой стороны, выразительность позволяет записывать вычисления в более удобной и компактной форме.
Надежность. В общем случае, надежность — это способность программы выполнять требуемые функции при заданных условиях и в течение определенного периода времени. Обычно уровень надежности характеризуется степенью автоматического обнаружения ошибок, которую обеспечивают транслятор и операционная среда выполнения программы. Надежный язык позволяет выявлять большинство ошибок во время трансляции программы, а не во время ее выполнения, поскольку это минимизирует стоимость ошибок. Опишем факторы, имеющие сильное влияние на надежность программ [14].
Проверка типов. Принципиальным средством достижения высокой надежности языка является система типизации данных. В ходе проверки типов анализируется совместимость типов в программе. Разные языки обеспечивают разную полноту проверки типов. Достаточно слабой считают проверку типов в языке С. Языки с динамической типизацией вообще относят эту проверку только к периоду выполнения программы [15].
Обработка исключений. Исключением называют аварийное событие, которое обнаруживается во время выполнения программы (аппаратом исключений). В результате авария устраняется, и программа продолжает работу. Подобный механизм значительно повышает надежность вычислений.
Совмещение имен. Совмещением имен называют наличие нескольких разных имен у одной и той же ячейки памяти. Во многих языках переменным разрешается иметь по паре имен: обычное прямое имя и косвенное имя (на базе указателя). С одной стороны, совмещение имен может приводить к понижению надежности программы. С другой стороны, эта возможность повышает гибкость программирования и компенсирует недочеты жестких схем типизации.
В завершение необходимо отметить, что читабельность и легкость создания прямо влияют на надежность программы. Чем выше значения этих показателей, тем надежнее будет программа.
2.2. Сравнительный анализ описания данных для различных языков программирования
2.2.1. Простые типы данных
Так как алгоритмы определяют, как и в каком порядке происходит обработка, то структуры данных должны четко описывать, что именно обрабатывается, - и на это описание затрачивается значительная часть усилий программиста. Учитывая, что программой являются алгоритмы и структуры данных, то в языках программирования должны быть средства описания алгоритмов и средства описания данных. При этом то, насколько удобно и эффективно можно описать данные, зависит от встроенных в язык программирования возможностей [16].
Некоторые языки программирования требуют, чтобы до их использования все переменные, аргументы и возвращаемые значения функций и процедур были объявлены с указанием типа (Pascal, Basic, С/C++). Другие (Лисп, PHP) этого не требуют, переменная в них приобретает тип в зависимости от первого присвоенного ей значения. При этом в большинстве языков программирования переменные могут иметь только один тип во все время их существования. Но в некоторых тип может меняться во время исполнения программы. В первом случае говорят о статической, во втором случае говорят о динамической типизации. Языки программирования могут быть как с явной, так и с неявной системой типов. В первом случае четко фиксируется, к какому типу относится та или иная переменная или константа, во втором об этом отдельно речь не идет, тем не менее данные обычно обрабатываются по-разному. И у первого, и у второго подхода имеются как достоинства, так и недостатки. Динамическая неявная типизация расширяет возможности использования переменных и избавляет программиста от хлопот, связанных с объявлением и контролем соответствия типов. Кроме того, данный подход позволяет создавать более универсальные и проще интегрируемые программные модули. Однако это требует от программиста большей ответственности, поскольку во время выполнения программы возможны неожиданности вроде попыток перемножить две строки или разделить число на логическое значение. При статической типизации такие ошибки обнаружились бы на этапе компиляции. И чем больше размер программы, тем более острой становится эта проблема. В некоторых языках само имя переменной свидетельствует о типе переменной. Например, в некоторых диалектах Basic имя переменной A% свидетельствует, что она целочисленная, а A$— что строковая. В языке Perl переменная в зависимости от типа получает значок перед именем: для скалярных переменных это $, для массивов — @, для ассоциативных массивов — % [17].
Под простыми, или базовыми, типами данных в языках программирования понимаются объекты (переменные или константы), которые не имеют доступной программисту внутренней структуры. В различных языках имеются разные наборы встроенных базовых типов данных [18].
Представление чисел в наиболее популярны на сегодняшний день языках программирования приведено в таблице 1.
Таблица 1 – Представление чисел в языках программирования
|
Тип данных переменной |
C# |
Pascal |
Basic |
|
Целочисленный |
int |
integer |
integer |
|
Действительный |
double |
real |
Double |
|
Логический |
bool |
boolean |
boolean |
|
Хранение одиночного символа |
char |
char |
- |
|
Строка |
String |
String |
String |
|
Указатель - константа или переменная, которая задает адрес в памяти, где располагаются некоторые другие объекты (данные, функция) |
int* pA |
C:=@pA; |
- |
|
Перечисления |
enum DAY {Monday, Tuesday, Wednesday } |
Type DAY=(Monday, Tuesday, Wednesday) |
enum DAY{ Monday, Tuesday, Wednesday } |
Программный код объявления переменной и присвоение ей значения на языках программирования:
1 C#:
int i=10;
2 Pascal:
var I :integer;
I:=10;
3 Basic:
Dim I as integer
I=10
2.2.2. Массивы
Массив представляет собой проиндексированный набор однородных элементов [19]. Объявление одномерного массива из 10 элементов в различных языках программирования может выглядеть так:
1 Basic:
Dim Vector (10) as integer
2 Pascal:
Var Vector = array [1..10] of integer;
3 C#:
Vector= new int[10];
Описание двумерного массива приведено ниже:
1 Basic:
Dim M(3, 4) as integer
2 Pascal:
Var M = array [1..3,1..4] of integer;
3 C#:
M= new int[3][4];
Необходимо отметить, что массивы могут быть статическими и динамическими. При объявлении статического массива программист должен знать его размер заранее.
Динамический массив это массив, размер которого определяется при выполнении программы, тогда же происходит и выделение памяти под него. В некоторых языках программирования индекс может изменяться лишь в пределах от единицы до N (Basic) или от нуля до N – 1 (С#). Это обусловлено смещением элемента от адреса начала массива в памяти. В других языках, например Pascal допускается устанавливать произвольные границы изменения индекса для каждого измерения.
Базовая операция для массива — взятие элемента по индексу. Поэтому массив представляет собой структуру данных с произвольным доступом - в любой момент за одинаковое количество времени возможен доступ к любому месту в нем. Как правило, сравнение массивов одной операцией недопустимо [20].
Программный код объявления и заполнения массива на различных языках программирования.
1 C#:
{
Console.WriteLine("Введите n");
int n = int.Parse(Console.ReadLine());
int[] a = new int[n];
for(int i = 0;i<n;i++)
{
Console.WriteLine("Введите {0}-й элемент", i + 1);
a[i] = int.Parse(Console.ReadLine());
}
}
2 Pascal:
var a:array[1..100] of integer;
I,n: integer;
begin
writeln(' Введите n: ');
readln(n);
for i:=1 to n do begin
write(' Введите {',i,'}-й элемент');
readln(a[i]);
end;
end;
3 Basic:
Dim n as integer;
Console.WriteLine("Введите n:", n)
n = Integer.Parse(Console.ReadLine())
DIM a(n)
For i = 1 To n
Console.WriteLine("Введите {0}-й элемент", i)
a(i) = Integer.Parse(Console.ReadLine())
Next
2.2.3. Записи
Весьма важной и популярной структурой данных в языках программирования являются записи (структура).
Запись представляет собой поименованную совокупность разнотипных данных, отдельные элементы которой принято называть полями. Доступ к элементу возможен по указанию имени всей структуры и имени поля. Объявление структур часто происходит с определением нового типа данных.
Рассмотрим пример записи на различных языках:
1 Pascal:
Type Book =record
price: real;
title: string[50];
author: string[50];
end;
var b: Book;
begin
writeln ('введите сведения об авторе');
readln (b. author);
writeln ('введите сведения о названии книги’);
readln (b. title);
writeln ('введите сведения о цене’);
readln (b. price);
end;
2 C#:
public struct Book
{
public decimal price;
public string title;
public string author;
public void DisplayInfo()
{
Console.WriteLine($"author: {author} title: {title} price: {price}");
}
}
class Program
{
static void Main(string[] args)
{
Book b;
b. author= Console.ReadLine();
b. title= Console.ReadLine();
b.price= Console.ReadLine();
b.DisplayInfo();
Console.ReadKey();
}
3 Basic – Отсутствует понятие структуры, доступно только в Visual Basic. Net.
Как видно из вышеописанного при помощи Pascal получается более трудоемкий программный код объявления записи, в отличие от C#.
2.2.4. Список
Следующей важнейшей структурой данных являются списки. Такого рода структуры в языках программирования весьма разнообразны. Простейшей является линейный односвязный список который представляет собой набор идущих друг за другом элементов, при записи разделяемых пробелом, запятой или иным знаком, например: [a,b,c,d,e]
В отличие от массивов, список, как правило, не предполагает возможности взятия элемента по его номеру.
Для взятия элемента из середины можно начать последовательно перебирать их с первого, пока не будет найден искомый.
В этом смысле список представляет собой структуру с последовательным доступом. Для полноты вводится также понятие пустого списка, или списка, не содержащего элементов, для которого используется специальное обозначение.
Основными операциями над списками служат:
- взятие первого элемента - головы списка;
- взятие остатка списка, также являющегося списком, или его хвоста;
- добавление элемента в список;θ
- удаление заданного элемента из списка;
- проверка на вхождение элемента в список;
- приписывание списка к списку;θподсчет количества элементов списка.
В некоторых языках списки можно сравнивать одной операцией.
Список является динамической структурой данных - его размер может меняться в ходе исполнения программы. Список является также так называемой рекурсивной структурой — его понятие может быть определено рекурсивно следующим образом: пустой список является списком, кроме этого список — это элемент-голова, за которым идет, возможно пустой хвост-список. В силу этого для обработки списков хорошо подходят рекурсивные программы.