Выпуск 09: Связь с внешним миром

 

Архив рассылки

Доброго времени суток!

Обмен ссылками :)

Ассемблер для начинающих. Для тех, кто хочет погрузиться в мир низкоуровненного программирования, где можно почувствовать себя богом! :) http://subscribe.ru/catalog/comp.soft.prog.asmnewbies

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

А теперь для всех. Многие пишут, что я объясняю довольно понятно. Я этому тоже рад :) Но не забывайте делать задачи, которые я вам даю, потому что они вам очень помогут усвоить тему и не только. При возникновении проблемы вы всегда можете спросить меня (по поводу программирования только!).

Я понял, что самый лучшый дизайн рассылки - самый простой, потому что:

1. Легче воспринимается информация
2. Легче читается
3. Меньше возни :)

В прошлом выпуске мы познакомились с языком Си. Само знакомство не было очень подробным, или даже понятным. Но не волнуйтесь! Это ради вас :) Вы легче всё поймёте, когда мы пройдём подпрограммы. А как изучают Си, которые вообще ничего не знают о программировании? Они просто запомянают, что просто так делать НАДО, или не надо :) А после некоторых уроков выясняют всё подробнее. На самом деле и мы так будем делать! :) Вы даже не представляете, как выглядит код, который создаёт окно OpenGL и подготавливает его к работе! Писать такой код довольно гиморно :) Но только после него начинается самое интересное! А если некоторые темы не пропускать (временно, конечно :), то выпуски этой рассылки будут чисто теоретическими. Думаю, вам этого не надо :) Конечно, я не оставлю вас в полном неизвестии. По этому для начала мы создадим обычное окно с помощью WinAPI функций (подпрограммы для работы с Windows). Проект мы уже начали, и скоро закончим :) А теперь, давайте вернёмся к подпрограммам.

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

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

Включите Дельфи. Работать будем не в консольном приложении. На форму поставьте компонент LabeledEdit (вкладка Additional), две метки и кнопку BitBtn (вкладка Additional). Для чего он нужен догадаться легко. Приведите программу в такой вид:

http://spider3d.narod.ru/img/09/01.gif

Чтобы изменить заголовок у LabeledEdit расскройте EditLabel в инспекторе объектов. Картинка у новой кнопки меняется в свойстве Kind.

Мы будем обрабатывать нажатие на кнопку. К проекту добавьте модуль Math. Думаю, вы догадались что будет делать эта программа :) Два раза щёлкните на кнопке, чтобы начать обработчик события OnClick. Мы ещё не будем здесь ничего писать :) Мы создадим две процедуры. Одна будет искать синус, а другая косинус. Сейчас наш код выглядит так:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
   LabeledEdit1: TLabeledEdit;
   Label1: TLabel;
   Label2: TLabel;
   BitBtn1: TBitBtn;
   procedure BitBtn1Click(Sender: TObject);
  private
   { Private declarations }
  public
   { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
begin

end;

end.

Перед событием OnClick (procedure TForm1.BitBtn1Click(Sender: TObject);) создайте процедуру. Назовите как хотите, но только латинскими буквами. В этой процедуре мы будем искать синус.

procedure Sinus();
begin

end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin

end;

end.

Как искать синус вы знаете. Я это говорил, когда объяснял что это такое модули :) Значение угла будет находится в компоненте LabeledEdit. Значит опять придётся превращать строку в число и наоборот. Многие из вас всё это могут зделать и сами, но другим я помогу. Сначала создайте две переменные дробного типа. Одной из них присвойте значение угла.

procedure Sinus();
var
  Alpha, Result: Real;
begin
 Alpha:= StrToFloat(Form1.LabeledEdit1.Text);
end;

Обратите внимание на то, как я обращаюсь к компоненту. Через его контэйнер! Т.е. форму. Это потому что наша функция сама по себе. Её содержит сам модуль (все файлы с расширением *.pas являются модулями), а не форма. Так предётся делать каждый раз. Не удобно? Ну, что поделать.... Итак, одно значение присвоенно. Другая переменная будет содержать результат, т.е. значение синуса. Останется только отобразить результат.

procedure Sinus();
var
  Alpha, Result: Real;
begin
 Alpha:= StrToFloat(Form1.LabeledEdit1.Text);
 Result:= Sin(Alpha);
 Form1.Label1.Caption:= 'Синус: ' + FloatToStr(Result);
end;

С синусом закончили. Остался косинус. Теперь зделайте сами. Чтобы найти косинус, надо воспользоваться функцией cos(). После того, как справитесь с косинусом, не забудьте, что эти две функции надо вызвать! У меня конечный результат получился таким (только не копируйте код! зделайте всё сами, а то потом не сможете зделать даже простых задач!):

procedure Sinus();
var
  Alpha, Result: Real;
begin
 Alpha:= StrToFloat(Form1.LabeledEdit1.Text);
 Result:= Sin(Alpha);
 Form1.Label1.Caption:= 'Синус: ' + FloatToStr(Result);
end;

procedure Cosinus();
var
  Alpha, Result: Real;
begin
 Alpha:= StrToFloat(Form1.LabeledEdit1.Text);
 Result:= Cos(Alpha);
 Form1.Label2.Caption:= 'Косинус: ' + FloatToStr(Result);
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
 Sinus();
 Cosinus();
end;

Я зделал одну ошибку. Не правильно назвал компонент LabeledEdit. На самом деле эти функции используют значения в радианах! Но программа работает! Можете проверить :)

Использование радианов не очень удобная вещь :) По крайней мере я их не признаю :) Это заставило меня покопаться в модуле Math. Я там нашёл функцию, которая конвертирует градусы в радианы. Но вам я её не скажу! :) Вы сами создадите эти функции, но чуть-чуть попозже, потому что ещё не знаете как это зделать. А пока придётся поработать с радианами :)

