Программирование на языке Object Pascal в среде Delphi (лабораторные работы)

Территория рекламы

ПРОГРАММИРОВАНИЕ НА ЯЗЫКЕ

OBJECT PASCAL В СРЕДЕ DELPHI

(лабораторные работы)

СОДЕРЖАНИЕ

ЛАБОРАТОРНАЯ РАБОТА 1. 

ПРОГРАММИРОВАНИЕ ЛИНЕЙНЫХ АЛГОРИТМОВ…………....………...... 2

1.5. Индивидуальные задания.....................................................................................17

ЛАБОРАТОРНАЯ РАБОТА 2. 

ПРОГРАММИРОВАНИЕ РАЗВЕТВЛЯЮЩИХСЯ АЛГОРИТМОВ…….……...19

2.7. Индивидуальные задания.....................................................................................23

ЛАБОРАТОРНАЯ РАБОТА 3. 

ПРОГРАММИРОВАНИЕ ЦИКЛИЧЕСКИХ АЛГОРИТМОВ…………………....24

3.6. Индивидуальные задания.....................................................................................31

ЛАБОРАТОРНАЯ РАБОТА 4. 

ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ МАССИВОВ…………….....35

4.9. Индивидуальные задания......................................................................................47

ЛАБОРАТОРНАЯ РАБОТА 5. 

ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

СТРОКОВЫХ ДАННЫХ.............................................................................................51

5.3. Индивидуальные задания......................................................................................55  

ЛАБОРАТОРНАЯ РАБОТА 6. 

ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

ПОДПРОГРАММ И МОДУЛЕЙ……………………………………..…………......57

6.8. Индивидуальные задания.....................................................................................69  

ЛАБОРАТОРНАЯ РАБОТА 7. 

ПОСТРОЕНИЕ ГРАФИКОВ.......................................................................................70

7.4. Индивидуальные задания......................................................................................79

ЛАБОРАТОРНАЯ РАБОТА 8. 

РАБОТА С ФАЙЛАМИ................................................................................................79

8.5. Индивидуальные задания......................................................................................89  

ПРИЛОЖЕНИЕ. 

СРЕДСТВА ОТЛАДКИ ПРОГРАММ В DELPHI…………………………….….....90

ЛИТЕРАТУРА……………………………………………………………………......81

ЛАБОРАТОРНАЯ РАБОТА 1.

ПРОГРАММИРОВАНИЕ ЛИНЕЙНЫХ АЛГОРИТМОВ

Цель работы: Изучить основы языка Object Pascal. Научиться составлять простейшие программы в среде DELPHI.

1.1. Базовые элементы языка Object Pascal

1.1.1. Алфавит языка

Язык Object Pascal оперирует следующим набором символов:

1. Прописные и строчные буквы латинского алфавита (A, B, C, ... , X, Y, Z, a, b, c, ..., x, y, z).

2. Десятичные цифры ( 0 … 9).

3. Символ «подчеркивание»( «_» ).

4. Специальные символы ( «+», «-», «/», «*», «{», «}», «:», «[», «]», «;», «(», «)», «'», «#», «@», «=», « », «$», «>», «.», «^», «<», «,», а также их комби-нации).

5. Ключевые слова (например: «Begin», «End»);

6. Стандартные идентификаторы (Например: «Sin», «Cos»).

7. Идентификаторы пользователя.

1.1.2. Синтаксис языка

Основные правила написания программ:

1. Прописные и строчные буквы компилятором не различаются (описание «mas» идентично написанию «MAS»).

2. Идентификаторы (имена) могут начинаться только с буквы и символа подчеркивания, и должны содержать буквы, цифры и символ подчеркивания. Компилятор воспринимает идентификаторы длиной не более 255 символов.

3. Каждое предложение заканчивается точкой с запятой («;»). В одной строке могут находиться несколько предложений, и наоборот, одно большое предложение может быть разбито на несколько строк.

4. Все данные, процедуры и функции должны быть объявлены в разделе объявлений до первого их использования.

5. Для повышения читабельности текста можно использовать комментарии (допускается использования русского языка). Комментарием является текст, заключенный в фигурные скобки ( { комментарий }, круглые с символом звездочка ( (* комментарий *)  ) либо размещенные после двух cимволов «правый слэш» ( // комментарий ).

1.1.3. Основные типы данных

Тип данных определяет количество выделяемых ячеек памяти и перечень допустимых операций. Существует две основные группы типов данных: скалярные (простые) и структурированные (составные). Данные скалярного типа представляют собой одно значение, размещенное в одной или нескольких ячейках памяти. Структурированные данные (объявляются после ключевого слова type) представляют собой объединение нескольких однотипных или неоднотипных данных скалярного типа.

Все данные могут быть либо константами (объявляются после ключевого слова const), либо переменными (объявляются после ключевого слова var). Значение переменных может быть изменено в процессе выполнения программы, а значение констант – не может. Типы данных приведены на рис. 1.1.

  Рис. 1.1. Типы данных Object Pascal

1.1.4. Оператор присваивания

Оператор присваивания записывается в виде:

<имя переменной>:=< выражение соответствующего типа>;

Переменная может быть любого типа, а выражение должно иметь тип, соответствующий типу переменной (разрешается присваивать действительной переменной значение, имеющее целый тип).

1.1.5. Целые типы данных

Используются для представления целых чисел. Характеристики основных целых типов данных приведены в табл. 1.1.     

           Таблица 1.1

ТипДиапазон возможных значенийРазмер памяти для хранения данныхInteger-2147483648 .. 21474836474 байта (32 бита)Cardinal0 .. 42949672954 байта (32 бита)ShortInt-128 .. 1271 байт (8 бит)SmallInt-32768 .. 327672 байта (16 бит)LongInt-2147483648 .. 21474836474 байта (32 бита)Int64-263 ..  263-18 байт (64 бита)Byte0 .. 2551 байт (8 бит)Wodd0 .. 655352 байта (16 бит)LongWord0 .. 42949672954 байта (32 бита)

Object Pascal поддерживает и наиболее универсальный целый тип - Integer, который эквивалентен LongInt.

     Операции над целыми числами:

Наименование операцииОбозначениеПримерСложение+5 + 2 = 7Вычитание-5 - 2 = 3Умножение*5 * 2 = 10Целочисленное делениеdiv5 div 2 = 2Остаток от целочисленного деленияmod5 mod 2 = 1Логическое равно=5 = 5 , результат: истинаЛогическое не равно<>5 <> 5 , результат: ложьСравнение>,  >=,  <,  <=

 

1.1.6. Вещественные (действительные) типы данных

Используются для представления чисел, имеющих дробную часть. Характеристики основных вещественных типов данных приведены в табл. 1.2.

           Таблица 1.2

ТипДиапазонвозможных значенийМаксимальное количество цифр в числеРазмерв байтахReal482,9 x 10-39 .. 1,7 x 103811 - 126Real5,0 x 10-324 .. 1,7 x 1030815 - 168Single1,5 x 10-45 .. 1,7 x 10387 - 84Double5,0 x 10-324 .. 1,7 x 1030815 -168Extended3,6 x 10-4951 .. 1,1 x 10493219 - 2010Comp-263+1 .. 26319 - 208Cyrrency-922337203685477,5808 .. 922337203685477,580819 - 208

           

Язык Delphi поддерживает и наиболее универсальный вещественный тип - Real, который эквивалентен Double.

     Операции над вещественными (действительными) числами:

Наименование операцииОбозначениеПримерСложение+5 + 1,5 = 6,5Вычитание-8 - 4,2 = 3,8Умножение*2 * 2,6 = 5,2Деление/5 / 2 = 2,5Логическое равно=5 = 5 , результат: истинаЛогическое не равно<>5 <> 5 , результат: ложьСравнение>,  >=,  <,  <=

         1.1.7. Булевы типы данных

Используются для представления логических значений. Наиболее часто используется тип Boolean, который занимает 1 байт памяти и может принимать два значения: true (истина) или false (ложь). Для булевых типов данных определены логические операции and, or, not, xor. Например, если переменные b1 и b2 имеют тип Boolean, то

 b1 := 5 > 3; // результат: b1=true

 b2 := 5 = 3; // результат: b2=false

 b1 := not b2; // результат: b1=true 

b2 := b1 and b2; // результат: b2=true 

1.1.8. Cимвольные типы данных

Используются для хранения одного символа.

Язык Delphi поддерживает два символьных типа: AnsiChar и WideChar:

  •  тип AnsiChar — это символы в кодировке ANSI, которым соответствуют числа в диапазоне от 0 до 255. Каждый симол занимает 1 байт памяти.
  •  тип WideChar — это символы в кодировке Unicode, им соответствуют числа от 0 до  65 535. Каждый симол занимает 2 байта памяти.

Object Pascal поддерживает и наиболее универсальный символьный тип Сhar, который эквивалентен AnsiChar , кажый символ которого занимает 1 байт памяти.

1.1.9. Строкоые типы данных

Язык Delphi поддерживает три строковых типа:

 ShortString, LongString, WideString: 

  •  тип ShortString представляет собой статически размещаемые в памяти компьютера строки длиной от 0 до 255 символов;

  •  тип AnsiString представляет собой динамически размещаемые в памяти строки, длина которых ограничена только объемом свободной памяти;

  •  тип WideString представляет собой динамически размещаемые в памяти строки, длина которых ограничена только объемом свободной памяти. Каждый символ строки типа WideString является Unicode-символом.

В языке Delphi для обозначения строкового типа допускается использование универсального типа String. Объявлять строку этип типом можно как с указанием ее длины, например, var S:string[12]  (в квадратных скобках -длина строки) или и без указания ее длины, например, var S:string. Тогда в первом случае такое объяление равносильно ShortString, а во втором случае - равносильно  AnsiString.

1.1.10. Арифметические вычисления

Арифметические выражения строятся из числовых констант, переменных, стандартных функций и операций над ними. В арифметическом выражении принят следующий приоритет операций:

1) вычисление значений стандартных функций;

2) умножение и деление;

3) сложение и вычитание.

Порядок выполнения операций изменяется с помощью скобок.

Для проведения арифметических вычислений используются следующие процедуры и функции (табл. 1.3).

           Таблица 1.3

ОписаниеОбозначениеТип аргументаТип значенияМодуль12345Модуль (абсолютное значение)Abs(x)Целый или вещественныйСоответствует типу аргументаSystemЭкпонентаExp(x)ВещественныйВещественныйSystemДробная частьFrac(x)ВещественныйВещественныйSystemЦелая частьInt(x)ВещественныйВещественныйSystemНатуральный логарифмLn(x)ВещественныйВещественныйSystemДесятичный логарифмLog10(x)ВещественныйВещественныйMathЛогарифм по основанию 2Log2(x)ВещественныйВещественныйMathЛогарифм по основанию NLogN(N, x)ВещественныйВещественныйMathМаксимум двух чиселMax(A, B)ВещественныйВещественныйMathМинимум двух чиселMin(A, B)ВещественныйВещественныйMathЧисло πPISystemВозведение числа А в степень ЕPower(A, E)ВещественныйВещественныйMathОкругление до ближайшего целогоRound(x)ВещественныйЦелыйSystemКвадратSqr(x)ВещественныйВещественныйSystemКорень квадратныйSqrt(x)ВещественныйВещественныйSystemВозврат целой частиTrunc(x)ВещественныйЦелыйSystemАрккосинусArcCos(x)ВещественныйВещественныйMathАрксинусArcSin(x)ВещественныйВещественныйMathАрктангенсArcTan(x)ВещественныйВещественныйSystemКосинусCos(x)ВещественныйВещественныйSystemСинусSin(x)ВещественныйВещественныйSystemТангенсTan(x)ВещественныйВещественныйMathКосинус гиперболическийCosH(x)ВещественныйВещественныйMathСинус гиперболическийSinH(x)ВещественныйВещественныйMathТангенс гиперболическийTanH(x)ВещественныйВещественныйMathГенерация псевдослучайного числа из диапазона 0 .. 1RandomВещественныйВещественныйSystemГенерация псевдослучайного числа из диапазона 0 .. RRandom(R)ЦелыйЦелыйSystemДелает случайной генерацию псевдослучайного числаRandomizeSystemВозвращает True (истина), если х - нечетное и False (ложь), если х - четноеOdd(x)ЦелыйЛогическийSystemВозвращает следующее за х значениеSucc(x)Целый, символьный, перечисляемыйСоответствует типу аргументвSystemВозвращает предыдующее перед х значениеPred(x)Целый, символьный, перечисляемыйСоответствует типу аргументовSystemВозвращает  символ ASCII кода хChr(x)ЦелыйСимвольныйSystemВозвращает ASCII код символа хOrd(x)СимвольныйЦелыйSystemУвеличивает значение х на 1Inc(x)ЦелыйЦелыйSystemУвеличивает значение х на nInc(x, n)ЦелыйЦелыйSystemУменьшает значение х на 1Dec(x)ЦелыйЦелыйSystemУменьшает значение х на nDec(x, n)ЦелыйЦелыйSystem

Примечание: В тригонометрических функциях аргумент задается только в радианах. Математические функции, находящиеся в модуле Math, могут быть использованы только после добавления его имени в раздел подключаемых модулей (uses).

1.2. Интегрированная среда разработчика DELPHI

Интегрированная среда разработчика представляет собой набор окон, содержащих все необходимые инструменты для проектирования, тестирования и запуска приложения. Количество, расположение, размер и вид окон может меняться программистом в зависимости от его текущих нужд. Кроме того, имеется возможность расширять среду, включая инструменты, поставляемые сторонними разработчиками, что значительно повышает производительность работы. Основное окно среды Delphi имеет вид как на рис. 1.2.

  Рис. 1.2. Основное окно среды Delphi.

Главное окно предназначено для управления процессом создания программы. Основное меню содержит все необходимые средства для управления проектом. Левая панель содержит набор кнопок быстрого доступа, дублирующих наиболее часто используемые команды меню. Правая панель представляет собой меню библиотеки визуальных компонентов (VCL), которые представляют собой стандартные сервисные программы, помещаемые программистом на окно формы. Каждый компонент имеет определенный набор свойств (параметров), которые можно изменять как на этапе проектирования, так и во время выполнения программы.

Окно инспектора объектов (вызывается c помощью клавиши F11) предназначено для изменения свойств выбранных компонентов и состоит из двух страниц. Страница Properties (Свойства) предназначена для изменения необходимых свойств компонента и делится на две части. Слева находится имя свойства, а справа – текущее значение свойства, которое может быть изменено. Если при щелчке на свойстве появится окно выпадающего списка, то нажав на кнопку со стрелкой, направленной вниз, можно увидеть список возможных значений свойства. Если слева от имени свойства находится значок плюс, то это означает, что свойство содержит некоторое количество вложенных свойств, доступ к которым осуществляется либо нажатием на знак плюс, либо двойным щелчком на свойстве. Страница Events (События) предназначена для определения реакции компонента на то или иное событие (например, нажатие определенной клавиши или щелчок «мышью» по кнопке).

Окно формы представляет собой проект Windows-окна программы. В это окно в процессе написания программы помещаются необходимые визуальные и невизуальные компоненты. При выполнении программы, помещенные визуальные компоненты будут иметь тот же вид, что и на этапе проектирования.

Окно текста программы предназначено для просмотра, написания и редактирования текста программы на языке программирования Object Pascal. При первоначальной загрузке в окне текста программы находится набор операторов обеспечивающий возможность функционирования пустой формы в качестве Windows-окна. При помещении новых компонентов на форму, текст программы автоматически дополняется описанием необходимых библиотек стандартных программ (раздел uses) и типов переменных (раздел type) (см. Листинг 1.1).

Программа в среде DELPHI составляется как описание алгоритмов, которые выполняются при возникновении того или иного события (например щелчок «мыши» на кнопке – событие OnClick, создание формы – OnCreate). Для каждого обрабатываемого события, с помощью страницы Events инспектора объектов в тексте программы организуется процедура (procedure), между ключевыми словами begin и end которой программист записывает на языке Object Pascal требуемый алгоритм.

Переключение между окном формы и окном текста программы осуществляется с помощью клавиши F12.

1.3. Структура программ DELPHI

Приложение в среде DELPHI состоит из файлов с исходным текстом (расширение pas), файлов форм (расширение dfm) и файла проекта (расширение dpr), который связывает вместе все файлы проекта. При компиляции программы DELPHI создает файл с расширением dcu, содержащий в себе результат перевода в машинные коды содержимого файлов с расширениями pas и dfm. Ком-поновщик преобразует файлы с расширением dcu в единый загружаемый файл с расширением exe. В файлах, имеющих расширения ~df, ~dp, ~pa, хранятся резервные копии файлов с образом формы, проекта и исходного текста соответственно.

В файле проекта (расширение dpr) находится информация о всех модулях, составляющих данный проект. Файл проекта автоматически создается и редактируется средой DELPHI.

Файл исходного текста (расширение pas) предназначен для размещения текста программы.

Модуль имеет следующую структуру:

 unit Unit1;

interface 

 // Раздел объявлений

 implementation

 // Раздел реализации

 begin

 // Раздел инициализации

 end.

В разделе объявлений описываются классы, типы, переменные, заголовки процедур и функций, которые могут быть использованы другими модулями. В разделе реализации располагаются тела процедур и функций, описанных в разделе объявлений, а также типы переменных, процедуры и функции, которые будут функционировать только в пределах данного модуля. Раздел инициализации используется редко и его можно пропустить.

  1.4. Пример написания программы

Задание: составить программу вычисления для заданных значений х, у арифметического выражения    .  Интерфейс программы представлен на рис.1.2.

          Рис. 1.2. Интерфейс программы

  

    1.4.1. Настройки формы

