OberonCore https://forum.oberoncore.ru/ |
|
Динамический массив. Алгоритм ввода числ.последовательности https://forum.oberoncore.ru/viewtopic.php?f=35&t=513 |
Страница 1 из 3 |
Автор: | Никита [ Вторник, 12 Июнь, 2007 13:15 ] |
Заголовок сообщения: | Динамический массив. Алгоритм ввода числ.последовательности |
Добрый день... У меня возникла проблема с массивом, нужна программа на BB, которая создаёт динамический массив, даёт возможность пользователю заполнить значения (буквы, цифры - что угодно), а после подсчитывает колличество одинаковых элементов в массиве и выводит пользователю. Если вас не затруднит помогите кто чем сможет. Заранее спасибо! |
Автор: | Илья Ермаков [ Вторник, 12 Июнь, 2007 13:54 ] |
Заголовок сообщения: | |
1) Динамический массив. Объявляется так: VAR a: POINTER TO ARRAY OF INTEGER; Создается на заданное количество элементов так: NEW(a, 150). LEN(a) возвращает длину массива, а LEN(a)-1 соответственно номер его последнего элемента. Циклы надо писать с использованием "до LEN-1", это грамотно. Удалять массив не надо, в ББ сборщик мусора, который сам его уничтожит потом. 2) Ввод данных. А как Вы хотите получать данные от пользователя? Для учебных и "числомолотильных" задачек обычно используется модуль In (посмотрите его документацию). Он считывает данные из выделенного в момент запуска вашей программы куска текста. Пример ввода: Код: VAR a: POINTER TO ARRAY OF INTEGER;
i, n: INTEGER; BEGIN n := 0; In.Open; (* Считаем количество элементов в выделенном фрагменте *) In.Int(i); WHILE In.Done DO (* Пока считывается успешно *) INC(n); In.Int(x) END; (* создаем массив на посчитанное количество элементов *) NEW(a, n); (* Повторно считываем фрагмент - теперь уже запоминая в массиве *) In.Open; FOR i := 0 TO LEN(a)-1 DO In.Int(a[i]) END |
Автор: | Pavel [ Среда, 13 Июнь, 2007 08:15 ] |
Заголовок сообщения: | |
Возможно, допущена опечатка: In.Int(x); Необходимо In.Int(i); |
Автор: | Илья Ермаков [ Среда, 13 Июнь, 2007 09:34 ] |
Заголовок сообщения: | |
Да, конечно же. |
Автор: | Никита [ Среда, 13 Июнь, 2007 09:44 ] |
Заголовок сообщения: | |
Данные от пользователя я хочу просто ввести в текстовом окне... по типу 2 ok.. 56 ok.. 34 ok и т.д. |
Автор: | Никита [ Среда, 13 Июнь, 2007 09:47 ] |
Заголовок сообщения: | |
Огромное Вам спасибо, вы мне очень сильно помогли. |
Автор: | Илья Ермаков [ Среда, 13 Июнь, 2007 10:19 ] |
Заголовок сообщения: | |
Никита писал(а): Данные от пользователя я хочу просто ввести в текстовом окне... по типу 2 ok.. 56 ok.. 34 ok и т.д.
Тогда читайте хелп ББ (надеюсь, Вы русскую версию скачали?) - учебник "Компоненты ББ шаг за шагом" (средняя часть в окне хелпа), главу 4 "Формы". |
Автор: | Евгений Темиргалеев [ Среда, 13 Июнь, 2007 18:25 ] |
Заголовок сообщения: | |
Желательно добавить проверку на то, что поток открылся. Для большей ясности. Код: ...
BEGIN n := 0; In.Open; IF In.Done THEN (* Считаем количество элементов в выделенном фрагменте *) ... END |
Автор: | Илья Ермаков [ Среда, 13 Июнь, 2007 22:59 ] |
Заголовок сообщения: | |
Поток может и открыться, но в нем не быть чисел... Лучше уж после Код: In.Int(i);
WHILE In.Done DO (* Пока считывается успешно *) INC(n); In.Int(x) END; добавить: ASSERT(n > 0, 20) - предусловие на то, что вводится хотя бы одно число. |
Автор: | Pavel [ Четверг, 14 Июнь, 2007 08:27 ] |
Заголовок сообщения: | |
А вот так: Код: In.Open;
(* Считаем количество элементов в выделенном фрагменте *) n := -1; REPEAT In.Int(i); INC(n); UNTIL ~In.Done ; (* создаем массив на посчитанное количество элементов *) IF n>0 THEN NEW(a, n); (* Повторно считываем фрагмент - теперь уже запоминая в массиве *) In.Open; FOR i := 0 TO LEN(a)-1 DO In.Int(a[i]); END; ELSE StdLog.String("Данные где?") END; |
Автор: | Илья Ермаков [ Четверг, 14 Июнь, 2007 10:27 ] |
Заголовок сообщения: | |
Pavel писал(а): А вот так: Код: REPEAT In.Int(i); INC(n); UNTIL ~In.Done ; Цикл построен неверно. n будет на единицу больше, чем чисел. Между выполнением In.Int(i) и INC(n) должна быть проверка условия In.Done, что и обеспечивал WHILE с вынесенным действием. Схема чтения из потока: Код: Берем_след_элемент; WHILE Взят_успешно() DO Используем элемент - например, считаем Берем_след_элемент END; Это цикл с вынесенным действием, т.к. чтений выполняется на одно больше, чем выполнений тела цикла с полезным действием - чтобы понять, что поток закончился, нужно попробовать прочитать. WHILE с вынесенным действием можно реализовать и через UNTIL, но не так, как Вы написали, а вот так: Код: REPEAT
Берем_след_элемент; IF Взят_успешно() THEN Используем_элемент END UNTIL ~ Взят_успешно(); Здесь тело цикла выполняется на один раз больше, чем у предыдущего WHILE. Но чтобы полезное действие не выполнялось лишний раз на последнем "холостом" витке, нужно поставить IF. В данном случае WHILE короче и удобнее. Однако бывают ситуации, код код взятия следующего элемента весьма громоздок, и удобнее поставить лишний IF, чем дублировать код перед циклом. |
Автор: | Илья Ермаков [ Четверг, 14 Июнь, 2007 10:30 ] |
Заголовок сообщения: | |
А, пардон, Вы перед циклом сделали n := -1. Можно, но не красиво - шаманство. n - количество элементов, и инвариант на него - n >= 0 по определению. К тому же, если бы мы выполняли не подсчет, а какое-то другое более сложное действие с данными из потока, то такой номер бы не прошел. |
Автор: | PGR [ Четверг, 14 Июнь, 2007 11:11 ] |
Заголовок сообщения: | |
Без повторения кода и без лишних вызовов функции. Да и понять проще... Код: LOOP
Берем_след_элемент; IF ~Взят_успешно() THEN EXIT END; Используем элемент; END; |
Автор: | Илья Ермаков [ Четверг, 14 Июнь, 2007 11:18 ] |
Заголовок сообщения: | |
Ни в коем случае! Вот, елки-палки, даже в КП люди GOTO себе найдут... Без лишних вызовов функций и легко понимабельный - первый вариант с WHILE. Это типовая схема, которая используется всегда. Практически. Иногда - альтернативный вариант REPEAT. LOOP-END - это не цикл для повседневного использования. Его ввели в КП как в промышленном языке для некоторых навороченных кусков вроде циклов обработки сообщений и т.п. Не более. Почему "нельзя"? Потому что вариант с WHILE - это частный случай универсальной базовой схемы "полный проход по последовательности" которая просто формально приспосабливается к текущей ситуации Ее надо знать - и наоборот, уметь узнавать в чужом коде как единое целое. Тогда не будет казаться, что "склепанное на коленках" частное решение с GOTO "понять проще". |
Автор: | PGR [ Четверг, 14 Июнь, 2007 11:43 ] |
Заголовок сообщения: | |
Почему GOTO? У этого цикла LOOP одна точка входа и одна точка выхода. |
Автор: | Pavel [ Четверг, 14 Июнь, 2007 11:47 ] |
Заголовок сообщения: | |
Илья Ермаков писал(а): Вы перед циклом сделали n := -1. Можно, но не красиво - шаманство.
Все программирование ШАМАНСТВО. n- в данном варианте это количество элементов, если оно получилось равно нулю, то элементов нет. |
Автор: | Илья Ермаков [ Четверг, 14 Июнь, 2007 11:52 ] |
Заголовок сообщения: | |
PGR писал(а): Почему GOTO? У цикла LOOP одна точка входа и одна точка выхода.
Ну, в данном случае да. Но вообще цикл LOOP позволяет делать сколько угодно точек выхода. Не стоит его использовать. Если конструкция позволяет делать много выходов, то тут же начнут делать - просто в силу правила "насыщения степеней свободы инструмента". |
Автор: | Илья Ермаков [ Четверг, 14 Июнь, 2007 11:56 ] |
Заголовок сообщения: | |
Цитата: Все программирование ШАМАНСТВО.
n- в данном варианте это количество элементов, если оно получилось равно нулю, то элементов нет. См. выше - ну зачем строить неверные циклы, затем изобретать велосипеды для их объезда, а потом еще искать теоретическое обоснование? Есть понятие инварианта - условия, которое должно соблюдаться на протяжении выполнения некоторого блока - в его начале, в середине и в конце. Если n - число элементов, то при грамотном построении алгоритма на всем его протяжении должен выполняться инвариант n >= 0. Если же инвариант приходится нарушать (n := -1), то это признак неграмотно построенного алгоритма... |
Автор: | Vlad [ Четверг, 14 Июнь, 2007 12:00 ] |
Заголовок сообщения: | |
PGR писал(а): Почему GOTO? У этого цикла LOOP одна точка входа и одна точка выхода.
Сейчас тебя пошлют читать Дейкстру Забей. Типичный случай, когда break (в твоем случае EXIT) удобнее/нагляденее/эффективнее. |
Автор: | Илья Ермаков [ Четверг, 14 Июнь, 2007 12:01 ] |
Заголовок сообщения: | |
Вообще, полезно почитать книжку Бейбера "Программное обеспечение без ошибок". viewtopic.php?t=411 |
Страница 1 из 3 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |