Компонентный Паскаль/Транспонирование одномерных матриц: различия между версиями

Содержимое удалено Содержимое добавлено
Новая страница: «__TOC__ ==Понятие о транспонировании== Слово w:Транспонированная матрица|"транспонирование…»
 
м <source> -> <syntaxhighlight> (phab:T237267)
 
Строка 11:
=== Создание пользовательского типа ===
Для решения поставленной задачи, например, возьмём отрывок из "Трёх законов робототехники" Айзека Азимова. Как вводить, данные в программу, уже было разобрано. Как создать массив, тоже понятно, с той поправкой, что желательно, чтобы он был больше, чем выбираемый отрывок, и обеспечить правильную ''охрану цикла'' для ввода и транспонирования. Если считать, что размер отрывка составит десятки мегабайтов, рекурсия тут точно не поможет -- никакого стека не хватит. Остаётся только ''перестановка на месте''. Для решения это задачи зададимся несколькими вспомогательными структурами. Одной из них, пусть будет безопасный тип строки:
<sourcesyntaxhighlight lang="oberon2">
TYPE
TString = POINTER TO RECORD
Строка 18:
txt: ARRAY 2049 OF CHAR; (* сам текст *)
END;
</syntaxhighlight>
</source>
C помощью записи создаётся новый пользовательский тип TString. Он содержит в себе отдельным полем свою длину, и сам массив текста определён на 1 символ больше, чем степень числа "2" (2049 вместо 2048). Это сделано специально, чтобы можно было индексировать начиная с "1". Кроме того есть поле, означающее максимальную длину массива. Также стоит обратить внимание на то, как изменилась форма определения записи -- использована новая привязка POINTER TO ("указатель на"). Указатель, как следует из названия "указывает на что-либо". В данном случае -- на запись. И такой подход несколько меняет работу с переменными такого типа (POINTER TO).
 
Строка 24:
Поскольку теперь у нас не просто массив литер в кодировке Unicode, а целая запись с полями -- прежде чем использовать такую структуру её нужно привести в порядок. Из примеров, которые встречались ранее известно, что переменные без начального присвоения содержат мусор.
Ниже приводится текст процедуры, которая как раз подготавливает к использования пользовательский тип TString:
<sourcesyntaxhighlight lang="oberon2">
PROCEDURE (s: TString) Init, NEW;
VAR
Строка 37:
END;
END Init;
</syntaxhighlight>
</source>
В этой процедуре сразу заметно отличие объявления процедуры от того, что объявлено ранее.
Перед именем процедуры в скобках приведён параметр тип "TString". Таким образом происходит привязка этой процедуры к записи. После такого определения можно обратиться к этой процедуре следующим образом:
<sourcesyntaxhighlight lang="oberon2">
a.Init; (* a -- экземпляр записи типа PONTER TO TString *)
</syntaxhighlight>
</source>
Запись компактна, и не возникает вопросов по поводу принадлежности процедуры "Init". Процедур "Init" даже в одном модуле может быть определено несколько, если они обладают различной принадлежностью и параметрами. При программировании на типизированных языках процедуры с одинаковым именем, но разными параметрами обладают разными ''сигнатурами''("подписями"), именно по ним компилятор и различает эти процедуры. Определение процедур с одинаковыми сигнатурами недопустимо.
 
Строка 56:
=== Ввод данных ===
Ввод данных уже разбирался, применим его снова в виде метода объекта:
<sourcesyntaxhighlight lang="oberon2">
PROCEDURE (s: TString) ReadText, NEW;
BEGIN
Строка 67:
Log.String('Длина введённого текста: '); Log.Int(s.len_txt); Log.Ln
END ReadText;
</syntaxhighlight>
</source>
В этом методе опять можно наблюдать привязку к записи типа "TString", не используются никакие сторонние переменные. Заполнение массива будет производиться до тех пор, пока либо не закончится текст, либо не будет исчерпана длина массива. После каждого успешного ввода длина текста наращивается на единицу. Обратите внимание, что индексация позиции вставки текстового массива осуществляется через свойство самого объекта "len_txt".
 
Строка 73:
=== Вывод текста ===
Вывод текста не является обязательной задачей, но всё-таки сделаем это, чтобы убедиться, что текст действительно будет "развёрнут на месте". Этот же метод будет использован для вывода перевёрнутого текста. Текст метода:
<sourcesyntaxhighlight lang="oberon2">
PROCEDURE (s: TString) LogText, NEW;
VAR
Строка 86:
Log.Ln
END LogText;
</syntaxhighlight>
</source>
В связи с тем, что литерный массив выводится не полностью, а только та часть, что получила заполнение, пришлось ввести локальную переменную "i". Он позволит выводить массив до тех пор, пока он не станет равным заполнению на вводе.
 
=== Разворот текста на месте ===
Разворот массива на месте выполним с помощью дополнительной переменной литерного типа, в качестве промежуточного хранилища элемента литерного массива. Середина введённого текста может быть найдена через целочисленное деление длины ведённого текста пополам. Для этого используется ключевое слово DIV (сокращение от DIVISION, "деление"). В остальном, метод похож на предыдущие.
<sourcesyntaxhighlight lang="oberon2">
PROCEDURE (s: TString) RotateText, NEW;
VAR
Строка 105:
END;
END RotateText;
</syntaxhighlight>
</source>
Точно также в начале метода используется диагностический вывод.
 
=== Главная процедура модуля ===
По аналогии с предыдущими программами, эта процедура будет называться "Start". Общий вид процедуры:
<sourcesyntaxhighlight lang="oberon2">
PROCEDURE Start*;
BEGIN
Строка 123:
Log.String('=[ Конец ]='); Log.Ln
END Start;
</syntaxhighlight>
</source>
Часть кода занято диагностическим выводом, другая ''вызовом методов'' переменной, имеющей тип "TString", и здесь тоже всё достаточно прозрачно. Единственная инструкция, требующая пояснения: NEW(txt). "txt" -- это переменная, имеющая тип "POINTER TO RECORD" (тип "УКАЗАТЕЛЬ НА ЗАПИСЬ"). Ключевое слово NEW указывает на то, что эта переменная создаётся динамически. Динамическое создание переменных используется очень часто, и использование NEW широко распространено. Если определить переменную "txt" не как динамическую, а как статическую, то размер программы сразу вырастит до примерно 4600 байт -- за счёт массива CHAR на 2049 элементов (4098 байт). Без статического определения массива программа занимает порядка 640 байт.
 
Строка 130:
 
Hello12.odc
<sourcesyntaxhighlight lang="oberon2">
MODULE TestHello12;
(* Этот пример показывает как развернуть
Строка 219:
BEGIN
END TestHello12.
</syntaxhighlight>
</source>
 
=== Ввод и вывод данных ===
Для ввода данных использовать этот текст:
<sourcesyntaxhighlight lang="dos">
В 2005 году она окончила Колумбийский университет в поступила в
аспирантуру по кибернетике.
Строка 240:
За пятьдесят лет на глазах Сьюзен Кэлвин прогресс человечества изменил
свое русло и рванулся вперед.
</syntaxhighlight>
</source>
 
Вывод программы, если всё сделано училось правильно:
<sourcesyntaxhighlight lang="dos">
 
компилируется "TestHello12" 636 8
Строка 277:
.екитенребик оп урутнарипса 0DX в алипутсоп в тетисревину йиксйибмулоК аличноко ано удог 5002
=[ Конец ]=
</syntaxhighlight>
</source>
Как видно, вместо переводов строк появился символ "0DX". Это символ перевода строки. Результат не совсем такой, как ожидалось. Как работать со строками будет рассмотрено отдельно.