Для создания нового проекта выберите в основном меню пункт  File-New-Application. С помощью мыши, "захватывая" одну из кромок формы или выделенную строку заголовка ттрегулируйте нужные размеры формы и ее положение на экране. Здесь можно руководствоваться тем, что размер формы не должен быть большим, чтобы не загромождать экран и чтобы на самой форме не было не нужного пустого пространства.

1.4.2. Изменение заголовка формы

Новая форма имеет одинаковые имя (Name) и заголовок (Сaption) – Form1. Для изменения заголовка перейдите в окно инспектора объектов и щелкните кнопкой мыши на форме. На странице Properties инспектора объектов найдите свойство Caption и в правой ячейке наберите «Линейный алгоритм».

          1.4.3. Размещение строки ввода (TEdit)

 Для ввода данных, а также вывода информации, которая вмещается в одну строку, используется однострочное окно редактирования (компонент TEdit). Доступ к отображаемой в окне информации в виде строки из символов осуществляется с помощью свойства Text.

Выберите в меню компонентов Standart пиктограмму    и щелкните мышью в том месте формы, где вы хотите ее поставить. Поместите два новых компонента TEdit в форму, в тексте программы (см. Листинг 1.1) появятся две новые переменные  Edit1  и Edit2. Захватывая компоненты "мышью" отрегулируйте размеры окон и их положение.

   1.4.4. Размещение надписей (TLabel)

На форме (рис.1.2) имеются две пояснительные надписи. Для нанесения таких надписей на форму используется компонент TLabel.

Выберите в меню компонентов Standart пиктограмму    и щелкните мышью в нужном месте формы (появится надпись Label1). Проделайте это для двух надписей, в тексте программы автоматически появятся две новые переменные типа TLabel. Для каждой надписи, щелкнув по ней мышью, отрегулируйте размер и положение на форме. В свойство Caption введите строку, например,  "Х=".

  1.4.5. Размещение многострочного окна вывода (TMemo)

 Для вывода результатов работы программы в виде отчета, содержащего несколько строк текста, обычно используется текстовое окно (компонент TMemo). Информация, которая отображается построчно в окно типа TMemo, находится в свойстве Мемо1.Lines. Новая строка добавляется методом Memo1.Lines.Add (переменная типа String). Для очистки окна во времы выполнения программы используется метод Memo1.Clear.

 Выберите в меню компонентов Standart пиктограмму    и поместите компонент ТМемо на форму, в тексте программы появилась новая переменная - Мемо1. С помощью мыши отрегулируйте размеры и местоположение на форме. Для отображения вертикальной и горизонтальной полос прокрутки, на странице Properties инспектора объектов установите свойство ScrolBars в положение SSBoth.

1.4.6. Написание программы обработки события

создания формы (FormCreate)

После запуска программы, происходит создание спроектированной формы (событие OnCreate). Создадим подпрограмму – обработчик этого события (TForm1.FormCreate). Занесем начальные значения переменных x, y в соответствующие окна TEdit, а окно ТMemo очистим.

Для создания обработчика события FormCreate необходимо дважды щелкнуть мышью на любом свободном месте формы. На экране появится текст, в котором автоматически внесен заголовок процедуры – обработчика события создания формы: Procedure TForm1.FormCreate(Sender:TObject). Между begin … end вставим текст (см. Листинг 1.1).

1.4.7. Написание программы обработки события

нажатия кнопки (ButtonClick)

Поместите на форму кнопку (компонент ТButton), для чего необходимо выбрать в меню компонентов Standart пиктограмму  . С помощью инспектора объектов измените заголовок (Caption) – Button1 на слово «Выполнить» или другое по вашему желанию. Отрегулируйте положение и размер кнопки.

Для создания обработчика события ButtonClick необходимо дважды щелкнуть мышью на кнопке. На экране появится текст подпрограммы, с за-головком процедуры обработчика события «щелчок мышью на кнопке»: (Procedure TForm1.ButtonClick(Sender:TObject); ). Между begin … end вставим текст (см. Листинг 1.1).

 Внимание! Заголовки процедур ButtonClick и FormCreate создаются средой Delphi автоматически (если набрать их вручную – программа работать не будет). При запуске программы на выполнение все функции обработки событий, у которых между begin и еnd не было написано текста удаляются автоматически по соответствующему запросу среды Delphi. Поэтому не надо вручную удалять ошибочно созданные обработчики.

Следует обратить внимание на то, что численные значения переменных име-ют вещественный (действительный) тип, а компоненты TЕdit и TMemo работают со строковыми переменными. Для преобразования строковой записи числа, в действительное или целое его представление и наоборот используют функции (табл. 1.4):

           Таблица 1.4

StrToInt(S : string) : integer;Преобразует строку в целое числоStrToFloat(S : string) : real;Преобразует строку в вещественное числоIntToStr(V : integer) : string;Преобразует целое число в его строковое представлениеFloatToStr(V : real) : string;Преобразует вещественное число в его строковое представлениеFloatToStrF(V : real; Format,p, d : integer) : string;Преобразует вещественное число в его строковое представление с форматом

Правила использования параметров функции FloatToStrF приведены в табл. 1.5:

           Таблица 1.5

Значение FormatОписаниеffFixedФормат с фиксированным положением разделителя целой и дробной частей. Р задает общее количество десятичных цифр в представлении числа. d - количество цифр в дробной части.ffNumberОтличается от ffFixed использованием символа-разделителя тысяч при выводе больших чисел.ffCurrencyСоответствует ffNumber, но в конце строки ставится символ денежной единицы (для руссифицированной версии Windows - символы "р.").ffExponentНаучная форма представления с множителем Ехх ("умножить 10 в степени хх"). Р задает общее количество десятичных цифр мантиссы. d - количество цифр в десятичном порядке хх. Число округляется с учетом первой отбрасываемой цифры. ffGeneralУниверсальный формат. Если число цифр в целой части числа не превышает заданной точности и значение больше 1*10-5, то используется формат с фиксированной точкой, иначе - научный.

   1.4.8. Запуск и работа с программой

Запустить программу можно выбрав в главном меню пункт  Run - Run, или нажав фуккциональную клавишу F9, или щелкнув мышью по пиктограмме     .

При этом происходит трансляция и, если нет ошибок, компановка программы и создание единого выполняемого файла с расширением exe. На экране появляется активная форма (рис. 1.3).

     Рис. 1.3

Работа с программой происходит следующим образом. Нажмите (щелкните мышью) кнопку "Выполнить". В окне Мемо1 появляется результат. Измените исходные значения х, у в окнах TEdit и снова нажмите кнопку "Выполнить" - появятся новые результаты. Чтобы  завершить работу программы, нужно нажать кнопку   на форме, или перейти в окно DELPHI и выбрать в главном меню пункт Run - Program Reset. Последний способ выхода из программы обычно используют в случае ее зацикливания.

В Листинге 1.1 представлен текст программы.

          Листинг 1.1

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls, math;

type

TForm1 = class(TForm)

Edit1: TEdit;

Edit2: TEdit;

Label1: TLabel;

Label2: TLabel;

Memo1: TMemo;

Button1: TButton;

procedure FormCreate(Sender: TObject);

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

//----------------------------------------------------------------

 procedure TForm1.FormCreate(Sender: TObject);

 begin

   Edit1.Text:='3,4E-4'; // Ввод начального значения X

  Edit2.Text:='24,687'; // Ввод начального значения Y

  Memo1.Clear;            //  Очиска Мемо1

 end;

 //---------------------------------------------------------------

 procedure TForm1.Button1Click(Sender: TObject);

var

  x,y,a,b,s : real; 

 begin

   x:=StrToFloat(Edit1.Text); // Считывание значения X 

   y:=StrToFloat(Edit2.Text); // Считывание значения Y

  // Вычисление арифметического выражения

  a:=ln(y)*exp(2*x);

   b:=power(y,x)/abs(tan(y));

   s:=a*b*100;

  // Вывод результата

  Memo1.Clear; // Очистка окна вывода Memo1

  Memo1.Lines.Add('Результат s='+FloatToStrF(s,ffFixed,7,2));

 end;

//----------------------------------------------------------------

 end. 

1.5. Индивидуальные задания

По указанию преподавателя выберите индивидуальное задание. Установите необходимое количество окон TEdit и меток TLabel. Выберите необходимые типы переменных и функции их преобразования при вводе и выводе данных. Для проверки правильности написания программы введите указанные в задании значения x, y и z – результат должен быть равен s.

              

ЛАБОРАТОРНАЯ РАБОТА 2.

ПРОГРАММИРОВАНИЕ РАЗВЕТВЛЯЮЩИХСЯ

АЛГОРИТМОВ

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

2.1. Понятие разветвляющегося алгоритма

Алгоритм называется разветвляющимся, если он содержит несколько ветвей отличающихся друг от друга содержанием вычислений. Выход вычислительного процесса на ту или иную ветвь алгоритма определяется текущими данными.

Для программирования разветвлений в языке Паскаль имеется два условных оператора if и Case.

2.2. Оператор условия if

Этот оператор служит для разделения естественного порядка выполнения операторов программы на две ветви. Выбор пути зависит от результата проверки логического выражения или от значения булевой переменной. Конструкция использующая оператор if выглядит следующим образом:

if <логическое выражение> then <Оператор 1>

 else <Оператор 2>;

Если значение логического выражения равно True («истина»), то выполняется «оператор 1», а «оператор 2» не выполняется. Иначе, если значение логического выражения равно False («ложь»), то выполняется «оператор 2», а «оператор 1» не выполняется. Обратите внимание на то, что в конце оператора, стоящего перед ключевым словом else точка с запятой не ставится.

Возможен сокращенный вариант конструкции:

if < логическое выражение > then <Оператор 1>;

или

 if <логическое выражение> then

else <Оператор 2>;

Если значение логического выражения равно True («истина»), то выполняется «оператор 1» и далее выполняются операторы стоящие после окночания конструкции if. Иначе, если значение логического выражения равно False («ложь»), то «оператор 1» не выполняется, а выполняются операторы стоящие после окончании конструкции if.

В качестве «оператора 1» и «оператора 2» может быть использован другой оператор if. При вложенности операторов if каждое else соответствует тому then, которое непосредственно ему предшествует.

Если необходимо логическое выражение представляет собой объединение нескольких логических выражений, то каждое отдельное выражение должно быть помещено в круглые скобки.

Пример 2.1. Даны длины сторон треугольника – а, b, c. Определить является ли данный треугольник равнобедренным.

if (а=b) аnd (b=c) and (c=a) then Memo1.Lines.Add(‘Равнобедренный’)

else Memo1.Lines.Add(‘Неравнобедренный’);

2.3. Оператор выбора Case

Оператор case анализирует некоторую переменную или выражение (селектор) и в зависимости от их значения выполняет те или иные действия.

 case <селектор> of

 <список 1>: <Оператор 1>;

 <список 2>: <Оператор 2>;

 …

 <список n>: <Оператор n>;

 else <Оператор n>;

 end;

Сначала вычисляется значение выражения-селектора, затем выполняется тот оператор, константа выбора которого равна значению выражения-селектора. Если ни одна из констант не равна значению селектора, то выполняется оператор, следующий за else. Если else отсутствует, то выполняется оператор, следующий за end. Селектор должен относиться к порядковому типу (целый, перечисляемый, булевый и др.).

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

Пример 2.2. По номеру месяца вывести название сезона.

Case mes of

  1,2,12 : Memo1.Lines.Add('Зима');

      3..5 : Memo1.Lines.Add('Весна');

      6..8 : Memo1.Lines.Add('Лето');

    9..11 : Memo1.Lines.Add('Осень');

  else

                Memo1.Lines.Add('Месяца с таким номером нет');

end;

2.4. Составной оператор

Во многих конструкциях допускается выполнение только одного оператора. Однако часто в определенном месте программы необходимо выполнить группу операторов. В Паскале имеется возможность объединить группу операторов в один составной оператор с помощью ключевых слов begin .... end. Такой составной оператор, например, может быть размещен после then или else.

2.5. Некоторые возможности, предоставляемые Delphi

для организации разветвлений

Для организации разветвлений в Delphi обычно используются компоненты в виде кнопок – переключателей TCheckBox и TradioGroup. Состояние таких кнопок визуально отражается на форме. Кнопка типа TCheckBox, помещенная на форму, позволяет пользователю с помощью щелчка мышью на ней изменить ее состояние (включена-выключена) и соответственно изменить значение связанной с ней переменной TСheckBox.Checked булевского типа:

if CheckBox.Checked then <Оператор 1>

else <Оператор 2>;

 Группа кнопок типа TRadioGroup, помещенная на форму, позволяет пользователю организовать селектор, передающий в программу через переменную целого типа RadioGroup.ItemIndex номер включенной кнопки (0, 1, 2, …).

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,  StdCtrls, ExtCtrls, math;

type

TForm1 = class(TForm)

Memo1: TMemo;

Button1: TButton;

Label1: TLabel;

Edit1: TEdit;

Label2: TLabel;

Edit2: TEdit;

RadioGroup1: TRadioGroup;

procedure FormCreate(Sender: TObject);

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

 end;

 var

Form1: TForm1;

implementation

{$R *.dfm}

//----------------------------------------------------------

procedure TForm1.FormCreate(Sender: TObject);

begin

  Edit1.Text:='2';

  Edit2.Text:='5,9';

  Memo1.Clear;

end;

//-----------------------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);

var

  x,y,a,f,s :extended;

begin  

  x:=StrToFloat(Edit1.Text);

  y:=StrToFloat(Edit2.Text);

  case RadioGroup1.ItemIndex of

    0 : f:=cos(x);

    1 : f:=sqr(x);

    2 : f:=sin(x);

  end;

  a:=sqr(x+y);

  if f > 0.5 then s:=a-sqrt(y)

  else

     if (f > -0.5) and (f <= 0.5) then s:=a+power(x*y,3)

    else s:=a+ln(y);

  Memo1.Clear;

  Memo1.Lines.Add('Результат S='+FloatToStrF(s,ffFixed,8,3));

 end;

//-----------------------------------------------------------------

 end.

2.7. Индивидуальные задания

По указанию преподавателя выберите индивидуальное задание. В качестве f(x) использовать по выбору: Sin(x), Cos(x) или Tg(x). Отредактируйте вид формы и текст программы, в соответствии с полученным заданием.

ЛАБОРАТОРНАЯ РАБОТА 3.

ПРОГРАММИРОВАНИЕ ЦИКЛИЧЕСКИХ АЛГОРИТМОВ

Цель лабораторной работы: изучить способы организации циклических вычислительных процессов.

3.1. Операторы для организации циклов

Цикл – многократное выполнение некоторой последовательности операторов. Количество повторений определяется управляющей переменной (счетчиком), которая должна изменять свое значение внутри цикла. Совокупность операторов, находящихся внутри цикла называют телом цикла.

3.1.1. Организация цикла с помощью оператора for

Оператор

 for <счетчик>:=<начальное значение> to <конечное значение> do

 begin

   <операторы>

 end;

организует повторение последовательности операторов при изменении значения счетчика от начального до конечного, с шагом «единица». Вначале счетчику присваивается начальное значение. После каждого выполнения тела цикла значение счетчика увеличивается на единицу. При достижении счетчиком конечного значения операторы выполняются в последний раз, и управление передается первому оператору стоящему после цикла.

Вторая форма оператора

 for <счетчик>:=<начальное значение> downto <конечное значение> do

 begin

   <операторы>

end;

организует повторение последовательности операторов при изменении значений счетчика от конечного до начального, с шагом « минус единица».

Если начальное и конечное значения равны, то тело цикла выполняется только один раз. Если начальное значение превышает конечное (для первой формы оператора) или начальное значение меньше конечного (для второй формы оператора), то тела цикла не выполняется ни разу.

Значение счетчика внутри цикла изменять нельзя.

Как правило, с помощью оператора for организуют циклы с заранее известным количеством повторений.

Пример 3.1. Вычислить N! (1*2*3*...*N).

f := 1; for i := 1 to n do f := f * i;

Пример 3.2. Найти минимум функции  y(x)=sin2(x)+4*cos(x) на интервале [-1; 1] с точностью ε=0,01.

 a := -1; b := 1; //границы интервала

 n := Round((b-a)/eps) + 1; //расчет количества шагов

 x := a; // начальная (первая) точка интервала

 min := sqr(sin(x))+4*cos(x); //в качестве минимума принимается 

          //значение функции в начальной точке интервала

 for i := 1 to n do begin

    x := x+eps;  // переход к следующей точке

   y := sqr(sin(x))+4*cos(x); // расчет значения функции

   if y<min then min:=y; // проверка, является ли 

            // текущее значение у минимальным

 end;

Минимум с точностью ε находится путем перебора всех значений от а до b c шагом равным eps. В начале, в качестве минимума принимается значение функции в первой точке интервала. После этого перебираются все точки интервала с заданным шагом. Если текущее значение у меньше минимального, то оно принимается за минимум.

3.1.2. Организация цикла с помощью оператора repeat

Оператор

repeat

  <операторы>

until <условие>;

организует повторение операторов, помещенных между ключевыми словами repeat и until до тех пор, пока условие не примет значение истина (true). Так как условие проверяется после выполнения операторов цикла, то тело цикла всегда будет выполняться хотя бы один раз.

Пример 3.3. Вычислить N!  (1*2*3* ... *N).

 i := 1; f := 1;

 if n>1 then

    repeat

      i := i + 1;

      f := f * i;

    until (i>=N);

Такой способ вычисления факториала менее удобен, чем с использованием оператора for. Для того, чтобы при n<=1 не выполнялось тело цикла введена проверка.

