OberonCore
https://forum.oberoncore.ru/

Книга Потопахина
https://forum.oberoncore.ru/viewtopic.php?f=35&t=5390
Страница 1 из 1

Автор:  snuk [ Среда, 15 Апрель, 2015 10:40 ]
Заголовок сообщения:  Книга Потопахина

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

Цитата:
Задача 12. Дан массив. Найти наибольшее значение.
Решение:
Идея такова, предположим, что максимальный элемент, это первый:
max:=mas[1]
Затем организуем цикл перебора от 2 до последнего элемента
и на каждом шагу цикла, если очередной элемент массива больше уже найденного максимального,
то пусть максимальному присваивается значение очередного элемента. Запишем программу полностью:
MODULE Example;
IMPORT In, StdLog;
PROCEDURE Calc*;
VAR
mas:ARRAY 100 OF INTEGER;
k, N, max:INTEGER;
BEGIN
In.Open;
N:=-1; Не понимаю, что в этой задаче есть N, тем более зачем N присваивать -1?
WHILE in.Done DO
N:=N+1; Тут зачем то прибавляем единицу
In.Int(mas[N]);
END;
N:=N-1; А тут мы ее снова убираем, написано зачем, но, в свете предыдущих манипуляций не могу понять и это.
k:=k+1;
max:=mas[0];
WHILE k<=N DO
IF mas[k]>max THEN
max:=mas[k];
END;
END;
k:=k+1;
END;
StdLog.Int(max);
END Calc;
END Example.

Примечания. Оператор N:=N-1 необходим для учета последней неудачной операции ввода. перед тем, как цикл
ввода WHILE завершит свою работу, выполнится попытка чтения из уже пустого потока, что создаст состояние
ошибки. переменная Done получит значение FALSE и цикл завершит свою работу, но тело цикла уже будет выполнено
и N вырастет на 1, эту 1 и надо вернуть назад.


Автор:  Alexander Shiryaev [ Среда, 15 Апрель, 2015 11:36 ]
Заголовок сообщения:  Re: Книга Потопахина

Если переписать так, то наверное будет понятнее:
Код:
MODULE Example;

   IMPORT In, StdLog;

   PROCEDURE Calc*;
      VAR k, n, max: INTEGER;
         mas: ARRAY 100 OF INTEGER;
   BEGIN
      (* заполнение массива введёнными данными *)
         n := 0;
         In.Open;
         IF In.Done THEN
            In.Int(mas[n]);
            WHILE In.Done DO
               n := n + 1;
               In.Int(mas[n])
            END
         END;

      (* n ---
         количество введёных данных (заполненных элементов массива) *)

      (* вычисление максимума, вывод результата *)
         IF n > 0 THEN
            max := mas[0];
            k := 1;
            WHILE k < n DO
               IF mas[k] > max THEN
                  max := mas[k]
               END;
               k := k + 1
            END;
            StdLog.Int(max)
         END
   END Calc;

END Example.

Автор:  snuk [ Четверг, 16 Апрель, 2015 18:45 ]
Заголовок сообщения:  Re: Книга Потопахина

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

mas:ARRAY 100 OF INTEGER; Определяем длину массива в 100 целых чисел
k, N, max:INTEGER; Задаем переменные
BEGIN
In.Open; Открываем входящий поток
N:=-1; Дальше вычитал, что N в этой задаче является верхней границей индекса элементов массива, зачем то задаем ей значение -1 ??
WHILE in.Done DO Если данные из входного потока получены, делаем
N:=N+1; Теперь задаем ей значение 0 ???
In.Int(mas[N]); Берем из входящего потока значение N от массива ??
END;
N:=N-1; Тут же снова отнимаем единицу ??
k:=k+1; Тут появляется k, которое на каждом шаге цикла будет присваивать +1
max:=mas[0]; Задаем max значение элемента с индексом 0
WHILE k<=N DO Но ведь N уже меньше k, потому что к этому моменту имеет значение "-1" ???
IF mas[k]>max THEN
max:=mas[k];
END;
END;
k:=k+1;
END;
StdLog.Int(max);


