Лекция 7 (1160840), страница 2
Текст из файла (страница 2)
С точки зрения семантики разницы нет, однако есть небольшая разница в синтаксисе. Язык командного интерпретатора SHELL явный терминал (done, if, fi)
Начало – done if
Конец - done fi
PROCEDURE p
Блок p
END p.
Если END забыт, разобраться в коде намного проще.
Рассмотрим все операторы поочередно.
Ветвления
Простое ветвление
Простое ветвление (в языке программирования без явных терминаторов):
Простое ветвление (в языке программирования с явными терминаторами)
Такая конструкция впервые появилась в Алгол-60. Заметим неприятность: конструкцию, например, вот такую:
if(B1) if(B2) s1; else s2;
можно понимать двояко. Полагается записывать такого рода вещи с отступами:
if(B1)
if(B2)
s1;
else
s2;
В языках с явными терминаторами такой проблемы не будет:
if B1 then
if B2 then
s1 end if
else
s2
end if
Многовариантное ветвление
На Си-подобном языке подобное ветвление будет выглядеть вот так:
Последовательный опрос вариантов:
if(B1)
s1
else if(B2)
s2;
else if(B3)
s3;
else sN;
Подчеркиваем синтаксическую вложенность:
if(B1)
s1
else
if(B2)
s2;
else
if(B3)
s3;
else sN;
Первый вариант, как показывает практика, воспринимается легче.
А записывать такую конструкцию на Modula-2 «неприятно»:
IF B1 THEN
S1
ELSE IF B2 THEN
S2
ELSE IF B3 THEN
S3
ELSE
S4
ENDIF ENDIF ENDIF
Оператор выбора
Оператор выбора добавляют практически во все известные языки программирования (несмотря на то, что его можно заменить многочисленными if-ами ).
Modula-2
CASE expr OF
Список значений1: s11; s12; … ; s1N |
Список значений2: s21; s22; … ; s2N |
….еще списки значений
ELSE ……
END
Ввиду возникающей синтаксической неоднозначности со списком значений вводится спецсимвол – вертикальная черта |
В языке Ада чуть более сложный синтаксис:
case expr of
when список1 =>
s11; s12; ….
when список2 =>
s21; s22; ….
……………………………………..
when other =>
………………………
end case
Когда список значений достаточно «плотный», можно запрограммировать задачку гораздо более эффективно (не на основе многовариантного ветвления, а на основе оператора перехода).
Для любого алгоритма, как мы знаем, необходимы операторы
-присваивания
-последовательного выполнения
-циклования
Ну и понятно, что в языке должно присутствовать понятие выражения.
Теорема
ЛЮБУЮ управляющую схему можно преобразовать в ЭКВИВАЛЕНТНУЮ ей схему, содержащую ТОЛЬКО 3 вышеперечисленных элемента.
Оператор «переключателя»
switch(expr) S
Чаще всего S – это блок, внутри которого находятся метки особого рода:
case конструкции;
default: …
Замечание(!)
Если после каждого case не делать break, то выполнение будет продолжаться. И не удивляйтесь, если в этом случае выполнятся другие case.
switch(e){
case 1: s1;// тут надо все время делать break! Не поставить его сознательно можно очень редко.
……………….
case 2: s2;
}
Самое оригинальное решение этой проблемы было принято в Java: если break не поставить, то компилятор выругается. А если вдруг надо выйти из переключателя, придется ставить переход к другому case,
Все эти проблемы – следствие довольно убогой концепции переключателя в Си.
Циклы
Виды циклов:
-
«Пока» (while)
-
«До» (until, do while)
-
«for »
-
Управляемые пользователем
Примеры цикла while:
while B do S
while(B) S
while B loop ……… endloop
WHILE B DO ………… END
REPEAT
……
UNTIL
В Си-подобных языках:
do{S} while(B);
do S while(B);
//S – один оператор, B – условие продолжения
Смысл do –while – чисто для удобства
Циклы, управляемые пользователем – лучше всего они выглядят на Ада и Модула-2
Ада:
loop
…
endloop
Модула-2
LOOP
............
END
Си:
while(1) S;
for(;;)S
Циклы, управляемые пользователем – это бесконечные циклы, они обладают большим практическим смыслом. С точки зрения современных систем бесконечные циклы – не грех. Пример: сервисы, режим ожидания. Ведь хороший сервис работает вечно
Вспомним главный принцип структурного программирования: программа должна иметь один вход и один выход, в коде не должно быть оператора перехода. А в бесконечных циклах пользователь сам «управляет», когда выходить из цикла. Существует, кстати, оператор EXIT(Modula-2, ADA), который можно применять только внутри цикла.
Только такая конструкция:
If B then exit; end if;
//немного раздражает...:((
Был придуман синоним данной конструкции:
when B => exit;
Exit, break, continue – все это – ограниченная форма goto.
Неплохой выход из данной проблемы – выбросить исключение. Однако любое исключение – авария, и оно сильно усложняет проблему. Намного проще написать:
if(!B){обработка; return;},
Такие конструкции позволяют выбросить оператор goto.
Оберон и цикл «for »
1988 год – Никлаус Вирт в своей статье «покончил» с циклом for. В Обероне for не было.
1993 год. - Оберон-2 – цикл «for» вернулся.
Начиная с Алгол-60, цикл for есть практически во всех уважающих себя языках программирования(С, С++, C#, Java, JavaScript).
Синтаксис:
for(e1; e2; e3) S;
В любом языке e1, e2, e3 могут отсутствовать.
Пример:
for(;e2;) – получился цикл while
for(;;) - получился цикл, управляемый пользователем
Еще одна интересная форма цикла for, обнаруженная в современных языках: foreach.
for v in диапазон(L..R) loop ….. endloop
В Аде v последовательно пробегает значения от L до R.
foreach – средство пробегания по контейнеру.(Контейнер – средство хранения объектов любого типа). Очень полеззен. Когда мы ищем максимальный и минимальный элемент контейнера, например.
Представим себе массив:
int[ ] a = new int[N];
for(int i=0; i<a.Length; i++)
{
Что-то делаем с a[i]………
}.
Не лучший способ записи. Результат может зависеть от порядка промотра.
a[i] – это всегда некоторое вычисление. Что есть в C#, а в С не будет никогда? Конечно, проверка выхода за границу массива.
foreach(double v in a)
{
.............
};//управляющая переменная v просто последовательно принимает значение элементов массива.
В C# общий вид конструкции таков:
foreach(T x in C) {……………..}
В общем случае контейнер языка C# - это класс, поддерживающий интерфейс IEnumerable. И компилятор будет обрабатывать конструкции подобных классов специфичесим образом.
GetEnumerator(); //видает iterator, нужный для пробегания по элементам, а не по индексам.
Также у класса поддерживающего интерфейс IEnumerable, есть свойства Current и метод MoveNext()
Создатели языка Java сделали еще метод hasNext().