Пример 3.4. Найти минимум функции y(x)-sin2(x)+4*cos(x) на интервале [-1; 1] с точностью ε=0,01.

 x:=a;

min:=sqr(sin(a))+4*cos(a);

 repeat

  x:=x+eps;

  y:= sqr(sin(x))+4*cos(x);

  if y<min then min:=y;

 until (x>=b);

Данный алгоритм более удобен, чем рассмотренный в примере 3.2.

 3.1.3. Организация цикла с помощью оператора while

 Данный оператор

  While <условие> do begin

  <операторы>

  end;

организует повторение операторов, помещеннх между begin и end, до тех пор, пока условие не примет значение ложь (false).

В отличие от оператора repeat, если условие будет равно false тело цикла не будет выполнено ни разу.

 Пример3.5. Вычислить N!  (1*2*3* ... *N).

 i := 0; f := 1;

 While i<N do begin

    i := i+1;

    f := f * i;

 end;

 Такой способ вычисления факториала менее удобен, чем с использованием оператора for.

 

Пример 3.6. Найти минимум функции  y(x) = sin2(x)+4*cos(x) на интервале [-1; 1] с точностью ε=0,01.

 x := a;

min := sqr(sin(a))+4*cos(a);

 while (x<=b) do begin

      x := x+eps;

   y := sqr(sin(x))+4*cos(x);

   if y<min then min := y;

 end;

Данный алгоритм более удобен, чем рассмотренный в примере 3.2.

  3.2. Организация вложенных циклов

Циклы могут быть вложены друг в друга.

 Пример 3.7. Вычислить таблицу значений функции   на интервале [a; b] с шагом h.

 x := a;

 repeat

   y := 0;

  for i := 1 to 10 do y := y+i*sin(i)/sqr(x);

  Memo1.Lines.Add(' При х=' + FloatToStrF(x, ffFixed, 4,1)+

        '    y='+ FloatToStrF(y, ffFixed, 8, 3));

  x := x+h;

 until (x > (b+h));

3.3. Организация прерывания цикла

Иногда необходимо прервать выполнение тела цикла до выполнения условия окончания. Можно использовать следующие процедуры и функции:

Continue – прерывает выполнение текущей итерации, и передает управление следующей итерации.

Break – прерывает тело любого цикла и передает управление следующему за циклом оператору.

Exit – прерывает не только тело цикла, но и прекращает выполнение процедуры или функции, в которой размещен этот цикл.

Abort – прерывает не только тело цикла, но и прекращает выполнение блока, в которой размещен этот цикл. Данная процедура генерирует «молчаливое» исключение, не связанное с сообщением об ошибке.

 3.4. Алгоритмы, использующие рекуррентную последовательность

Роследовательность чисел a0, a1, a2, ..., an называется рекуррентной, если каждый последующий ее член выражается через один или несколько предыдущих. Если для получения следующего значения последовательности требуется только один предыдущий элемент  ak=φ(ak-1), то это последовательность первого порядка. Для нахождения всех членов такой последовательности достаточно задать начальный элемент a0 .

 s:=sin(x);

 a:=1;

 for k:=1 to 100 do begin

    a:=-a*sqr(x)/(2*k*(2*k-1));

    s:=s+a*sin(x);

end;

При расчете удобно начинать расчет не с нулевого элемента, а с первого. Значение суммы в нулевом элементе рассчитывается до начала цикла (s:=sin(x)). Нерекуррентная часть добавляется при суммировании (s:=s+a*sin(x)).

    

   3.5. Пример написания программы

Задание: написать и отладить программу, которая выводит таблицу значений функции y(x) = sh(x) и ее разложения в ряд    для X изменяющихся в интервале от Xn до Xk  c шагом dX. Если проанализировать данный ряд, то вычисление k-го слагаемого (ak) через (k-1)-е слагаемое (ak-1) выражается рекуррентной формулой     Примерный интерфейс программы представлен на рис. 3.1, а текст программы - на листинге 3.1.

 

 

Рис. 3.1. Интерфейс программы

           Листинг 3.1

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,  StdCtrls, Math;

type

TForm1 = class(TForm)

Memo1: TMemo;

Button1: TButton;

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

Label4: TLabel;

Edit1: TEdit;

 Edit2: TEdit;

 Edit3: TEdit;

 Edit4: TEdit; 

procedure FormCreate(Sender: TObject);

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

//---------------------------------------------------------

procedure TForm1.FormCreate(Sender: TObject);

         //задание начальных значений в Edit`ах

 begin 

   Edit1.Text:='0,1';   

  Edit2.Text:='1';      

  Edit3.Text:='0,1';   

  Edit4.Text:='30';    

end;

//-----------------------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);

         //нажатие кнопки Выполнить

var k, n : integer;

  Xn,Xk,dX,s,x,y : extended;

begin  

  Xn:=StrToFloat(Edit1.Text);

  Xk:=StrToFloat(Edit2.Text);

  dX:=StrToFloat(Edit3.Text);

  n:=StrToInt(Edit4.Text);

  Memo1.Clear;

  x:=Xn;

  While x <= Xk do begin

     s := x;

     a := x;

     for k:=1 to n do begin

        a:=a * sqr(x) / (2*k*(2*k-1)); //выч. очередного слагаемого через предыдущее

       s:=s+a;

      end;

    y:=sinh(x); //для вычислен. гиперболич. синуса подключить модуль Math

    Memo1.Lines.Add(' при x='+FloatToStrF(x,ffFixed,4,2)+

                                           '  y='+ FloatToStrF(y, ffFixed,10,6)+

                                           '  s='+FloatToStrF(s, ffFixed,10,6));

    x:=x+dX;

           end; //цикла While

end;

//---------------------------------------------------------------------- 

 end.  

Следует заметить, что для решения подобной задачи не всегда возможно получить рекуррентное соотношение. В одних случаях оно получается довольно громоздким и получение его довольно затруднительно, в других случаях оно совсем не существует. Тогда можно обойтись и без рекуррентного соотношения. Рассмотрим тот же пример и составим обработчик Button1Click() без использования рекуррентного соотношения. В формуле   можно в цикле k последовательно вычислять очередное k-е слагаемое    и добавлять его в результат, т.е. в s.

//-----------------------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);

         //нажатие кнопки Выполнить

 var k, n, i : integer;

  Xn, Xk, dX, s, x, y, c, z : extended;

begin  

  Xn:=StrToFloat(Edit1.Text);

  Xk:=StrToFloat(Edit2.Text);

  dX:=StrToFloat(Edit3.Text);

  n:=StrToInt(Edit4.Text);  

    Memo1.Clear;

  x:=Xn;

 While x<=Xk do begin

    s:=0;

    for k:=0 to n do begin

       c := 1; for i := 1 to (2*k+1) do  c := c*x; //c - числитель очередного слагаемого

               z := 1; for i := 1 to (2*k+1) do z := z*i;   //z - знаменатель очередного слагаемого

               a := c/z;  //a - очередное слагаемое

      s := s+a;

    end;

    y:=sinh(x); //для вычислен. гиперболич. синуса подключить модуль Math

    Memo1.Lines.Add(' при x='+FloatToStrF(x,ffFixed,4,2)+

                                           '  y='+ FloatToStrF(y, ffFixed,10,6)+

                                           '  s='+FloatToStrF(s, ffFixed,10,6));

    x:=x+dX;

           end; //цикла While

 end;

//---------------------------------------------------------------------- 

      3.6. Индивидуальные задания

Ниже приведены 2 задания. Выбор задания для лабораторной работы производится преподавателем.

 Задание 1:

 По указанию преподавателя выберите вариант задачи. Нарисуйте схему алгоритма. Создайте интерфейс и напишите текст программы. Вывести на экран таблицу значений функции Y(x) и ее разложения в ряд S(x) для X изменяющихся от Xn до Xk с заданным шагом dX . Близость значений S(x) и Y(x) во всем диапазоне значений х указывает на правильность вычисления S(x) и Y(x).

        

Задание 2:   Составить алгоритм (блок-схему) решения задачи при помощи стандартных блоков: начало, конец, действие, проверка условия, ввод/вывод. Написать программу для выбранного варианта (вариант предлагается преподавателем). В качестве результата вывести значение суммы и количество слагаемых, которые обеспечивают заданную точность.

            Таблица 3.2

ВариантУсловие задания1Вычислить значение суммы следующего ряда с требуемой точностью (|x|<1 и вводятся): 2Вычислить значение суммы следующего ряда с требуемой точностью (|x|<1 и  вводятся): 3Вычислить значение суммы следующего ряда с требуемой точностью (|x|<1 и вводятся):  4Вычислить значение суммы следующего ряда с требуемой точностью (x и  вводятся):  5Вычислить значение суммы следующего ряда с требуемой точностью ( вводится): 6Вычислить значение суммы следующего ряда с требуемой точностью (x и вводятся):  7Вычислить значение суммы следующего ряда с требуемой точностью (x<= 2π  и  вводятся):  8Вычислить значение суммы следующего ряда с требуемой точностью (x<= 2π  и  вводятся): 9Вычислить значение суммы следующего ряда с требуемой точностью (x<= 2π  и  вводятся): 10Вычислить значение суммы следующего ряда с требуемой точностью (|x|<1 и  вводятся): 11Вычислить значение суммы следующего ряда с требуемой точностью (|x|<1 и  вводятся):  12Вычислить значение суммы следующего ряда с требуемой точностью (|x|<1  и  вводятся): 13Вычислить значение суммы следующего ряда с требуемой точностью (|x|<1 и  вводятся):  14Вычислить значение суммы следующего ряда с требуемой точностью (|x|<1 и  вводятся):  15Вычислить значение суммы следующего ряда с требуемой точностью (|x|<1 и  вводятся): 16Вычислить значение суммы следующего ряда с требуемой точностью (|x|<1 и  вводятся): 17Вычислить значение суммы следующего ряда с требуемой точностью (|x|<1 и  вводятся): 18Вычислить значение суммы следующего ряда с требуемой точностью (|x|<= π/2  и  вводятся):  19Вычислить значение суммы следующего ряда с требуемой точностью (|x|<=π/2  и  вводятся): 20Вычислить значение суммы следующего ряда с требуемой точностью (|x|<1  и  вводятся): 21Вычислить значение суммы следующего ряда с требуемой точностью (x  и  вводятся):  22Вычислить значение суммы следующего ряда с требуемой точностью (x  и  вводятся):  23Вычислить значение суммы следующего ряда с требуемой точностью (x и  вводятся): 24Вычислить значение суммы следующего ряда с требуемой точностью (x и  вводятся):  25Вычислить значение суммы следующего ряда с требуемой точностью ( и  вводятся):  

ЛАБОРАТОРНАЯ РАБОТА 4.

ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

МАССИВОВ

Цель лабораторной работы: изучить свойства компонента TStringGrid. Рассмотреть способы ввода массивов с помощью компонентов: TEdit, TStringGrid, TMemo. Написать программу с использованием массивов.

4.1. Работа с массивами

Массив – структура однотипных данных, каждый элемент которой хранится в отдельной ячейке, доступ к которой осуществляется по ее номеру. Массив характеризуется: имением массива, типом хранимых данных, размером и размерностью.

Каждый элемент массива обозначается именем, за которым в квадратных скобках следует один или несколько индексов, разделенных запятыми, например: a[1], bb[i], c12[i, j*2], q[1, 1, i*j-1]. В качестве индекса можно использовать любые порядковые типы за исключением LongInt.

Массив объявляется с помощью ключевого слова array:

type

<имя типа массива> = array [<перечисляемый тип>] of <тип элемента массива>;

var

<имя массива> : array [<перечисляемый тип>] of <тип элемента массива>;

Примеры описания массивов:

type

TMas=array[1..10] of integer; // Описание типа одномерного массива 

var

A : TMas; // Массив типа TMas 

B : array[1..10] of extended;  // Одномерный массив действительных чисел

D : array[1..10,1..10] of char; // Двумерный массив символьного типа 

Элементы массивов могут использоваться в выражениях так же, как и обычные переменные. Доступ к каждому элементу массива осуществляется по индексу заключенному в квадратные скобки, например:

A[j] := 5;

B[k ] := B[i]+A[j*2+k];

D[i, j] :=  2*A[i];

причем значение индексов не должно выходить за грaницы диапазона (m≤j≤n) указанного в описании. Чаще всего используются индексы целого типа, хотя возможны индексы порядкового типа (например Char).

Нумерация элементов в одномерных массивах ведется слева направо, а в двумерных массивах – первый индекс (номера строк) – сверху вниз, а второй индекс (номера столбцов) – слева направо. Например:

4.2. Операции над массивами

Однотипные массивы могут участвовать в операциях отношения «рaвно», «не рaвно» и в операторе присваивания. Например, если массивы объявлены 

type

  TMas1 = array[1..10] of integer;

var

  A, B : Tmas;

  C : array[1..10] of integer;

то, допустимы следующие операции:

выражение A = B принимаeт значения true если все элементы массива А и массива В одинаковы и false в противном случае;

выражение A <> B принимает значение true если массивы А и В отличаются хотя бы в одном элементе;

A := B элементам массива А присваиваются значения всех соответствующих элементов массива B.

Следует обратить внимание на то, что вышеперечисленные операции определены только для однотипных массивов. В данном примере массивы А и B являются однотипными, а массив C не является однотипным с массивами А и B, несмотря на то, что все эти массивы имеют одинаковую структуру. При попытке присваивания  A := C компилятор выдаст сообщение о несовместимости типов.

4.3. Примеры часто встречающихся алгоритмов работы с массивами

Пример 4.1. Вычислить сумму n элементов одномерного массива А   .

 S:=0;  

 for i:=1 to n do

    S:=S+A[i];

Пример 4.2. Вычислить сумму модулей всех элементов матрицы В .

 S:=0;  

 for i:=1 to n do

   for j:=1 to m do

      S:=S+abs(B[i, j]);

Пример 4.3. Вычислить сумму диагональных элементов квадратной матрицы В

 S:=0;  

 for i:=1 to n do

           S:=S+B[i, i];

Пример 4.4. Вычислить значение и номер максимального элемента одномерного массива А.

 max:=A[1]; // за максимум принимается первый элемент массива

 nmax:=1;    // номер максимального элемента массива равен 1

 for i:=1 to n do

   if A[i]>max then begin // если A[i] больше максимального, то ...

        max:=A[i];  // за максимум принимается A[i]

           nmax:=i;    // номер максимального элемента равен i

   end;

Пример 4.5. Переставить местами элементы одномерного массива А: первый элемент меняется с n-м, второй - с (n-1)-м, третий - с (n-2)-м и т.д.

 i := 1;  j := n;

 repeat

   r := A[i];

   A[i] := A[j];

   A[j] := r;

   i := i+1;

   j := j-1;

 until i >= j;

Для обмена данными между ячейками используется вспомогательная переменная r.

Пример 4.6. Переставить местами элементы квадратной матрицы А (размером n×m) относительно главной диагонали: все элементы, стоящие ниже главой диагонали поменять с элементами, которые стоят выше главной диагонали.

В квадратной матрице А размером n×m элементы главной диагонали имеют одинакорые индексы (ai,i , i=1, n). Каждому элементу, стоящему выше главой диагонали (ai,j , 1≤ i ≤ n-1,  i+1≤ j ≤ n) соответствует симметричный ему элемент, стоящий ниже главной диагонали (aj,i , 1≤ i ≤ n-1,  i+1≤ j ≤ n).

 for i := 1 to n-1 do

   for j := i+1 to n do begin

      r:=A[i, j];

      A[i, j] := A[j, i];

      A[j, i] := r;

   end;

Пример 4.7. В матрице А размера n×m переставить местами строки с номерами k1 и k2.

 for j:=1 to n do begin

    r:=A[k1, j];

     A[k1, j] := A[k2, j];

     A[k2, j] := r;

 end;

Пример 4.8. Отсортировать одномерный массив А в порядке возрастания элементов. Использовать метод пузырька.

for i := 2 to n do

    for j := n downto i do

         if A[j-1] > A[j] then begin

             r := A[j];

             A[j] := A[j-1];

           A[j-1] := r;

       end;

Для данного примера возможен и другой алгоритм (тот же метод пузырька):

  for i := 1 to n-1 do

       for j := i+1 to n do

          if A[j] < A[i] then begin

                r := A[i];

              A[i] := A[j];

              A[j] := r;

         end;

4.4. Компонент TStringGrid для ввода/вывода массивов

В Delphi имеется возможность организовать ввод/вывод двухмерных и одномерных массивов с отображением их на форме. Для этого используют специальный компонент TStringGrid (находится на странице Additional), который предназначен для отображения информации в виде двухмерной (одномерной) таблицы каждая ячейка которой представляет собой окно однострочного редактора (аналогично окну TEdit). Доступ к информации осуществляется с помощью свойства Cells[ACol : Integer; ARow : Integer] : String, где ACol, ARow – индексы элемента двумерного массива. Свойства ColCount и RowCount устанавливают количество столбцов и строк в таблице, а свойства FixedCols и FixedRows задают количество столбцов и строк фиксированной зоны. Фиксированная зона выделена другим цветом, и в нее запрещен ввод информации с клавиатуры.

4.5. Пример написания программы с использованием TStringGrid

Задание: Двухмерный массив (матрица) вещественных чисел A, размером NxM, вводится с клавиатуры (компонент TStringGrid). Найти количество положительных элементов массива и их сумму, а также количество отрицательных элементов массива и их произведение.

Интерфейс программы приведен на рис. 4.1, а текст программы - на Листинге 4.1.

Рис. 4.1. Интерфейс программы