Программа работает? Должна... Надеюсь вы поняли, как действуют процедуры. Если этих примеров не хватило и у вас появились вопросы, пожалуйста обращайтесь ко мне. Итак, продолжаем.

Функции

Функции чуть-чуть по сложнее процедур, но у них и больше возможностей. Чем они отличаются? Есть только одно различие. Функция возвращает значение! Обратите внимание на то, как я присваивал переменной Result новое значение. Я ей присвоил функцию! На самом деле я присвоил значение, которое возвращает данная функция после проведения нужных действий. Т.е. функция сначала делала разные действия с каким-то значением радиана, а потом вернула конечный результат, который был присвоен к переменной Result. Вы всё легче поймёте после практики :)

Создадим функцию, которая что-то делает :) Чтобы она могла делать...... Хммм....... А! Придумал. Пусть она ввозводит цифру в 3 степень. Легко и понятно. Начнём с объявления функции:

function Power();
begin

end;

Функция начинается с ключевого (зарезервированного, хоть первый вариант более правильный :) слова Function. Дальше всё, как и у процедуры. Всё, да не совсем! На самом деле такая функция не только бесполезная, но она ещё и не будет работать! Я говорил, что функция возвращает значение. Но какое? Наверняка где-то надо определить тип этого значения. А определяется он в начале. Вам будет легче запомнить так (легче запомнить, но не путайте!): функция - это переменная, только вместо слова var пишется function. Теперь догадались чего тут не хватает? Вот именно....

function Power(): Integer;
begin

end;

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

А как указать возвращаемое значение? Надо ли это вообще делать? НАДО! Обязательно! И не забывайте этого! Хотя вы этого и не видите, но каждая функция автоматически создаёт переменную, в которой хранится возвращаемое значение. Тип этой переменной мы указали в самом начале. После исполнения некоторых действий функция эту переменную, т.е. её значение передаёт во внешний мир, т.е. подпрограмме, которая вызвала эту функцию. Переменная называется Result. Собственно, можно начинать программировать результат :)

function Power(): Integer;
begin
 Result:= 2*2*2;
end;

Вызовите эту функцию:

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
 ShowMessage(IntToStr(Power));
end;

Запустите программу и нажмите на кнопку. Ответ должен быть 8. Работает? Поскольку функция возвращает значение, с ней можно делать всё, что и с другими значениями, по этому её тоже надо превращать в строку. Превращается то не функция, а результат, который хранится в переменной Result. Эта переменная служит только для одного - для хранения возвращаемого значения. Что это значит? А то, что вы не можете ни в одной функцие создать такой переменной. Но можете в процедурах! Тем не менее в процедурах она будет служить, как самая обычная переменная.

Наша функция не очень удобна. Если понадобится найти степень другого числа, то вам предётся изменять три значения! Можно её усовершенствовать:

function Power(): Integer;
var
  Digit: Integer;
begin
 Digit:= 3;
 Result:= Digit*Digit*Digit;
end;

Конечно, можете придумать переменную с названием по короче :) Но это сейчас не важно. Запустите программу. Работает? На этот раз результат должен быть 27, потому что 3*3=9, а 9*3=27 :) Второй класс :) Но функция всё ещё не удобная. Значение переменной надо менять в коде. Значит функция должна брать начальное значение из внешнего мира. Должна, но руки коротки :) Нужен удлинитель :) А где его взять? Не пролема! Вы не чайники! Вы уже ПРОГРАММИСТЫ! А программист и сам может всё зделать. Ему не надо обращатся к маме за помощью! :) Но иногда надо к учителю... :)

Жирные подпрограммы :)

Помните, я назвал наши процедуры пустыми! Эта функция тоже такая же, т.е. пустая. Я точно не знаю, говорится ли так - "пустая", но по моему это слово здесь подходит :) Конечно, подпрограмму жирной называть точно нельзя :) Это я так..... для разнообразия так сказать :)

Пора связать функцию с внешним миром. Работать я буду с функцией, но у процедур всё тоже самое. Когдато в ранних выпусках я вам говорил, что значение, которое вы вводите в скобки функции называется аргументом. В математике точно так же. Эти значения где то хранятся. А где все значения хранятся вы уже знаете. В переменных! Делаем выводы. Нам надо в скобках создать переменную для хранения этого значения. Эта переменная (или несколько) называется параметром. Давайте создадим "нормальную" функцию из прежней:

function Power(Digit: Integer): Integer;
begin
 Result:= Digit*Digit*Digit;
end;

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

Функция готова. Но теперь, чтобы её вызвать надо указать аргумент в скобках. Это очень удобно, потому что аргумент может вводить пользователь.

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
 ShowMessage(IntToStr(Power(StrToInt(LabeledEdit1.Text))));
end;

Осторожно! Куча скобок! Не запутайтесь :) Можете запустить программу. Введите в поле ввода любое значение (но не слишьком большое). Не забывайте, что значение переменной ограниченно!

С процедурами всё также. Надеюсь вы поняли, что я вам объяснял. Если что-то не так, спрашивайте! :)

Выпуск ещё не закончен! Я помню, что вам оставил задание! :) Не увернётесь :) Итак, Задание #7: напишите функцию, которая превращает градусы в радианы и используйте это в нашей не законченной программе. Превращается так: "Градусы * (Пи / 180)".

В следущем выпуске мы уже в серьёз займёмся языком Си, так что "дельфяне" могут не спешить :) Хорошо выучите эту тему, потому что она встречается в каждой программе. На сегодня хватит. Удачи :)
 

2005-10-18

Spider3D http://spider3d.narod.ru

Евгений Нарышкин Spider3D@yandex.ru

Хостинг от uCoz