Я совсем уже запутался :(

Автор:  Александр Ильин [ Четверг, 16 Апрель, 2015 19:31 ]
Заголовок сообщения:  Re: Книга Потопахина

Строку "In.Int(mas[N]);" следует понимать так: "Прочитать очередное целое число и сохранить его в массив mas под номером N". Однако, операция In.Int может завершиться ошибкой, о чём мы узнаем позже, вызвав In.Done.

На момент завершения первого цикла WHILE переменная N содержит индекс последнего сохранённого в массив элемента. Если в массив помещено 5 элементов, то N = 4. Но так как последний элемент был помещён с ошибкой (In.Done = FALSE), про него надо "забыть", уменьшив N на один. Об этом написано в процитированном вами примечании.

В вашем коде строка "k:=k+1;" повторяется дважды. Это ошибка. В первом вхождении должно быть "k:=1;".

Примечание от меня: можно удалить "N:=N-1;", а во втором цикле WHILE условие "<=" заменить на "<".

Автор:  Виктор О [ Понедельник, 20 Апрель, 2015 18:02 ]
Заголовок сообщения:  Re: Книга Потопахина

snuk писал(а):
Построчно я понял это так:

mas:ARRAY 100 OF INTEGER; Определяем длину массива в 100 целых чисел
------------ причем первый из них mas[0], а последний mas[99]
k, N, max:INTEGER; Задаем переменные
BEGIN
In.Open; Открываем входящий поток
N:=-1; Дальше вычитал, что N в этой задаче является верхней границей индекса элементов массива, зачем то задаем ей значение -1 ??
----------- далее в цикле обратите внимание - мы сначала добавляем 1, а потом начинаем читать в массив. Нам надо прочитать mas[0]. Значит до добавления 1 значение N должно быть -1. Вы скажете, а зачем сначала добавлять 1, а потом читать mas? И будете правы. Если в цикле сначала читать mas[N], а потом добавлять 1, то до цикла N должно будет иметь значение 0. Кстати, N - это не верхняя граница, а номер в массиве куда читаем.
WHILE in.Done DO Если данные из входного потока получены, делаем
N:=N+1; Теперь задаем ей значение 0 ???
In.Int(mas[N]); Берем из входящего потока значение N от массива ??
END;
N:=N-1; Тут же снова отнимаем единицу ??
------- это после цикла. Так часто бывает. В данном случае ошибка.
k:=k+1; Тут появляется k, которое на каждом шаге цикла будет присваивать +1
------- Ошибка. Надо k:=1
max:=mas[0]; Задаем max значение элемента с индексом 0
------- Это опять же определяется последующим циклом. Мы думаем :) что у нас не менее одного элемента в массиве. Тогда закладываем пробный шар - делаем вид, что это и есть максимум.
WHILE k<=N DO Но ведь N уже меньше k, потому что к этому моменту имеет значение "-1" ???
-------- Вовремя остановиться в переборе и не сделать перебора :) Здесь N - последний номер, который надо проверить. Номер 0 проверять не надо - мы предварительно уравняли максимум с нулевым номером. Поэтому проверять надо, начиная с номера 1. Если в массиве у нас только один элемент (с номером 0), то и цикла не будет. А если вообще нет ни одного? Ой-ей-ей!
IF mas[k]>max THEN
max:=mas[k];
END;
END;
k:=k+1;
--------- Ошибка. Это должно быть в цикле, а тут это вывалилось из цикла.
END;
StdLog.Int(max);


Я совсем уже запутался :(
---------- Двигайтесь дальше. Дальше будет легче.

Автор:  Александр Ильин [ Понедельник, 20 Апрель, 2015 19:30 ]
Заголовок сообщения:  Re: Книга Потопахина

Виктор О писал(а):
N:=N-1; Тут же снова отнимаем единицу ??
------- это после цикла. Так часто бывает. В данном случае ошибка.
Так бывает довольно редко. В данном случае это не ошибка.

Автор:  snuk [ Вторник, 21 Апрель, 2015 10:11 ]
Заголовок сообщения:  Re: Книга Потопахина

Друзья, спасибо за комментарии, стало намного понятнее теперь :D

Автор:  snuk [ Вторник, 21 Апрель, 2015 10:15 ]
Заголовок сообщения:  Re: Книга Потопахина

Кстати, это задача, перепечатанная мною из учебника, я лишь в одном месте синтаксическую ошибку допустил, а так целиком оттуда.

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/