В программе для задания числа строк и столбцов матрицы использованы компоненты TSpinEdit (страница Samples). Использование этих компонентов очень удобно для ввода целых чисел, т.к. у них есть такие свойства как MinValue и MaxValue, с помощью которых можно задавать диапазон изменения значений в компоненте. В данной программе следует задать эти свойства как: MinValue=1, MaxValue=10. Это будет означать, что значение переменной в поле TSpinEdit будет изменяться от 1 и до 10. Подстройка числа столбцов и строк таблицы TStringGrid в зависимости от значений переменных TSpinEdit выполняется в обработчиках OnChange (см. Листинг 4.1).

 Заметим, что вместо компонента TSpinEdit можно использовать комбинацию двух компонентов TEdit и TUpDown (компонент TUpDown находится на странице Win32). Для этого надо поместить на форму эти два компонента по отдельности, а затем с помощью свойства Associate связать  TUpDown с TEdit. Визуально это будет выглядеть так, что как будто компонент TUpDown "перепрыгнет" к TEdit и займет свое положение в конце поля TEdit.

Для упрощения и ускорения процесса ввода данных в ячейки таблицы можно сделать так, чтобы курсор автоматически переходил в следующую ячейку таблицы, например, в результате нажатия клавиши <Enter>. Сделать это можно при помощи процедуры обработки события OnKeyPress для таблицы. На эту же процедуру можно возложить задачу фильтрации данных, вводимых в ячейку таблицы.

В нашем случае надо разрешить:

    -ввод в ячейку только цифр;

    -ввод минуса только на первой позиции, т.е. когда ячейка пустая;

    -точку  автоматически заменять на запятую;

    -ввод только одной запятой.

    -при нажатии в ячейке клавиши <Enter>, курсор должен переходить на следующую ячейку, расположенную справа.

Текст процедуры обработки события OnKeyPress  для таблицы приведен также на Листинге 4.1.

           Листинг 4.1

unit Unit1;

interface

uses

 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

 Dialogs, Grids, StdCtrls, jpeg, ExtCtrls, Spin;

type

 TForm1 = class(TForm)

   Label1: TLabel;

   Label2: TLabel;

   StringGrid1: TStringGrid;

   Button2: TButton;

   Memo1: TMemo;

   Button1: TButton;

   Label3: TLabel;

   Image1: TImage;

   SpinEdit1: TSpinEdit;

   SpinEdit2: TSpinEdit;

   Label4: TLabel;

   Label5: TLabel;

   procedure FormCreate(Sender: TObject);

   procedure Button1Click(Sender: TObject);

   procedure StringGrid1KeyPress(Sender: TObject; var Key: Char);

   procedure SpinEdit1Change(Sender: TObject);

   procedure SpinEdit2Change(Sender: TObject);

 private

   { Private declarations }

  public

   { Public declarations }

 end;

Type

 TMatr = array[1..10,1..10] of real; // Объявление типа матрицы размером 10 х 10

var

 Form1: TForm1;

 A : TMatr;             // Глобальное объявление матрицы

       n, m : integer;  

implementation

{$R *.dfm}

//------------------------------------------------------------

procedure TForm1.FormCreate(Sender: TObject);

//первоначальное формирование интерфейса программы

var i, j: integer;

begin

 Memo1.Clear;

 SpinEdit1.Text := '4';

 SpinEdit2.Text := '4';

  With StringGrid1 do begin

    RowCount := StrToInt(SpinEdit1.Text)+1;

    ColCount := StrToInt(SpinEdit2.Text)+1;

    Cells[0, 0] := '    A';

    for i := 1 to RowCount do Cells[0,i] := '  i=' + IntToStr(i);

    for j := 1 to ColCount   do Cells[j,0] := '  j=' + IntToStr(j);

 end;

end;

//---------------------------------------------------------------

procedure TForm1.SpinEdit1Change(Sender: TObject);

//изменение Числа строк в таблице

var  i:integer;

begin

  if  SpinEdit1.Text = '' then Exit;

 //подготовка таблицы по строкам

 With StringGrid1 do begin

   RowCount:=StrToInt(SpinEdit1.Text)+1;

   for i:=1 to RowCount do Cells[0,i] := '  i=' + IntToStr(i);

 end;

end;

//--------------------------------------------------------

procedure TForm1.SpinEdit2Change(Sender: TObject);

//изменение Числа столбцов в таблице

var j : integer;

Begin

   if  SpinEdit2.Text='' then Exit;

 //подготовка таблицы по столбцам

 With StringGrid1 do begin

   ColCount := StrToInt(SpinEdit2.Text)+1;

   for j := 1 to ColCount do StringGrid1.Cells[j, 0] := '  j=' + IntToStr(j);

 end;

end;

//--------------------------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);

//выполнить

var

 i, j, k, ke : integer;

 p, pe : real;

 s : string;

begin

   {Проверка на заполненность таблицы}

   With StringGrid1 do begin

     for i := 1 to RowCount-1 do

         for j := 1 to ColCount-1 do

          if  Cells[j, i] = '' then begin

             ShowMessage('Надо заполнить все ячейки таблицы !!!');

             Exit;

         end;

   end;

    n := StrToInt(SpinEdit1.Text);  // число строк  матрицы

    m := StrToInt(SpinEdit2.Text); // число столбцов  матрицы

  {Заполнение матрицы А[1..n,1..m] элементами из таблицы StringGrid1}

  for i := 1 to n do

    for j := 1 to m do

      A[i, j] := StrToFloat(StringGrid1.Cells[j, i]);

  {Расчет}

  k := 0; ke := 0;

  p := 0; pe := 1;

  for i := 1 to n do

     for j := 1 to m do

      if A[i, j] > 0 then begin k := k+1; p := p+A[i, j]; end

     else

       if (A[i, j] < 0) then begin ke := ke+1; pe := pe * A[i, j]; end;

  

   {формируем обобщеную строку для показа в Мемо1 введенной матрицы }

   s:='Введенная матрица:'+#13#10;

   for i := 1 to n do begin

     for j := 1 to m do

        s := s+FloatToStr(A[i, j])+#9;

     s:=s+#13#10;

   end;

   Memo1.Clear;

   {показываем в Мемо1 введенную матрицу}

   Memo1.Lines.Add(s);

   {показываем в Мемо1 результаты расчета}

   if k = 0 then  Memo1.Lines.Add('Положительных элементов нет !')

   else begin

       Memo1.Lines.Add('Количество положительных элементов:  ' +IntToStr(k));

       Memo1.Lines.Add('Сумма положительных элементов:  ' + FloatToStr(p));

   end;

   Memo1.Lines.Add('');

   if ke = 0 then Memo1.Lines.Add('Отрицательных элементов нет !')

   else begin

       Memo1.Lines.Add('Количество отрицательных элементов:  ' +IntToStr(ke));

       Memo1.Lines.Add('Произведение отрицательных элементов:  '+ FloatToStr(pe));                  

   end;

 end;

//-------------------------------------------------------------------

procedure TForm1.StringGrid1KeyPress(Sender: TObject; var Key: Char);

//ВВОД В StringGrid ДОПУСТИМЫХ СИМВОЛОВ ВЕЩЕСТВЕННОГО ЧИСЛА

//По нажатию Enter курсор перемещается в выбранной строке слева направо.

//Если строка заканчивается, то происходит переход на следующую строку.

//Если курсор доходит до конца таблицы, то он возвращается на 1-ю ячейку.

Begin

  With StringGrid1 do begin

  if not (Key in ['0'..'9','-',',','.',#8,#13]) then Key:=#0; //разреш.символы

  if Key='-' then //минус ввод. только 1-м символом, т.е. когда ячейка пустая

             if Length(Cells[Col, Row]) <>0 then Key := Chr(0) ;

  if (Key='.') or (Key=',') then begin

        if Key='.' then Key:=','; // заменить точку на запятую

        if Pos(',' ,Cells[Col,Row])<>0 then Key := Chr(0); //запятая только одна

  end;// if

  if Key=#13 then begin  //Enter

     if (Row=RowCount-1) and (Col=ColCount-1) then begin //конец табл.

          Row:=1; Col:=1;

     end

     else

       if Col = ColCount-1 then begin //конец строки

          Row:=Row+1; Col:=1;

       end

       else

         if Col<ColCount-1 then Col := Col+1; //не конец строки

  end; //#13

 end; //With

end;

//---------------------------------------------------

end. 

          

 4.6. Компонент TEdit для ввода одномерных массивов

В Delphi ввод одномерных массивов, кроме использования компонента   TStringGrid , можно еще организовать и с использованием компонента TEdit. Зачастую это бывает проще, т.к. не надо дополнительно задавать размерность массива - она получается из подсчета слов в строке TEdit. Алгоритм ввода одномерного массива из строки TEdit состоит в разделении этой строки на отдельные слова, каждое из которых и есть компонент массива. Слова в строке друг от друга отделяются некоторыми разделителями, например, одним или несколькими пробелами - это и позволяет выделить из строки отдельные слова.

Заметим, что компонент TEdit удобно использовать для ввода только одномерного массива, для ввода двумерного массива он менее удобен, и в этом случае больше подходит TStringGrid.

4.7. Пример написания программы с использованием TEdit

Задание: Одномерный массив целых чисел A размерности n вводится из строки TEdit. Найти количество четных положительных элементов массива, и произведение отрицательных элементов.

Интерфейс программы приведен на рис. 4.2, а на листинге 4.2 - фрагмент программы (только обработчик TForm1.Button1Click() по  аналогии с примером 4.5)

    Рис. 4.2. Интерфейс программы

        Листинг 4.2

//---------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);

//нажатие кнопки Вычислить

var

 pe, k : integer;

 s, s1 : string;

 A:array [1..100] of integer;

begin

 {Ввод массива из строки Edit1}

 s := Edit1.Text;                  //получаем строку из Edit1

 s := Trim(s);                       //удаляем пробелы из строки s слева и справа

 while Pos( '  ', s ) > 0 do  //оставляем по одному пробелу между словами

      Delete( s, Pos( '  ', s ), 1 );

 s := s+' ';                  //искусственно добавляем один пробел в конец строки

 n := 0;                      //готовим  счетчик слов

 s1 := '';                    //готовим вспомогательную строку для слова

 for i := 1 to Length(s) do

    if s[i] = ' ' then begin       //если нашли очередное слово, то ...

      n := n+1;                        //увеличиваем счетчик слов

      A[n] := StrToInt(s1);     //преобразуем найденное слово в элемент массива

      s1 := '';                           //очищаем вспомогательную строку - готовим для след.слова

    end

    else s1 := s1+s[i];           //иначе продолжаем накапливать символы слова

 //показываем введенный массив в Мемо

 s:='Введенный массив  :'+#13#10;

 s:=s+'Индекс'+#9+'Значение'+#13#10;

 for i:=1 to n do

   s := s+IntToStr(i)+' :'+#9+InTtoStr(A[i])+#13#10;

 Memo1.Text := s;

 {расчет}

 k := 0;

 pe := 1;

  for i := 1 to n do

    if (A[i] > 0) and (not odd(A[i]))  then k := k + 1

    else   if (A[i] < 0) then pe := pe * A[i];

 { Вывод результата}

 Memo1.Lines.Add('Количество четных положительных элементов:  ' + IntToStr(k));                 

 Memo1.Lines.Add('Произведение отрицательных элементов:  ' + IntToStr(pe));          

end;

//---------------------------------------------------

 4.7. Компонент TMemo для ввода/вывода одномерных массивов

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

Компонент TМемо также можно использовать и для ввода двумерного массива, однако алгоритмически это более сложно, чем использование для этих целей компонента TStringGrid.

4.8. Пример написания программы с использованием TMemo

Задание: Ввести одномерный массив вещественных чисел Х размерности n из компонента TМемо.

Интерфейс программы приведен на рис. 4.3, а на листинге 4.3 - фрагмент программы (только обработчик TForm1.Button1Click( ) )

Рис. 4.3. Интерфейс программы

           Листинг 4.3

//--------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);

//Ввести массив

var

 X : array[1..20] of real;

 i, n : integer;

 s : string;

begin

 //проверка на отсутствие текста в Мемо1

 if  Memo1.Lines.Count = 0 then begin

     ShowMessage('В Мемо1 ничего не введено !!!');

     Exit;

 end;

 //читаем не пустые строки в Мемо1 и по ним формируем массив

 n := 0;

  for i := 1 to  Memo1.Lines.Count do

     if  Memo1.Lines[i-1] <> ''  then begin  //счет строк в Мемо1 идет с нуля

         n := n+1;

         X[n] := StrToFloat(Memo1.Lines[i-1]);

     end

     else continue;

 //формируем строку с элементами массива для вывода в Мемо2

 s := 'Введенный массив:' + #13#10 + 'Индекс' + #9 + 'Значение' + #13#10;

 for i := 1 to n do

     s := s + IntTostr(i) + ' :' + #9 + FloatToStr(x[i]) + #13#10;

 Memo2.Text := s;

end;

//---------------------------------------------------

4.9. Индивидуальные задания

Ниже приведены 3 задания: первое - на одномерные массивы, а два других - на двумерные. Выбор задания для лабораторной работы производится преподавателем.

Задание 1:  Одномерный массив (вариант задается преподавателем).

Во всех заданиях:  N - длина массива. Значения элементов массива вводятся с помощью компонента TEdit, TMemo или с помощью TStringGrid.

Таблица 4.1

ВариантЗадание1Дан массив из N вещественных чисел. Вычислить разность между максимальным и минимальным из них.2Дан массив из N вещественных чисел. Определить порядковый номер наименьшего из них.3Дан массив из N вещественных чисел, среди которых есть хотя бы одно отрицательное число. Найти количество отрицательных чисел и величину наибольшего  среди них.4Дан массив из N вещественных чисел. Определить, образуют ли они возрастающую последовательность.5Дан массив из N вещественных чисел. Определить количество отрицательных чисел и найти среди них минимальное число.6Дан массив из N вещественных чисел. Найти порядковый номер элемента, величина которого наиболее близка к какому-нибудь целому M, задаваемому с клавиатуры числу.7Дан массив из N целых чисел. Определить, сколько из них принимает наибольшее значение.8Дан массив из N целых чисел. Определить количество цифр в наиболее длинной подпоследовательности из подряд идущих нулей.9Дан массив из N вещественных чисел. Определить, сколько из них больше своих "соседей", т.е. предыдущего и последующего чисел.10Дан массив из N целых чисел. Определить, сколько раз в этом массиве величины элементов меняют знак. (Например, в последовательности элементов 1, -34, 8, 14, -5 знак меняется три раза).11Дан массив из N натуральных чисел. Вычислить сумму тех из них, порядковые номера которых - числа Фибоначчи. Числа Фибоначчи  определяются формулами: f0=f1=1; fn=fn-1 + fn-2 при n=2,3,....12Найти сумму положительных элементов массива и их порядковые номера.  13Найти сумму всех элементов массива, кратных заданному числу.14Найти сумму элементов массива с k1-го по k2-й, где k1 и k2 вводятся с клавиатуры. 15Найти сумму элементов массива, больших данного числа А (А вводится с клавиатуры).16Найти сумму элементов, принадлежащих промежутку от А до В (А и В вводятся с клавиатуры).17Найти максимальные элементы массива и их номера при условии, что есть повторяющиеся элементы.18Найти номера всех отрицательных элементов (вывести их на экран), если таких нет, то сообщить об этом.19Найти количество нечетных элементов.20Найти количество отрицательных элементов.21Сколько элементов массива превосходят по модулю заданное число А? 22Найти все элементы, кратные задаваемому с клавиатуры целому числу. Сколько их?23Есть ли в данном массиве два соседних положительных элемента? Найти номера элементов, образующих первую (последнюю) пару.24Есть ли в данном массиве элементы, равные заданному числу? Если есть, то вывести номер одного из них.25 Определить значения частного min/max, их среднее арифметическое и геометрическое значения элементов массива.26Написать программу, создающую массив из N чисел, первое вводится с клавиатуры, а каждое последующее равно квадрату предыдущего.

Задание 2:  Двумерный массив (вариант задается преподавателем)..

Во всех заданиях двумерный массив вводить c помощью компонента TStringGrid, в котором 0-й столбец и 0-ю строку использовать для отображения индексов массивов.

ВариантЗадание1Задан двухмерный массив целых чисел A размером M на N. Найти сумму элементов, расположенных ниже главной диагонали. 2Задан двухмерный массив целых чисел A размером M на N. Найти произведение элементов, расположенных выше главной диагонали. 3Задан двухмерный массив целых чисел A размером M на N. Найти сумму элементов, расположенных выше побочной диагонали. 4Задан двухмерный массив целых чисел A размером M на N. Найти произведение элементов, расположенных ниже побочной диагонали5Задан двухмерный массив целых чисел A размером M на N. Найти сумму элементов, расположенных ниже побочной диагонали6Задан двухмерный массив целых чисел A размером M на N. Найти количество элементов, расположенных выше главной диагонали.7Задан двухмерный массив целых чисел A размером M на N. Найти минимальный элемент, расположенный ниже главной диагонали.8Задан двухмерный массив целых чисел A размером M на N. Найти максимальный элемент, расположенный выше главной диагонали.9Задан двухмерный массив целых чисел A размером M на N. Найти максимальный элемент, расположенный выше побочной диагонали.10Задан двухмерный массив целых чисел A размером M на N. Найти минимальный элемент, расположенный ниже побочной диагонали.11Задан двухмерный массив целых чисел A размером N на M. Найти максимальный элемент и поменять его местами с элементом A[1,1].12Задан двухмерный массив целых чисел A размером N на M . Найти минимальный элемент и поменять его с элементом A[N,M].13Задан двухмерный массив целых чисел A размером N на M, состоящий из нулей и единиц. Найти количество нулей и единиц в этом массиве.14Задан двухмерный массив целых чисел A размером N на M. Найти число элементов A[i, j] > T и сумму этих элементов. 15Задан двухмерный массив целых чисел A размером N на M. Найти число элементов A[i,j] < T и произведение этих элементов.

Задание 3:  Двумерный массив (вариант задается преподавателем).

Все двумерные массивы в заданиях имеют размерность NxM, где N - число строк, М - число столбцов. Для квадратных массивов - рамерность NxN. В программе двумерные массивы вводить c помощью компонента TStringGrid, в котором 0-й столбец и 0-ю строку использовать для отображения индексов массивов.

Таблица 4.2

ВариантЗадание1Посчитать количество нулевых, положительных и отрицательных элементов двухмерного массива.2Определить произведение, сумму и среднее арифметическое элементов двухмерного массива.3Определить поотдельности произведение элементов 2-х двухмерных массивов и результирующее произведение.4Определить отношение суммы элементов двухмерного массива, стоящих на нечетных местах в строках, на сумму элементов, стоящих на четных местах.5Вывести все элементы двумерного массива, абсолютные значения которых меньше 1.6Подсчитать, сколько элементов двухмерного массива в интервале [А,В]. Вычислить количество элементов, не попавших ни в один из этих интервалов.7Для заданного двухмерного массива определить:- сумму всех положительных элементов;- произведение всех отрицательных элементов;- количество нулевых элементов;- среднее значение абсолютных величин всех элементов.8Для заданного двухмерного массива выполнить следующее:- подсчитать число элементов с начала до первого отрицательного;- подсчитать число отрицательных элементов.9Определить максимальный и минимальный элементы двухмерного массива  и их адреса. Вычислить сумму, разность, среднее арифметическое и геометрическое значения.10Для заданного двухмерного массива подсчитать число элементов, которые расположены за первым отрицательным элементом, и вычислить их среднее арифметическое.11Все элементы двухмерного массива, меньшие 1, заменить на их обратную величину. Полученный массив отсортировать в порядке возрастания.12Определить элемент двухмерного массива и его порядковый номер, значение синуса которого есть наибольшее число. Найти среднее значение синусов элементов этого массива.13Определить, что больше: сумма, разность или произведение максимального и минимального элементов двухмерного массива.14Для двух двухмерных массивов А и В определить:- средние значения;- наибольшие значения;- наименьшие значения;- сумму всех элементов каждого массива.15Найти разность суммы элементов двух заданных двухмерных массивов и их произведение. Определить, что больше.16Все отрицательные элементы двух квадратных массивов возвести в квадрат, а положительные умножить на 2. Найти сумму всех элементов модифицированных массивов.17Задан двумерный массив. Расположить положительные элементы в порядке возрастания. Отрицательные элементы остаются на своих первоначальных местах.18Написать программу, создающую двумерный массив из NxM целых случайных чисел (-10..10), и перемещающую отрицательные числа в конец массива. 19Написать программу, создающую массив  из NxM случайных целых чисел в диапазоне (0..100) и выводящую на экран среднее арифметическое чисел массива и массив отклонений от среднего      (B[i, j]=A[i, j]-Aср).20Написать программу, создающую двумерный массив из NxM случайных чисел и сортирующую первую строку массива по возрастанию, а вторую – по убыванию.21Даны два двухмерных массива (NхM). Получить третий массив размерностью 2Nx2M, состоящий из элементов первых двух.22В двумерном массиве отсортировать каждую строку по возрастанию.23Отсортировать двумерный массив по убыванию.24Отсортировать каждый столбец двумерного массива по убыванию.25Дан двумерный массив. Найти сумму элементов каждой строки массива.26Даны два массива NхN. Найти максимальное число (одно) из этих массивов.27Отсортировать главную диагональ двумерного массива NхN по убыванию.28Написать программу, создающую двумерный массив (NxN) элементы которого равны произведению их индексов (таблица Пифагора).29В массиве NхN расположить элементы каждой четверти по возрастанию. 30Дан двумерный массив NxN. Поменять местами левую и правую половину массива.31Написать программу, создающую двумерный массив (NxN) построчно заполненный числами от 1 до 2N, и меняющую местами верхнюю и нижнюю половину массива.32Для квадратного массива найти сумму элементов, расположенных в строках, содержащих  отрицательные элементы.33Для квадратного массива найти сумму и произведение элементов, расположенных на главной и второстепенной диагоналях массива.34Вычислить и вывести таблицу NхN, элементы которой равны сумме их индексов.

ЛАБОРАТОРНАЯ РАБОТА 5.

ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

СТРОКОВЫХ ДАННЫХ

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

5.1. Работа со строками

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

Строка - это последовательность символов.  В Object Pascal существует несколько строковых типов:

Тип данных      Максимальная длина         Используемая память       Используется для... 

ShortString   255 символов                      от 2 до 256 байт               Минимальная совместимость, хранение

                                   небольших строк

AnsiString   около 2^31 символов         от 4 байт до 2 Гб               8-битные символы (ANSI), DBCS ANSI,

                                                                                                                                                        MBCS ANSI и т.д.

WideString  около 2^30 символов          от 4 байт до 2 Гб             Юникод-символы -

                                                                                                                                                        многопользовательские сервера,  

                                                                                                                                                        мультиязыковые приложения

Для большинства целей подходит тип AnsiString (иногда называется LongString), а также универсальный тип String (аналог AnsiString).

Примеры описания строк:

type 

str_type = string[12];

const

n = 50;

var

s1: string;

s2, s3: str_type;

s4: string[n];

 s5, s6, s7: string[7];

Для работы со строками в Object Pascal`е существует довольно много процедур и функций, перечислять которые здесь не имеет смысла. Приведем только некоторые из них.

Стандартные функции и процедуры обработки строк:

  1.  Функция Length(Str: String) - возвращает длину строки (количество символов).

Пример:

var

  Str: String; L: Integer;

{ ... }

Str:='Привет!';

L:=Length(Str);  { L = 6 }

  1.   Функция SetLength(Str: String; NewLength: Integer) позволяет изменить длину строки. Если строка содержала большее количество символов, чем задано в функции, то "лишние" символы обрезаются.

Пример:

var Str: String;

{ ... }

Str:='Hello, world!';

SetLength(Str, 5); { Str = "Hello" }

  1.  Функция Pos(SubStr, Str: String) - возвращает позицию подстроки в строке. Нумерация символов начинается с единицы. В случае отсутствия подстроки в строке возращается 0.

Пример:

var Str1, Str2: String; P: Integer;

{ ... }

Str1:='Пример решения 1-й задачи';

Str2:='1-й';

P:=Pos(Str2, Str1);  { P = 16 }

  1.  Функция Copy(Str: String; Start, Length: Integer) - возвращает часть строки Str, начиная с символа Start длиной Length. Ограничений на Length нет - если оно превышает количество символов от Start до конца строки, то строка будет скопирована до конца.

Пример:

var Str1, Str2: String;

{ ... }

Str1:='Тест решения задачи';

Str2:=Copy(Str1, 6, 7); { Str2 = 'решения' }

  1.  Функция Delete(Str: String; Start, Length: Integer) - удаляет из строки Str символы, начиная с позиции Start длиной Length.

Пример:

var Str1: String;

{ ... }

Str1:= 'Тест решения задачи';

Delete(Str1, 6, 8); { Str1 = 'Тест задачи' }

  1.  Функции UpperCase(Str: String) и LowerCase(Str: String) преобразуют строку соответственно в верхний и нижний регистры:

Пример:

var Str1, Str2, Str3: String;

{ ... }

Str1:='hELLo';

Str2:=UpperCase(Str1); { Str2 = 'HELLO' }

Str3:=LowerCase(Str1); { Str3 = 'hello' }

Строки можно сравнивать друг с другом стандартным способом:

Пример:

var Str1, Str2, Str3: String; B1, B2: Boolean;

{ ... }

Str1 := '123';

Str2 := '456';

Str3 := '123';

B1 := (Str1 = Str2); { B1 = False }

B2 := (Str1 = Str3); { B2 = True }

Если строки полностью идентичны, логическое выражение станет равным True.

Помимо отмеченных стандатных фунций и процедур, существует еще довольно большое количество дополнительных, которые размещены в модуле StrUtils.pas. Чтобы подключить этот модуль к программе, нужно добавить его имя (StrUtils) в раздел Uses.

5.2. Пример написания программы

Задание:  Дана строка, в которой содержится текст, включающий в себя как русские, так и английские слова. Подсчитать каких букв больше: русских или английских?

На рис. 5.1 изображен интерфейс программы, а на листинге 5.1 - ее текст.

Рис 5.1. Интерфейс программы.

          Листинг 5.1

unit Unit1;

interface

uses

 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

 Dialogs, StdCtrls, ExtCtrls, jpeg;

type

 TForm1 = class(TForm)

   Button1: TButton;

   Label1: TLabel;

   Edit1: TEdit;

   Image1: TImage;

   Label2: TLabel;

   procedure Button1Click(Sender: TObject);

 private

   { Private declarations }

  public

   { Public declarations }

 end;

var

 Form1: TForm1;

implementation

{$R *.dfm}

//-------------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);

const

 EngChar = ['A'..'Z', 'a'..'z'];              //множество английских букв

 RusChar = ['Ё', 'ё', 'А'..'Я', 'а'..'я'];   //множество русских букв

var

 i, e, r: integer;

begin

 e := 0;

 r := 0;

 for i := 1 to Length (Edit1.Text) do begin  

     if  Edit1.Text [i] in EngChar then e := e+1;

     if Edit1.Text [i] in RusChar then  r := r+1;

 end;

 Label1.Caption := 'Английских символов - ' + IntToStr (e)+#13#10+

                               'Русских символов - ' + IntToStr (r);

end;

//------------------------------------------------

end.

5.3. Индивидуальные задания 

Во всех заданиях приведено по 2 задачи. Если возможно, то обе задачи можно объединить в одну и для нее разработать общий интерфейс и общее решение. Если это сделать нельзя, то каждую задачу следует решать отдельно.

Таблица 5.1

ВариантЗадание11. Дана строка. Подсчитать, сколько в ней букв (r, k, t).2. В строке заменить все двоеточия (:) точкой с запятой (;). Подсчитать количество замен.2         1. Дана строка, заканчивающаяся точкой. Подсчитать, сколько слов в строке.         2. Дана строка. Указать те слова, которые содержат хотя бы одну букву (с).31. Дана строка, содержащая английский текст. Найти количество слов, начинающихся с буквы (b).          2. Дана строка. Найти в ней те слова, которые начинаются и оканчиваются одной и той же буквой.41. Дана строка. Определить, сколько в ней символов (*) , ( ;) , (:) .2. В строке удалить символ "двоеточие" (:) и подсчитать количество замен.51. Дана строка, содержащая текст. Найти длину самого короткого слова и самого длинного слова.2. В строке вставить вместо пробела запятую и пробел.61. Дана строка символов, среди которых есть двоеточие (:). Определить, сколько символов ему предшествует.2. Удалить часть символьной строки, заключенной в скобки (вместе со скобками)71. Дана строка, содержащая текст, заканчивающийся точкой. Вывести на экран слова, содержащие три буквы.2. Определить сколько раз в строке встречается заданное слово. Заданное слово ввести с клавиатуры.81. Дана строка. Преобразовать ее, удалив каждый символ (*) и повторив каждый символ, отличный от (*) .2. В строке имеется точка с запятой (;). Подсчитать количество символов до точки с запятой и после нее.91. Дана строка. Определить, сколько раз входит в нее группа букв (abc).2. Дана строка. Преобразовать ее, заменив точками все двоеточия, встречающиеся среди первой половины символов строки, и заменив точками все восклицательные.101. Дана строка. Подсчитать количество букв (k) в последнем ее слове.2. Строка содержит одно слово. Проверить будет ли она одинаково читаться справа налево и слева направо (т.е. является ли оно палиандромом.)111. Дана строка. Подсчитать, сколько различных символов встречается в ней. Вывести их на экран.2. В записке слова зашифрованы – каждое из них записано наоборот. Расшифровать сообщение.121. Дана строка. Подсчитать самую длинную последовательность подряд идущих букв (a).2. Проверить, одинаковое ли число открывающихся и закрывающихся скобок в данной строке.131. Дана строка. Указать те слова, которые содержат хотя бы одну букву (k).2. Дана строка. Заменить в ней все парные символы на одиночные (например, аа -> а, тт -> т).141. Имеется строка, содержащая буквы латинского алфавита и цифры. Вывести на экран длину наибольшей последовательности цифр, идущих подряд.2. Дана строка, содержащая текст, заканчивающийся точкой. Вывести на экран слова, содержащие хотя бы одну букву (о).151. Дан набор слов, разделенных точкой с запятой (;). Набор заканчивается двоеточием (:). Определить, сколько в нем слов, заканчивающихся буквой (а).2. Дана строка, заканчивающаяся точкой. Подсчитать, сколько запятых в строке.

ЛАБОРАТОРНАЯ РАБОТА 6.

ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ

ПОДПРОГРАММ И МОДУЛЕЙ

Цель лабораторной работы: изучить возможности DELPHI для написания подпрограмм и создания модулей. Составить и отладить программу, использующую внешний модуль UNIT с подпрограммой.

6.1. Описание подпрограмм

Подпрограмма – это последовательность операторов, оформленная таким образом, что ее можно вызвать по имени из любого места программы. При вызове подпрограммы в нее передаются определенные данные, а из нее получают результат вычислений.

В языке Паскаль имеется два типа подпрограмм, различающихся способом обмена данными: процедуры (Procedure) и функции (Function).

Подпрограмма-функция описывается следующим образом:

Function <Имя функции>[(<формальные параметры>)]: <тип результата>;

 <описание типов, констант, переменных, вложенных процедур и функций>

 begin

 <операторы>

 [Result:=<результат соответствующего типа>]

 end;

Первая строка, содержащая имя функции называется заголовком. Параметры, которые описываются в заголовке функции называются формальными параметрами. Результат можно передать в основную программу используя ключевое слово Result или имя функции.

Пример 6.1. Составить программу для вычисления суммы квадратов натуральных чисел от 1 до n и оформить ее в виде функции.

Function Lux (N : integer) : integer;

Var s, i : integer;

Begin

  S:=0;

  for i:=1 to N do S:=S + Sqr(i);

  Result:=S;

 End;

Вызов функции в основной программе может иметь вид

w:=Lux (10);

где, w - переменная типа Integer.

Для преждевременного выхода из функции используется процедура Exit либо Abort (молчаливое исключение).

Рекомендуется оформлять подпрограмму в виде функции в том случае, когда результатом является значение одной переменной.

Подпрограмма-процедура описывается следующим образом:

Procedure <Имя процедуры>[(<формальные параметры)];

 <описание типов, констант, переменных, вложенных процедур и функций>

 begin

 <операторы>

 end;

Обмен данными с основной программой осуществляется с использованием действительных параметров.

Пример 6.2. Составить программу для вычисления суммы квадратов натуральных чисел от 1 до n и оформить ее в виде процедуры.

 Procedure Lux (N:integer; Var Sum:integer);

 Var i:integer;

 Begin

    Sum:=0;

    For i:=1 To N Do Sum:=Sum + Sqr(i);

 End;

Вызов процедуры в основной программе имеет вид

Lux ( 10,s );

где, s - переменная типа Integer.

При использовании в качестве параметров процедур данных сложного типа (массивы, множества, записи ) в основной программе необходимо предварительно описать имя типа этих данных, которые потом указываются в списке формальных параметров процедуры. Таким образом, данные сложного типа (массивы, множества, записи) передаются в процедуры только через их тип.

6.2. Передача данных через формальные параметры

Формальные параметры могут быть трех основных разновидностей:

Параметры-значения, параметры - переменные, параметры - константы.

Параметры-значения описываются следующим образом:

 <Имя процедуры> (a:Tип 1; c, d, e : Тип 2; ...)

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

Достоинством передачи данных с помощью формальных параметров является то, что в качестве фактического параметра можно использовать не только переменные, но и константы и арифметические выражения.

Например:  PAST(a, 5, (2*x+3))

К недостаткам такой передачи относятся дополнительные затраты памяти (например, большой массив) и затраты времени на копирования значений.

Параметры – переменные описываются следующим образом:

 <Имя процедуры> (Var a, b : Тип1; Var c, d, e : Тип2; ...)

При обращении к процедуре происходит не копирование фактических параметров а передача адреса ячейки памяти в которой находится фактическая переменная. Таким образом внутри процедуры происходит работа не с формальным параметром, а со ссылкой на фактический параметр. Любые изменения формальных параметров внутри процедуры ведут к изменению фактических параметров в основной программе. Используя такие параметры осуществляют передачу результатов выполнения процедуры в основную программу. Достоинством использования параметров-переменных является малая занимаемая память (только под указатель) и экономия времени (не надо перезаписывать данные). Недостаток: при обращении нельзя использовать константы и арифметические выражения.

Параметры – константы описываются следующим образом:

 <Имя процедуры> (Const a,b:Тип1;Const c,d,e:Тип2;...)

В этом случае фактическим параметром может быть переменная, константа или выражение. Для такого формального параметра новой ячейки не отводится, а при вызове подпрограммы в неё передается адрес ячейки фактического параметра, но внутри запрещены все его изменения.

Кроме рассмотренных трех основных типов формальных параметров можно использовать выходные параметры (out), которые невозможно изменять внутри программы и нетипизированные, которые используются для передачи данных. Параметры со значение по умолчанию позволяют передавать не все необходимые данные. Если данные не были переданы, то подставляется значение по умолчанию.

Кроме использования формальных параметров можно использовать глобальные параметры (видимые и в процедуре и в основной программе).

6.3. Процедурные типы

Язык Object Pascal позволяет объявлять типы и переменные процедурного типа, например:

type TPt1 = function(x:integer):integer;

var Pt1 : Tpt1;

Pt2 : procedure(var s:extended);

Использование процедурных типов позволяет использовать имя подпрограммы в качестве формального параметра.

6.4. Область видимости переменных

Все константы, типы, переменные, процедуры и функции могут использоваться только в определенных местах программы. Часть программы, в которой определен данный конкретный элемент называется областью видимости. При этом часто пользуются понятием блок, который состоит из объявления элемента и составного оператора:

 <объявление>

 begin

 <операторы>

 end;

Элементы называются локальными, если область видимости ограничена только блоком, в котором элемент объявлен. Если элемент объявлен и интерфейсной части модуля, то он будет виден во всех модулях, подключивших данный модуль, поэтому такой элемент является глобальным.

Если элемент объявлен в головном файле программы или в подпрограмме, то область его видимости начинается от точки объявления и заканчивается концом текущего блока.

Если элемент объявлен в интерфейсной части модуля, то область видимости будет включает текущий модуль, а так же все модули, которые подключили данный модуль.

Если элемент объявлен в разделе инициализации, то область видимости включает все подпрограммы, расположенные в данном разделе.

6.5. Пример написания программы с использованием процедур

Задание: Двухмерный массив (матрица) вещественных чисел A, размером NxM, вводится с клавиатуры (компонент TStringGrid). Найти количество положительных элементов массива и их сумму, а также количество отрицательных элементов массива и их произведение (см. пример 4.5). Оформить ввод двумерного массива из TStringGrid и его вывод в ТМемо процедурами.

Интерфейс программы будет таким же, что и примере 4.5, а текст программы с процедурами приведен на Листинге 6.1.

           Листинг 6.1

unit Unit1;

interface

uses

 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

 Dialogs, Grids, StdCtrls, jpeg, ExtCtrls, Spin;

type

 TForm1 = class(TForm)

   Label1: TLabel;

   Label2: TLabel;

   StringGrid1: TStringGrid;

   Button2: TButton;

   Memo1: TMemo;

   Button1: TButton;

   Label3: TLabel;

   Image1: TImage;

   SpinEdit1: TSpinEdit;

   SpinEdit2: TSpinEdit;

   Label4: TLabel;

   Label5: TLabel;

   procedure FormCreate(Sender: TObject);

   procedure Button1Click(Sender: TObject);

   procedure StringGrid1KeyPress(Sender: TObject; var Key: Char);

   procedure SpinEdit1Change(Sender: TObject);

   procedure SpinEdit2Change(Sender: TObject);

 private

   { Private declarations }

  public

   { Public declarations }

 end;

Type

 TMatr = array[1..10,1..10] of real; // Объявление типа матрицы размером 10х10

var

 Form1: TForm1;

 A : TMatr;            // Глобальное объявление матрицы

       n, m : integer;

implementation

{$R *.dfm}

//============================================================

Procedure Vvod_Matr_iz_Tabl(StringGrid : TStringGrid; var n, m : integer;

                                               var Matr : TMatr);

//ввод матрицы из StringGrid

var

 i, j : integer;

begin

 With StringGrid do begin

   n := RowCount-1; //число строк матрицы

   m := ColCount-1; //число столбцов матрицы

   for i := 1 to n do

     for j := 1 to m do

        Matr[i, j] := StrToFloat(Cells[j, i]);

 end;

end;

//============================================================

Procedure Vyvod_Matr(n, m : integer; Matr : TMatr;  Memo : TMemo);

//вывод матрицы в Мемо

var

 i, j : integer;

 St : string;

begin

 St := 'Введенная матрица:'+#13#10;

 for i := 1 to n do begin

   for j := 1 to m do

     St := St+FloatToStr(Matr[i, j])+#9;

   St := St+#13#10;

 end;

 Memo.Lines.Add(St);

end;

//============================================================

procedure TForm1.FormCreate(Sender: TObject);

//первоначальное формирование интерфейса программы

var i, j: integer;

begin

 Memo1.Clear;

 SpinEdit1.Text := '4';

 SpinEdit2.Text := '4';

  With StringGrid1 do begin

    RowCount:=StrToInt(SpinEdit1.Text)+1;

    ColCount:=StrToInt(SpinEdit2.Text)+1;

    Cells[0, 0] := '    A';

    for i:=1 to RowCount do Cells[0, i] := '  i=' + IntToStr(i);

    for j:=1 to ColCount   do Cells[j, 0] := '  j=' + IntToStr(j);

 end;

end;

//---------------------------------------------------------------

procedure TForm1.SpinEdit1Change(Sender: TObject);

//изменение Числа строк в таблице

var  i : integer;

begin

  if  SpinEdit1.Text = '' then Exit;

 //подготовка таблицы по строкам

 With StringGrid1 do begin

   RowCount := StrToInt(SpinEdit1.Text)+1;

   for i:=1 to RowCount do Cells[0, i] := '  i=' + IntToStr(i);

 end;

end;

//--------------------------------------------------------

procedure TForm1.SpinEdit2Change(Sender: TObject);

//изменение Числа столбцов в таблице

var j : integer;

Begin

   if  SpinEdit2.Text = '' then Exit;

 //подготовка таблицы по столбцам

 With StringGrid1 do begin

   ColCount := StrToInt(SpinEdit2.Text)+1;

   for j := 1 to ColCount do StringGrid1.Cells[j, 0] := '  j=' + IntToStr(j);

 end;

end;

//--------------------------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);

//выполнить

var

 i, j, k, ke : integer;

 p, pe : real;

 s : string;

begin

   {Проверка на заполненность таблицы}

   With StringGrid1 do begin

       for i := 1 to RowCount-1 do

         for  j := 1 to ColCount-1 do

            if  Cells[j, i] = '' then begin

               ShowMessage('Надо заполнить все ячейки таблицы !!!');

               Exit;

           end;

    end;

  {Ввод матрицы А из таблицы StringGrid1}

  Vvod_Matr_iz_Tabl(StringGrid1, n, m, A); //вызов процедуры

  {Расчет}

  k := 0; ke:=0;

  p:=0; pe := 1;

  for i := 1 to n do

     for j := 1 to m do

      if A[i, j] > 0 then begin k := k+1; p := p + A[i,j]; end

     else

       if (A[i,j] < 0) then begin ke := ke+1; pe := pe * A[i,j]; end;

    Memo1.Clear;

   {Показаваем в Мемо1 введенную матрицу А}

   Vyvod_Matr(n, m, A, Memo1); //вызов процедуры 

  

   {показываем в Мемо1 результаты расчета}

   if k=0 then  Memo1.Lines.Add('Положительных элементов нет !')

   else begin

       Memo1.Lines.Add('Количество положительных элементов:  ' +IntToStr(k));

       Memo1.Lines.Add('Сумма положительных элементов:  ' + FloatToStr(p));

   end;

   Memo1.Lines.Add('');

   if ke=0 then Memo1.Lines.Add('Отрицательных элементов нет !')

   else begin

       Memo1.Lines.Add('Количество отрицательных элементов:  ' +IntToStr(ke));

       Memo1.Lines.Add('Произведение отрицательных элементов:  '+ FloatToStr(pe));                  

   end;

 end;

//-------------------------------------------------------------------

procedure TForm1.StringGrid1KeyPress(Sender: TObject; var Key: Char);

begin

   {текст этой процедуры здесь не приводится, так как он полностью соответствует тексту  примера 4.5}

end;

//---------------------------------------------------

end. 

6.6. Использование модулей

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

Модуль – автономно компилируемая программная единица, включающая в себя процедуры, функции, а также различные разделы описаний. Структура модуля представлена в п.1.3 и содержит следующие основные части: заголовок, интерфейсная часть, исполняемая, инициирующая и завершающая (последние две части могут отсутствовать).

Заголовок состоит из зарезервированного слова Unit и следующего за ним имени модуля, которое должно совпадать с именем дискового файла. Использование имени модуля в разделе Uses основной программы приводит к установлению связи модуля с основной программой.

Интерфейсная часть расположена между ключевыми словами interface и implementation и содержит объявление тех конструкций и разделов описаний модуля, которые должны быть доступны другим программам.

Исполняемая часть начинается ключевым словом implementation и содержит описание процедур и функций, объявленных в интерфейсной части. Она может также содержать разделы описаний вспомогательных типов, констант, переменных, процедур и функций, которые будут использоваться только в исполняемой части и не будут доступны внешним программам.

Инициирующая часть начинается ключевым словом initialization и содержит операторы, которые исполняются перед началом выполнения основной программы (может отсутствовать).

Завершающая часть начинается ключевым словом finalization и выполняется в момент окончания работы программы (может отсутствовать).

Заголовок модуля состоит из слова Unit и следующего за ним имени модуля, которое служит для связи с другими модулями и основной программой. Имя модуля должно совпадать с именем файла на диске, в который помещается исходный текст модуля. Подключение модулей к разрабатываемой программной единице осуществляется с помощью оператора

Uses имя М1, имя М2, ..., имя Mn;

который должен стоять вначале раздела описаний т.е. сразу после заголовков Program, Interface или Implementation.

После подключения модуля в разрабатываемой программе становятся доступными все конструкции, описанные в интерфейсной части модуля.

6.7. Пример написания программы с использованием модуля

Задание: Текст задания такой же, что и в примере 6.5. Процедуры ввода двумерного массива из TStringGrid и его вывода в ТМемо оформить отдельным модулем, который далее будет подключен в основной программе.

Интерфейс программы будет таким же, что и примере 4.5, а текст модуля с процедурами приведен на Листинге 6.2.

6.7.1. Создание модуля

В среде Delphi модули могут создаваться как со своей формой, так и без нее. Для создания нового модуля без своей формы необходимо в меню File выбрать New – Unit. В результате будет создан файл с заголовком Unit Unit2. Имя модуля можно изменить на другое, отвечающее внутреннему содержанию модуля, например Unit MyUnit. Для этого необходимо сохранить модуль с новым именем (например, MyUnit.pas). Следует обратить внимание на то, что имя файла должно совпадать с именем модуля. После компиляции модуля (файл MyUnit.pas)  будет создан модуль для сборки пректа - файл с тем же именем, но с другим расширением ( .dcu), т.е. MyUnit.dcu  . Именно этот модуль (без расширения dcu) и надо прописывать в разделе uses основной программы (см. Листинг 6.3).

6.7.2. Подключение модуля

Для того чтобы подключить модуль к проекту, необходимо в меню Project выбрать опцию Add to Project… и выбрать файл, содержащий модуль. После этого в разделе Uses добавить имя подключаемого модуля – MyUnit. Теперь в проекте можно использовать функции, содержащиеся в модуле.

Интерфейс программы будет иметь вид как и в прошлой задаче(см. рис. 4.5).

Тексты модуля с процедурами (Листинг 6.2) и вызывающей программы (Листинг 6.3) приведены ниже.

Листинг 6.2 

unit MyUnit;

interface

uses

  SysUtils, Grids, StdCtrls, Dialogs;

type

 TMatr = array[1..20, 1..20] of real;

{здесь прописываются только заголовки процедур и функций}

Procedure Vvod_Matr_iz_Tabl(StringGrid:TStringGrid;var n, m : integer;

                                                   var Matr:TMatr);

Procedure Vyvod_Matr(n, m : integer; Matr: TMatr; Memo : TMemo);

implementation

{ниже прописываются сами процедуры и функции}

//==================================================

Procedure Vvod_Matr_iz_Tabl(StringGrid:TStringGrid;var n,m:integer;

                                                     var Matr:TMatr);

//ввод матрицы из StringGrid

var

 i, j : integer;

begin

 with StringGrid do begin

   n:=RowCount-1; //число строк

   m:=ColCount-1; //число столбцов

   for i:=1 to n do

     for j:=1 to m do

        Matr[i,j]:=StrToFloat(Cells[j,i]);

 end;

end;

//===================================================

Procedure Vyvod_Matr(n, m : integer; Matr:TMatr; Memo:TMemo);

//вывод матрицы в Мемо

var

 i, j : integer;

 St : string;

begin

 St:='Введенная матрица:'+#13#10;

 for i:=1 to n do begin

   for j:=1 to m do

      St := St + FloatToStr(Matr[i, j])+#9;

   St := St + #13#10;

 end;

 Memo.Lines.Add(St);

end;

//===================================================

end.

Этот модуль компилируется отдельно, а затем подключается в разделе uses основной программы (см. Листинг 6.3).

 

Листинг 6.3

unit Unit1;

interface

uses

 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

 Dialogs, Grids, StdCtrls, jpeg, ExtCtrls, Spin, MyUnit;  //подключили модуль MyUnit

type

 TForm1 = class(TForm)

   Label1: TLabel;

   Label2: TLabel;

   StringGrid1: TStringGrid;

   Button2: TButton;

   Memo1: TMemo;

   Button1: TButton;

   Label3: TLabel;

   Image1: TImage;

   SpinEdit1: TSpinEdit;

   SpinEdit2: TSpinEdit;

   Label4: TLabel;

   Label5: TLabel;

   procedure FormCreate(Sender: TObject);

   procedure Button1Click(Sender: TObject);

   procedure StringGrid1KeyPress(Sender: TObject; var Key: Char);

   procedure SpinEdit1Change(Sender: TObject);

   procedure SpinEdit2Change(Sender: TObject);

 private

   { Private declarations }

  public

   { Public declarations }

 end;

Type

 TMatr = array[1..10,1..10] of real; // Объявление типа двухмерного

                          // массива размером 10 x 10

var

 Form1: TForm1;

 A : TMatr;   // Глобальное объявление двухмерного массива

       n, m : integer;

implementation

{$R *.dfm}

{ Здесь уже не надо прописывать процедуры, т.к. они есть в подключ. модуле MyUnit }

//-------------------------------------------------------------

procedure TForm1.FormCreate(Sender: TObject);

//первоначальное формирование интерфейса программы

var i, j: integer;

begin

 Memo1.Clear;

 SpinEdit1.Text := '4';

 SpinEdit2.Text := '4';

  With StringGrid1 do begin

    RowCount:=StrToInt(SpinEdit1.Text)+1;

    ColCount:=StrToInt(SpinEdit2.Text)+1;

    Cells[0,0] := '    A';

    for i:=1 to RowCount do Cells[0,i] := '  i=' + IntToStr(i);

    for j:=1 to ColCount   do Cells[j,0] := '  j=' + IntToStr(j);

 end;

end;

//---------------------------------------------------------------

procedure TForm1.SpinEdit1Change(Sender: TObject);

//изменение Числа строк в таблице

var  i:integer;

begin

  if  SpinEdit1.Text='' then Exit;

 //подготовка таблицы по строкам

 With StringGrid1 do begin

   RowCount:=StrToInt(SpinEdit1.Text)+1;

   for i:=1 to RowCount do Cells[0,i] := '  i=' + IntToStr(i);

 end;

end;

//--------------------------------------------------------

procedure TForm1.SpinEdit2Change(Sender: TObject);

//изменение Числа столбцов в таблице

var j : integer;

Begin

   if  SpinEdit2.Text='' then Exit;

 //подготовка таблицы по столбцам

 With StringGrid1 do begin

   ColCount:=StrToInt(SpinEdit2.Text)+1;

   for j:=1 to ColCount do StringGrid1.Cells[j,0] := '  j=' + IntToStr(j);

 end;

end;

//--------------------------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);

//выполнить

var

 i, j, k, ke : integer;

 p, pe : real;

 s : string;

begin

   n := StrToInt(SpinEdit1.Text); // Число строк в массиве

   m := StrToInt(SpinEdit2.Text); // Число столбцов в массиве

   {Проверка на заполненность таблицы}

   for i:=1 to n do

       for j:=1 to m do

        if  StringGrid1.Cells[j,i]='' then begin

           ShowMessage('Надо заполнить все ячейки таблицы !!!');

           Exit;

       end;

  {Ввод матрицы А из таблицы StringGrid1}

 Vvod_Matr_iz_Tabl(StringGrid1, n, m, A); //вызов процедуры, текст которой

           //находится в модуле MyUnit

  {Расчет}

  k := 0; ke:=0;

  p:=0; pe := 1;

  for i := 1 to n do

     for j := 1 to m do

      if A[i, j]>0 then begin k := k+1; p:=p+A[i,j]; end

     else

       if (A[i,j]<0) then begin ke:=ke+1; pe := pe * A[i,j]; end;

    Memo1.Clear;

   {Показаваем в Мемо1 введенную матрицу А}

   Vyvod_Matr(n, m, A, Memo1); //вызов процедуры, текст которой находится в MyUnit 

  

   {показываем в Мемо1 результаты расчета}

   if k=0 then  Memo1.Lines.Add('Положительных элементов нет !')

   else begin

       Memo1.Lines.Add('Количество положительных элементов:  ' +IntToStr(k));

       Memo1.Lines.Add('Сумма положительных элементов:  ' + FloatToStr(p));

   end;

   Memo1.Lines.Add('');

   if ke=0 then Memo1.Lines.Add('Отрицательных элементов нет !')

   else begin

       Memo1.Lines.Add('Количество отрицательных элементов:  ' +IntToStr(ke));

       Memo1.Lines.Add('Произведение отрицательных элементов:  '+ FloatToStr(pe));                  

   end;

 end;

//-------------------------------------------------------------------

procedure TForm1.StringGrid1KeyPress(Sender: TObject; var Key: Char);

begin

   {текст этой процедуры здесь не приводится, так как он полностью соответствует тексту  примера 4.5}

end;

//---------------------------------------------------

end. 

  

6.8. Индивидуальные задания 

По указанию преподавателя выберите вариант задачи. Составьте программу, оформив вычисления в виде подпрограммы (процедуры или функции). В головной программе произвести ввод исходных данных, вызов подпрограммы и вывод результатов.

           Таблица 6.1

ВариантЗадание1В вещественной квадратной матрице N-го порядка найти максимальный и минимальный элементы. Переставить строки, в которых они находятся. Если они находятся в одной строке, выдать об этом сообщение.2Дана вещественная матрица размером NxM. Переставляя ее строки и столбцы, добиться того, чтобы наибольший элемент (один из них) оказался в левом верхнем углу.3Задана одномерная матрица N-го порядка, содержащая нули и целые числа. Заменить нули полусуммой последующего и предыдущего чисел. Если нуль является первым или последним числом матрицы, то его соответственно заменить последующим или предыдущим числом.4Определить, является ли заданная матрица N-го порядка магическим квадратом, т.е. такой, в которой сумма элементов во всех строках и столбцах одинакова.5Дана целочисленная матрица размером NxM. Найти сумму наименьших элементов ее нечетных строк и наибольших элементов ее четных строк.6Дана действительная квадратная матрица N-го порядка. Рассмотрим те элементы, которые расположены в строках, начинающихся с отрицательного элемента. Найти сумму тех из них, которые расположены ниже главной диагонали матрицы.7Дана вещественная квадратная матрица N-го порядка. Получить целочисленную квадратную матрицу, в которой элемент равен 1, если соответствующий ему элемент исходной матрицы больше элемента, расположенного на главной диагонали, и равен 0 в противном случае.8Дана квадратная целочисленная матрица N-го порядка. Упорядочить элементы в строках по возрастанию.9Дана действительная квадратная матрица N-го порядка. Рассмотрим те элементы, которые расположены в строках, начинающихся с отрицательного элемента. Найти сумму тех из них, которые расположены на главной диагонали матрицы.10Дана квадратная целочисленная матрица N-го порядка. Упорядочить элементы в столбцах по убыванию. 11Дана квадратная целочисленная матрица N-го порядка. Найти минимальный элемент среди положительных и максимальный среди отрицательных и их координаты.12Дана квадратная целочисленная матрица N-го порядка. Найти суммы элементов, расположенных на линиях, параллельных главной диагонали матрицы и находящихся выше нее.13Задана матрица размером NxM. Определить K - количество «особых» элементов матрицы, считая, что элемент «особый», если он больше суммы остальных элементов своего столбца.14Дана квадратная целочисленная матрица N-го порядка. Найти сумму элементов тех строк матрицы, у которых на главной диагонали расположены отрицательные элементы.15Определить, является ли заданная квадратная матрица n-го порядка симметричной относительно главной диагонали.

ЛАБОРАТОРНАЯ РАБОТА 7.

ПОСТРОЕНИЕ ГРАФИКОВ

Цель лабораторной работы: изучить принцип построения графиков с помощью компонента TChart. Написать программу по построению графика f(x) с использованием TChart.

7.1. Компонент TChart

 Компонент Delphi TChart располагается на странице Additional Палитры компонентов. Это богатый возможностями, очень мощный компонент, позволяющий строить двух и трехмерные красивые диаграммы на основе разнообразных данных. Он имеет большое количество разнообразных свойств. Часть из них, в свою очередь, являются объектами и обладают собственными свойствами.

Значок на Палитре компонентов имеет вид     . Расположенный компонент на форме будет выглядеть так (рис. 7.1) и имя ему присваивается по умолчанию Chart1:

   Рис. 7.1. Окно компонента Chart1

Настройка свойств компонента Chart1 происходит в редакторе Editing Chart. Вызвать его можно двойным щелчком по компоненту или используя свойство SeriesList Инспектора объектов. Появится следующее окно (рис. 7.2):

Рис. 7.2. Редактор компонента диаграмм и графиков Chart1

Основные параметры диаграммы определяются на вкладке Chart1 (диаграмма), она, в свою очередь, состоит из набора дополнительных панелей.

Панель Ряд данных (Series) важная, в ней можно добавить на один график несколько диаграмм с помощью кнопки Add. При этом над значениями данных можно выполнять операции задаваемые во вкладке Series -> Data Source выбрав function выбрав функцию из списка function.

Панель Общие (General) содержит следующие элементы управления:

  •  кнопка Export - экспорт изображения в файл,
  •  кнопка Print Preview - предварительный просмотр и печать диаграммы,
  •  панель Zoom - масштабирование,
  •  панель AllowScroll - отвечает за прокрутку изображения.

Средства панели Оси (Axis) регулируют настройку координатных осей, заголовков, их масштаб, шаг пунктирной сетки и многое другое.

Панель Заголовков (Titles) помогает оформить заголовки.

Панель Легенда (Legend) отвечает за внешний вид и содержание легенды.

Панель Панель (Panel) задает оформление панели основы: цвет и форму границы панели (можно сделать так, что диаграмма будет расположена на панели имеющей градиентную заливку).

Панель Страницы (Paging), позволяет разделить диаграммы на страницы. Для этого необходимо в поле (точки на странице) Points per Page подобрать соответствующее значение.

Панель Границы (Walls) отвечает за цвет и границы диаграммы.

Панель 3D дает возможность настройки 3D эффектов, (изменение масштаба, положения в пространстве), простым передвиганием ползунков управления.

Вкладка Ряды данных (Series) отвечает за оформление каждого ряда данных (графиков добавленных с помощью вкладки Chart). Текущий ряд данных задается с помощью раскрывающегося списка. Наиболее важная панель Источник данных данных (Data Sourece). В ней можно выбрать отказ от генерации значений (No Data), создать случайные значения (Random Values) или сформировать значения, как результат применения функции (список Function) к значениям рядов.

Чтобы добавить график или диаграмму выберете вкладку Add. Появится диалоговое окно TeeChartGallery, затем выберите Line (он выбран по умолчанию) и снимите флажок трехмерного отображения (рис. 7.3)

Рис. 7.3. Окно выбора отображения информации в Chart1

Нажмите OK. По умолчанию имя вашего графика Series1 (рис. 7.4) – это один из множества возможных наборов точек данных принадлежащих объекту Chart. При этом каждый конкретный набор точек данных – это также объект, принадлежащий диаграмме.

Каждый набор имеет множество опций для отображения его на диаграмме. В данном случае под диаграммой понимается сам объект Chart1.

Также необходимо отметить, что класс TChart к которому принадлежит компонент Chart1  является наследником класса TPanel, поэтому он обладает родительским свойством parent и может содержать в себе некоторые другие объекты типа TButton, TSpeedButton и т.д. Фактически это более усложненная панель для отображения.

Рис. 7.4. С помощью кнопки «Add» можно добавлять графики и диаграммы с именами по умолчанию Series2, Series3 и т.д.

Для задания отображаемых значений используются методы серии Series.

Основные:

Метод Clear очищает серию от занесенных ранее данных.

Метод Add:

 Add(const AValue: Double; const ALabel: String; AColor: TColor)

позволяет добавить в диаграмму новую точку (x). Параметр AValue соответствует добавляемому значению, параметр ALabel - название, которое будет отображаться на диаграмме и в легенде, AColor - цвет. Заметим, что параметр ALabel - не обязательный, его можно задать пустым: ' '.

Метод AddXY:

AddXY(const AXValue, AYValue: Double; const ALabel: String; AColor: TColor)

позволяет добавить в график функции новую точку (x, y). Параметр AXValue и AYValue соответствуют аргументу и функции. Параметр ALabel и AColor те же, что и в методе Add.

Рассмотрим некоторые примеры.

Пример использования метода Add для свойства Series. Например, чтобы заполнить круговую диаграмму, отображающую доли 6 различных значений, можно использовать следующий код:

Chart1.Series[0].Add(135,'Домашние сети'); Chart1.Series[0].Add(123,'ADSL'); Chart1.Series[0].Add(99,'Коммутируемые'); Chart1.Series[0].Add(52,'Кабельные сети'); Chart1.Series[0].Add(19,'GPRS'); Chart1.Series[0].Add(17,'Другие типы');

Для выбора заголовка диаграммы используется свойство Text.Title, являющееся списком строк. В типичном случае следует лишь изменить 0-й элемент этого списка, который по умолчанию имеет значение "TChart":

Chart1.Title.Text[0]:='Типы подключения к Интернету в Москве';

Если разместить на форму кнопку, а приведенный выше код использовать в качестве обработчика события OnClick, то при нажатии не нее в области построения будет выводиться соответствующая диаграмма (рис. 7.5).

Рис. 7.5. Построенная диаграмма

Пример использования метода AddXY для свойства Series.

Обработчик события OnActivate формы создает график, показанный на рис.7.6.

 

procedure TForm1.FormActivate(Sender: TObject);

var k: integer;

begin

 for k:=0 to 20 do

 Chart1.SeriesList[0].AddXY(k, cos(k*pi/5),' ', clRed);

end;

Рис.7.6. Пример использования компонента TChart 

Так же возможна печать диаграммы (графика), для чего у компонента Chart1 имеется метод Print, так что выводить построенные диаграммы на печать чрезвычайно просто:

Chart1.Print;

7.2. Пример написания программы

Задание: Написать программу, которая с помощью компонента TChart строит

график функции

    

на отрезке (Хн - Хк) с шагом dX.

Значения Хн, Хк, dX вводятся с клавиатуры в компоненты TLabeledEdit.

Вычисление f(x) для любого Х оформить в виде подпрограммы-функции.

 Интерфейс программы приведен на рис. 7.7, а текст - в листинге 7.1.

Рис. 7.7. Интерфейс программы.

         Листинг 7.1

unit Gr_ChartU;

interface

uses

 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

 Dialogs, ExtCtrls, jpeg, StdCtrls, Buttons, TeeProcs, TeEngine, Chart,

 Series;

type

 TForm1 = class(TForm)

   XXn: TLabeledEdit;

   XXk: TLabeledEdit;

   ddX: TLabeledEdit;

   Chart1: TChart;

   BitBtn1: TBitBtn;

   Series1: TLineSeries;

   Image1: TImage;

   procedure BitBtn1Click(Sender: TObject);

 private

   { Private declarations }

 public

   { Public declarations }

 end;

var

 Form1: TForm1;

implementation

{$R *.dfm}

//==========================================

Function f(x : real) : real;

// вычисление функции  f(x)

begin

 if x < -1 then Result := exp(x);

 if (x > -1) and (x < 0) then Result := 1/exp(x) + exp(5*ln(x+1));

  if x > 1 then Result := exp(-x);

end;

//==========================================

procedure TForm1.BitBtn1Click(Sender: TObject);

// построить

var

 Xn, Xk, dX, X : real;

begin

 Xn:=StrToFloat(XXn.Text);

 Xk:=StrToFloat(XXk.Text);

 dX:=StrToFloat(ddX.Text);

 Series1.Clear;

 X:=Xn;

 While X<=Xk do begin

    Series1.AddXY(X, f(X),'', clRed);

    X:=X+dX;

 end;

end;

//---------------------------------------------

end.

7.3. Пример написания программы

Построить график функции (с помощью компонента TChart), которая приведена ниже. В качестве f(x) использовать по выбору (компонент TRadioGroup): cos(x), x2 или sin(x). Значения: у, диапазон (Xнач - Хкон) и шаг dX вводятся с клавиатуры.

Примерный интерфейс программы приведен на рис. 7.7, а фрагмент программы (только функция и обработчик Button1Click() ) - в Листинге 7.2.

Рис. 7.7. Интерфейс программы

           Листинг 7.2

//=============================================

Function f(x, y : real; RadioGroup : TRadioGroup) : real;

//фунция

var fx : real;

begin

 case RadioGroup.ItemIndex of

    0 : fx := cos(x);

    1 : fx := sqr(x);

    2 : fx := sin(x);

  end;

 if  fx > 0.5 then f := sqr(x+y)-sqrt(y);

 if  (fx > -0.5) and (fx <= 0.5) then f := sqr(x+y)+power(x*y,3);

  if  fx < -0.5 then f := sqr(x+y)+ln(y);

end;

//=============================================

procedure TForm1.Button1Click(Sender: TObject);

//построить

var

 Xn, Xk, Y, x, dX : real;

begin

  Y:=StrToFloat(Edit1.Text);    //получаем у

  Xn:=StrToFloat(Edit2.Text) ; //получаем Хнач

  Xk:=StrToFloat(Edit3.Text);  //получаем Хкон

  dX:=StrToFloat(Edit4.Text);  //получаем шаг dХ

  Series1.Clear;

  x := Xn;

  while x <= Xk do begin

    Series1.AddXY(X, f(x,y,RadioGroup1), '',  clRed);

    x := x + dX;

  end;

end;

//--------------------------------------------

7.4. Индивидуальные задания

Варианты заданий взять из лабораторной работы № 2 (пункт 2.7, стр.24).

Диапазон изменения Х, шаг dX и значение Y для графика выбрать самостоятельно. Вычисление функции f(x) для любого Х оформить в виде подпрограммы-функции.

ЛАБОРАТОРНАЯ РАБОТА 8.

РАБОТА С ФАЙЛАМИ

Под файлом понимается именованная область внешней памяти компьютера.

Любой файл имеет три характерные особенности:

1. Файл имеет имя, что дает возможность программе работать одновременно с несколькими файлами;

2. Файл содержит компоненты одного типа;

3. Длина создаваемого файла не оговаривается при его объявлении и ограничивается только размером устройств внешней памяти.

Работа с файлами важная вещь в любом языке программирования. Работа с файлами в Delphi позволяет считывать, сохранять информацию, и выполнять другие действия с файлами. В Delphi поддерживаются все операции с файлами - создание, поиск, чтение и запись, переименование как файлов, так и к директорий. В Delphi существует несколько способов работы с файлами.

Работать с файлами в Delphi можно как с помощью компонентов, которые имеют свойства и методы такой работы, так и напрямую с помощью процедур и функий Object Pascal`я.

  8.1. Компоненты для работы с файлами в Delphi

Сначала рассмотрим компоненты Delphi, которые умеют работать с файлами. Они читают и сохраняют своё содержимое, строки типа String, в файл текстового формата. Это компоненты TStringList, TListBox, TComboBox и TMemo, расположенные на первой  вкладке палитры компонентов. Содержимое этих компонентов очень легко записать в файл с помощью только одной команды, а также считать из файла тоже с помощью одной команды. Каждая строка компонентов TListBox и TComboBox является объектом Items[i], а TMemo - Lines[i], где i - номер строки, который отсчитывается от нуля. Добавление строк в компоненты выполняется методами Add и Insert:begin  Memo1.Lines.Add('Первая строка');  ComboBox1.Items.Add('Первая строка');  ComboBox1.Items.Add('Вторая строка');  ListBox1.Items.Add('Первая строка');  ListBox1.Items.Add('Вторая строка');end ;Метод Add добавляет новую строку в конец. Метод Insert имеет дополнительный параметр, указывающий, после какой строки разместить новую строку. Доступ к строкам осуществляется так:ComboBox1.Items[0] := 'Первая строка изменилась' ;ListBox1.Items[1] := 'Вторая строка изменилась' ;

У компонентов TComboBox и TMemo дополнительно есть свойство Text, где (как и у компонента Edit) находится вводимый текст:ComboBox1.Text := ' Вводимый текст ';

Memo1.Text := 'Новый текст';На выделенную в данный момент строку компонента TComboBox указывает свойство ItemIndex типа Integer, т.е. это номер выделенной строки. Следовательно, получить саму выделенную строку компонента ComboBox можно следующей конструкцией:S:=ComboBox1.Items[ComboBox1.ItemIndex];или, пользуясь оператором присоединенияWith ComboBox1 do S:=Items[ItemIndex];

Впрочем, чтобы стереть всё сразу, есть метод Clear во всех этих компонентах.Ну а теперь собственно о сохранении содержимого в файл. Для этого выполните командуListBox1.Items.SaveToFile(' Имя_файла.txt ') ;Расширение можно поставить любое по желанию, не обязательно .txt, как и вообще без него обойтись. Но расширение .txt позволит легко открыть файл стандартным виндовским Блокнотом, что бывает очень удобно на этапе написания программы!Для загрузки из файла служит метод LoadFromFile:ListBox1.Items.LoadFromFile(' Имя_файла.txt ') ;Что делать, если в своей программе мы не работаем с компонентами Combobox, ListBox или Memo, а сохранять информацию нужно? Все очень просто - берём один из компонентов и делаем его невидимым, для этого в Инспекторе Объектов ставим в свойство Visible значение False. Функциональность его от этого не изменится, а дальше с ним работаем как обычно. В конце работы с файлами этот компонент можно удалить.

 8.2. Прямая работа с файлами (классический способ)

Технология работы с файлами в системе Delphi требует определённого порядка действий:

  1.  Прежде всего файл должен быть открыт. Система следит, чтобы другие приложения не мешали работе с файлом. При этом определяется, в каком режиме открывается файл - для изменения или только считывания информации. После открытия файла в программу возвращается его идентификатор, который будет использоваться для указания на этот файл во всех процедурах обработки.
  2.  Начинается работа с файлом. Это могут быть запись, считывание, поиск и другие операции.
  3.  Файл закрывается. Теперь он опять доступен другим приложениям без ограничений. Закрытие файла гарантирует, что все внесённые изменения будут сохранены, так как для увеличения скорости работы изменения предварительно сохраняются в специальных буферах операционной системы.

В Delphi реализовано несколько способов работы с файлами. Познакомимся со классическим способом, связанным с использованием файловых переменных.

Файл задается с помощью зарезервированного слова file. Затем можно указать тип файла

var

 f1:file of char;

 f2:TextFile;

 f3:file;

Можно выделить три вида файлов:

  •  Типизированные файлы(задаются с помощью file of..)
  •  Текстовый файл(определяются типом TextFile)
  •  Не типизированные файлы(определяются типом File)
Доступ к файлам

Работа с файлами становится доступна программе после выполнения процедуры открытия файла. Эта процедура связывает файловую переменную с именем существующего или создаваемого файла, а также указание доступа к нему: чтение, запись или и чтение и запись.Файловая переменная связывается с именем файла с помощью процедуры AssignFile:

var 

  f : file;

begin

...

assignFile(f, 'newfile.txt');

...

end.

Первый параметр - файловая переменная, второй - название файла.Затем требуется инициализировать файл. Для этого существует три процедуры:

  •  Reset - эта процедура открывает для чтения уже созданный файл. Для нетипизированных файлов необходимо указывать длину записи.
  •  Rewrite - эта процедура открывает файл для записи. Если файла нет, то он создается, если есть, то он перезаписывается, уничтожая тем самым содержимое старого файла.  Для нетипизированных файлов необходимо указывать длину записи.
  •  Append - эта процедура только для текстовых файлов, она открывает текстовый файл и устанавливает указатель файла в конец, тем самым становится возможность сделать дозапись в старый файл.

После завершения работы с файлом его необходимо закрыть с помощью процедуры CloseFile.

var f1 : file;

begin

 assignFile(f1, 'newfile');

 rewrite(f1, 1); //f1 нетипизированный файл, мы должны указать длину 

                        // записи (обычно единица)

CloseFile(f1);

end.

Подпрограммы для работы с файлами

ФункцияОписаниеFunction EOF(var F):booleanВозвращает True если файловый указатель стоит в конце файла.Procedure Erase(var f)Уничтожает файл F. Перед уничтожением необходимо закрыть файл с помощью процедуры CloseFile.FileExists(const filename:string):booleanВозвращает True если файл с именем filename существует.procedure Flush(var f)Сохраняет изменения файла.procedure Rename(var f;NewName:string)Переименовывает файл F, FileName - новое имя. Перед выполнением процедуры необходимо закрыть файл с помощью процедуры CloseFile.function FileSize(var f):integer;Возвращает размер файла в байтах, если файл нетипизированный, или в количестве записей, если файл типизированный.

Запись и чтение типизированных файлов

Для чтения и записи типизированных файлов используются функции read и write. Для того, чтобы с помощью этих функциий работать с файлами, необходимо указать в качестве параметра файловую переменную:

var f : TextFile;

      s : string;

begin

  readln(s);                     //Ввод с клавиатуры в переменную s

  writeln(s);                   //Вывод на экран из переменной s

 assignFile(f, 'text.txt');//связываем файловую переменную f с конкретным файлом

 rewrite(f);                   //открываем файл на запись

 writeln(f, s);                //пишем в файл строку s

 closefile(f);                 //закрываем файл

end.

Функции writeln и readln следует использовать только для текстовых файлов. Для остальных нужно использовать read и write.

Запись и чтение нетипизированных файлов

Для чтения и записи нетипизированных файлов используется функция blockread и blockwrite. В качестве параметров нужно указать файловую переменную, буфер, и длину записи/чтения (она не должна превышать размеры буфера). В качестве буфера можно использовать массив, запись или переменную.

var f:file;

   a : array[1..10] of char;

begin

 assignfile(f, 'file.bin');

 reset(f, 1);

 blockread(f, a, sizeof(a)); //Функция sizeof возвращает размер параметра, 

                                          // в нашем случае 10 байт

end.

Мы не можем считать больше байт, чем размер файла, иначе будет вызвана исключительная ситуация и программа может аварийно завершиться. Поэтому следует контролировать чтение файла.

 8.3. Диалоги открытия и сохранения файлов

То, что мы рассмотрели выше, позволяет работать с файлами по адресу, жёстко записанному в тексте программы. Мы же хотим иметь возможность открывать любые файлы и работать с файлами по нашему выбору. Естественно, Delphi предоставляет нам такую возможность. Рассмотрим компоненты, позволяющие в работающей программе осуществлять выбор файлов. Delphi диалоги выбора файла позволяют указать програме, с каким файлом мы хотим работать.На вкладке палитры компонентов Dialogs находятся компонент Delphi OpenDialog и компонент Delphi SaveDialog. Все Delphi диалоги, находящиеся на этой вкладке, в том числе и Delphi диалоги выбора файла, невизуальные, т.е. при переносе их на Форму в работающей программе их не видно, они видны только на этапе конструирования. Компонент Delphi OpenDialog позволяет открыть в нашей программе стандартное Windows-окно диалога открытия файла, компонент Delphi SaveDialog - окно диалога сохранения.

Delphi диалоги выбора файла сами по себе ничего не делают, а только предоставляют настройки, сделанные пользователем при выборе файла. Самый важный метод Delphi диалогов - Execute. Он срабатывает в момент нажатия кнопки "открыть" или "сохранить" в окне выбора файла. Для примера давайте введём в программу возможность выбора файла для загрузки в редактор Memo, и сохранения после редактирования.Итак, помещаем на Форму оба Delphi диалога, текстовый редактор Memo, и три кнопки Button. В свойство Caption одной из них записываем "Открыть...", другой - "Сохранить", третьей - "Сохранить как..."

В обработчике OnClick кнопки "Открыть..." пишем:if OpenDialog1.Execute then                     Memo1.Lines.LoadFromFile(OpenDialog1.FileName);В результате выбора файла свойство FileName компонента OpenDialog получает значение полного адреса выбранного файла, который мы и вставляем в функцию загрузки файла компонента Memo.Всё это хорошо, но только в данном случае, когда записанное выражение записывается в одну строку. Если программа использует несколько раз выражение OpenDialog1.FileName, то писать руками устанешь. В Delphi для такого случая есть так называемый "оператор присоединения" with. Он используется для любых объектов, имеющих длинный "хвост" из свойств, которые приходится записывать многократно. Вот как он записывается:with Объект do beginend;Свойства Объекта внутри логических скобок begin/end можно записывать непосредственно. Допускается перечислять через запятую несколько объектов. Естественно, в случае, когда внутри скобок находится один оператор, они необязательны. Перепишем фрагмент загрузки файла с использованием оператора присоединения:with OpenDialog1, Memo1 do        if Execute then   Lines.LoadFromFile(FileName);Запись получается более компактной.Так как свойства компонентов OpenDialog и SaveDialog одинаковы, сохранение текста выглядит абсолютно аналогично. Создаём обработчик нажатия кнопки "Сохранить как..." и пишем:with SaveDialog1, Memo1 do   if Execute then begin        Lines.SaveToFile(FileName);        OpenDialog1.FileName:=FileName;   // Чтобы исправленный 

                                                                                                // текст не затёр источник                                                                   end;Наконец, для кнопки "Сохранить" пишем:Memo1.Lines.SaveToFile(OpenDialog1.FileName); // Сохраняем туда,   

                                                                                                            //откуда считалиПри работе этих фрагментов можно заметить, что выбирать приходится из всех файлов в нужной директории. Удобнее видеть только, например, текстовые файлы, или другой тип файлов по нашему выбору. Для этого используются фильтры, свойство Filter в наших компонентах. Настраивается оно в Инспекторе Объектов. При выборе его можно перейти в редактор фильтров:

В колонке FilterName записываем имена фильтров, в колонке Filter - список масок файлов, разделённых точкой с запятой. Маска файла в данном случае выглядит как* . расширение_файла ;Звёздочка означает, что выбираются файлы с любыми именами, подходящие по расширению.

Свойство Delphi диалогов Title позволяет записать в заголовок нужную нам фразу. Если оставить его пустым, то в заголовке будут стандартные "открыть" или "сохранить"Свойство InitialDir позволяет в момент открытия оказаться в нужной нам директории. Оно доступно как на этапе "конструирования", так и программно.

8.4. Пример написания программы

Задание: Записать в текстовой файл содержимое Мемо. Затем прочитать файл и все его строки, начинающиеся на букву "А", записать в другой текстовой файл. Далее прочитать новый файл и вывести его строки в RichEdit.

Интерфейс программы изображен на рис. 8.1, а программа - на листинге 8.1.

Рис. 8.1. Интерфейс программы

          Листинг 8.1

unit Unit1;

interface

uses

 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

 Dialogs, ComCtrls, ExtCtrls, StdCtrls, jpeg;

type

 TForm1 = class(TForm)

   Memo1: TMemo;

   Button1: TButton;

   Splitter1: TSplitter;

   RichEdit1: TRichEdit;

   Button2: TButton;

   Image1: TImage;

   Label1: TLabel;

   Label2: TLabel;

   procedure Button1Click(Sender: TObject);

   procedure Button2Click(Sender: TObject);

 private

   { Private declarations }

 public

   { Public declarations }

 end;

var

 Form1: TForm1;

implementation

{$R *.dfm}

//-----------------------------------------------------------

procedure TForm1.Button1Click(Sender: TObject);

//запись содержимого Мемо в файл

var

 f: TextFile;

 i: integer;

begin

 AssignFile(f, 'F.txt');

 Rewrite(f);

//записываем построчно содержимое Мемо1

 for i:=0 to Memo1.Lines.Count-1 do

      writeln(f, Memo1.Lines[i]);

 CloseFile(f);

 ShowMessage('Данные из Мемо записаны в файл "f.txt" ');

end;

//---------------------------------------------

procedure TForm1.Button2Click(Sender: TObject);

//читаем исходный файл и все строки, начинающиеся на "A" ,

// и записываем их в другой файл

var

 f,f1: TextFile;

 s,t: string;

begin

 AssignFile(f,'F.txt');

 Reset(f);               //открываем 1-й файл f для чтения

 AssignFile(f1,'F1.txt');

 Rewrite(f1);          // открываем 2-й файл f1 для записи

 while not Eof(f) do begin  //пока не достигли конца файла f ...

     ReadLn(f,s);

     if s[1] = 'А' then  WriteLn(f1,s);  //сравниваем с русской буквой "A"

 end;

 CloseFile(f);

 CloseFile(f1);

// открываем 2-й файл f1 для чтения (теперь в этом файле

//все строки начинаются на "A" )

 S := '';

 AssignFile(f1, 'F1.txt');

 reset(f1);

 while not Eof(f1) do begin //пока не достигли конца файла f1 ...

    ReadLn(f1, t);                   //читаем запись

    S := S + t + #13#10;         //добавляем запись в обобщенную строку S  

 End;

 CloseFile(f1);

 RichEdit1.Text := S; //выводим обобщенную строку S в RichEdit

end;

//-----------------------------------------

end.

8.5. Индивидуальные задания

           Таблица 8.1

ВариантЗадание1Даны два текстовых файла f и f1. Определить совпадают ли компоненты файла f с компонентами файла f1. Если нет, то получить номер первой строки и позицию первого символа в этой строке, в которых файлы f и f1 отличаются между собой. Обеспечить возможность вывода файлов.2Читается текстовой файл: а) определить, являются ли 2 первых символа файла цифрами? б) если да, то узнать, является ли число, образованное этими цифрами, четным?3Создайте два текстовых файла: первый содержит целые числа, второй - любые символы. Упорядочите символы второго файла по алфавиту.4Заполнить файл целыми числами из отрезка [-7000;7000] с помощью датчика случайных чисел. Переписать в один из новых файлов все четырехзначные положительные числа исходного файла, в другой - все двузначные.5Считать из заданного текстового файла f1 слова и записать в новый текстовый файл f2 только те из них, которые оканчиваются на заданную букву.6В заданном текстовом файле строки имеют разное количество слов, вывести строки, содержащие менее 5 слов.7Написать программу, которая запрашивает с клавиатуры строку текста и записывает ее в текстовый файл, имя которого запрашивается с клавиатуры.8Создать файл и заполнить его целыми числами (окончание ввода 0). Сформировать второй файл, в который записать квадраты элементов первого файла. Вывести на экран содержимое файлов с комментариями.9Дан файл, содержащий в каждой отдельной строке фамилию, предмет и оценку(на 1 фамилию - 1...n предметов), нужно вывести список студентов, имеющих оценки только 4 и 5 по всем предметам.10В текстовом файле получить длину каждой строки и записать её в типизированный файл.11В текстовом файле получить длину каждой строки и записать её в типизированный файл.12Создать файл компонентами которого являются целые числа, удалить последние 10 элементов файла.13Имеется текстовый файл. получить другой файл, в котором в конце каждой строки заданного файла добавлен восклицательный знак.14Создайте два типизированных файла одинакового размера, элементами которых являются отдельные буквы. Получить третий файл, каждый элемент которого представляет собой сочетание соответствующих букв первого и второго файлов.15Имеется текстовый файл. Переписать его строки в перевёрнутом виде в другой файл. Порядок строк во втором файле должен совпадать порядку строк в заданном файле.

Приложение 

Средства отладки программ в DELPHI

Практически в каждой вновь написанной программе после запуска обнаруживаются ошибки.

 Ошибки первого уровня (ошибки компиляции) связаны с неправильной записью операторов (орфографические, синтаксические). При обнаружении ошибки компилятор DELPHI останавливается напротив первого оператора, в котором обнаружена ошибка. В нижней части экрана появляется текстовое окно, содержащее сведения обо всех ошибках найденных в проекте. Каждая строка этого окна содержит имя файла, в котором найдена ошибка, номер строки с ошибкой и характер ошибки. Для быстрого перехода к интересующей ошибке необходимо дважды щелкнуть на строке с ее описанием. Для получения более полной информации о характере ошибки необходимо обратится к HELP нажатием клавиши F1. Следует обратить внимание на то, что одна ошибка может повлечь за собой другие, которые исчезнут при ее исправлении. Поэтому следует исправлять ошибки последовательно, сверху вниз и, после исправления каждой ошибки компилировать программу снова.

 Ошибки второго уровня (ошибки выполнения) связаны с ошибками выбранного алгоритма решения или с неправильной программной реализацией алгоритма. Эти ошибки проявляются в том, что результат расчета оказывается неверным либо происходит переполнение, деление на ноль и др. Поэтому перед использованием отлаженной программы ее надо протестировать, т.е. сделать просчеты при таких комбинациях исходных данных, для которых заранее известен результат. Если тестовые расчеты указывают на ошибку, то для ее поиска следует использовать встроенные средства отладки среды DELPHI.

 В простейшем случае для локализации места ошибки рекомендуется поступать следующим образом. В окне редактирования текста установить курсор в строке перед подозрительным участком и нажать клавишу F4 (выполнение до курсора) или щелкнуть на серой полосе слева от оператора для обозначения точки прерывания (появится красная точка) и нажать клавишу F9. Выполнение программы будет остановлено на указанной строке. Для просмотра текущих значений можно поместить на нужную переменную курсор (на экране будет высвечено ее значение), либо нажать Ctrl-F7 (окно оценки и модификации) или Ctrl-F5 (окно наблюдения) и в появившимся диалоговом окне указать интересующую переменную. Нажимая клавишу F7 (пошаговое выполнение), можно построчно выполнять программу, контролируя изменение тех или иных переменных и правильность вычислений. Если курсор находится внутри цикла, то после нажатия F4 расчет останавливается после одного выполнения тела цикла. Для продолжения расчетов следует нажать <Run> меню Run или F9.

 На практике, часто вместо вышеописанного отладочного режима, используют вызов окна с собщением ShowMessage('  '), где в кавычках ставится текст сообщения. Это может быть какой-либо простой текст, или текст со значениями программных переменных. Поскольку данное окно является модальным, то после его вывода работа программы приостанавливается до тех пор, пока окно не будет закрыто. Это позволяет в разных местах программы просмотреть как меняются значения тех, или иных переменных и проверить правильность работы программы.

ЛИТЕРАТУРА 

1. Бурцев А. А. Основы программирования на языке Object Pascal в среде DELPHI: Лаб. практикум по курсам «Программирование» и «Основы алгоритмизации и программирования» для студ. всех спец. заоч. формы обуч.: В 2 ч. Ч. 1. / А. А. Бурцев, А. А. Навроцкий, В. П. Шестакович. – Мн.: БГУИР, 2006. – 50 с.: ил.

2. Архангельский А.Я. Программирование в Delphi 7. – М.: ЗАО «Издательство БИНОМ», 2003.

← Предыдущая
Страница 1
Следующая →

Скачать

Programmir_na_Object_Pascal_lab_raboty_.doc

Programmir_na_Object_Pascal_lab_raboty_.doc
Размер: 13.8 Мб

Бесплатно Скачать

Пожаловаться на материал

Программирование линейных, разветвляющихся, циклических алгоритмов. Программирование с использованием массивов, с использованием подпрограмм и модулей. Построение графиков. Работа с файлами.

У нас самая большая информационная база в рунете, поэтому Вы всегда можете найти походите запросы

Искать ещё по теме...

Похожие материалы:

Электромагнитная индукция. Магнитный поток. Закон электромагнитной индукции. Правило Ленца

1. Опыты по электромагнитной индукции. 2. Магнитный поток. 3. Закон электромагнитной индукции. 4. Правило Ленца.

Детская эмоциональная психология

Детские эмоции - с точки зрения психологии. Спецпсихология, нарушение психики у детей, интелектуальное развитие

Бизнес-тренинг: как это делается

Представлена методология разработки и проведения блестящего тренинга, основная цель которого – стать эффективным инструментом развития бизнеса.

Дипломная работа Тема: Криминогенные качества личности и возможностииндивидуального предупреждения преступлений

Налоговая администрация: цели и задачи деятельности

Налоговое администрирование. Государственная (национальная) налоговая администрация. Налоговая администрация. Функционирование системы государственной налоговой администрации. Правоохранная деятельность

Сохранить?

Пропустить...

Введите код

Ok