Урок Delphi 9

Создание собственных процедур и функций Delphi




Уроки Delphi
  1.  Первая программа
  2.  Использование компонентов
  3.  События Delphi
  4.  Типы данных Delphi
  5.  Создание своих типов данных
  6.  Выражения и операторы
  7.  Работа с файлами в Delphi
  8.  Дополнительные формы
  9.  Подпрограммы в Delphi
  10. Исключительные ситуации
  11. Взаимодействие приложения с пользователем
  12. Указатели в Delphi
  13. Обзор компонентов
  14. Работа со строками
  15. Создание интерфейса
  16. Графика в Delphi
  17. Многопоточность в Delphi
  18. Динамическое создание
        компонентов
Поиск по сайту




 Это важно:
   Метод Application.ProcessMessages;

 Это полезно:
   Параметр Sender в обработчиках событий;










Бояться не надо



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

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

   И процедуры, и функции позволяют добиться одинаковых результатов. Но разница всё же есть.

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

   Функция Delphi также позволяет выполнить всё перечисленное, но дополнительно возвращает результат в присвоенном ей самой значении. То есть вызов функции может присутствовать в выражении справа от оператора присваивания. Таким образом, функция - более универсальный объект!

   Описание подпрограммы состоит из ключевого слова procedure или function, за которым следует имя подпрограммы со списком параметров, заключённых в скобки. В случае функции далее ставится двоеточие и указывается тип возвращаемого значения. Обычная точка с запятой далее - обязательна! Сам код подпрограммы заключается в "логические скобки" begin/end. Для функции необходимо в коде присвоить переменной с именем функции или специальной зарезервированной переменной Result (предпочтительно) возвращаемое функцией значение. Примеры:

   procedure Имя_процедуры(параметры);
   begin
    Код процедуры;
   end;



   function Имя_функции(параметры): тип_результата;
   begin
    Код функции;
    Result:=результат;
   end;

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

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

   Теперь нужно ввести понятие локальных данных. Это данные - переменные, константы, подпрограммы, которые используются и существуют только в момент вызова данной подпрограммы. Они так же должны быть описаны в этой подпрограмме. Место их описания - между заголовком и началом логического блока - ключевым словом begin. Имена локальных данных могут совпадать с именами глобальных. В этом случае используется локальная переменная, причём её изменение не скажется на глобальной с тем же именем.
   Совершенно аналогично локальным типам, переменным, константам могут быть введены и локальные процедуры и функции, которые могут быть описаны и использованы только внутри данной подпрограммы.

   Теперь пример. Напишем программу суммирования двух чисел. Она будет состоять из Формы, на которой будет кнопка (компонент Button), по нажатию на которую будет выполняться наша подпрограмма, и двух строк ввода (компоненты Edit), куда будем вводить операнды. Начнём с процедуры.

var
  Form1: TForm1;
  A, B, Summa: Integer;
  procedure Sum(A, B: Integer);

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 A:=StrToInt(Edit1.Text);
 B:=StrToInt(Edit2.Text);
 Sum(A, B);
 Caption:=IntToStr(Summa);
end;

procedure Sum(A, B: Integer);
begin
 Summa:=A+B;
end;
Программа суммирования двух чисел
   Наша процедура находится после обработчика нажатия кнопки, где осуществляется её вызов. И программа работает именно потому, что заголовок процедуры вынесен в блок описания данных. Но всё же операция суммирования в данном случае производится как-то невнятно.
   Теперь сделаем то же самое с помощью функции.

var
  Form1: TForm1;
  A, B, Summa: Integer;
  function Sum(A, B: Integer): Integer;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 A:=StrToInt(Edit1.Text);
 B:=StrToInt(Edit2.Text);
 Summa:=Sum(A, B);        // На мой взгляд, сейчас более понятно, откуда что берётся
 Caption:=IntToStr(Summa);
end;

function Sum(A, B: Integer): Integer;
begin
 Result:=A+B;
end;

   Есть особенности в использовании в качестве параметров больших по объёму структур данных, например, массивов, состоящих из нескольких тысяч (и больше) элементов. При передаче в подпрограмму данных большого объёма могут быть большие расходы ресурсов и времени системы. Поэтому используется передача не самих значений элементов (передача "по значению", как в предыдущих примерах), а ссылки на имя переменной или константы (передача "по имени"). Достигается это вставкой перед теми параметрами, которые мы хотим передать по имени, ключевого слова var.

function Sum(A, B: Integer; var Arr: array[1..1000000] of Integer): Integer;

   Если взглянуть на описание нашей подпрограммы и описание обработчика нажатия кнопки (это тоже подпрограмма!), который был создан Delphi, то видим, что перед именем обработчика (Button1Click) стоит TForm1. Как мы знаем, в Delphi точкой разделяется объект и его атрибуты (свойства и методы). Таким образом, Delphi создаёт Button1Click как метод объекта Form1. Причём, буква T перед объектом говорит о том, что Button1Click не просто метод объекта, а метод класса объекта. Не будем этим пока заморачиваться, а просто будем поступать также. Описав свою процедуру или функцию как метод класса TForm1, мы получаем возможность использовать в ней объекты класса без указания его имени, что гораздо удобнее. То есть, если мы используем в нашей подпрограмме какие-либо компоненты, размещённые на Форме (например, Button1), то мы пишем

Button1.Width:=100;   //Ширина кнопки
   а не
Form1.Button1.Width:=100;

   Также появляется возможность использовать встроенные переменные, такие как параметр Sender. В каждом обработчике этот объект указывает на источник, то есть тот объект, который вызывает данную подпрограмму. Например, в нашей процедуре суммирования Sender = Button1. Проанализировав эту переменную, можно принять решение о тех или иных действиях.

   Описав подпрограмму как метод класса, её описание мы должны поместить туда же, куда их помещает Delphi - в описание класса TForm1. Смотрите сами, где находится описание процедуры Button1Click. Для этого, поставив курсор внутрь подпрограммы Button1Click, нажмите CTRL+Shift и кнопку управления курсором "Вверх" или "Вниз" одновременно. Произойдёт переход к описанию подпрограммы (чтобы вернуться обратно, повторите это действие ещё раз). Ставьте описание своей подпрограммы рядом, с новой строки. Обратите внимание, что TForm1 уже не пишется.

   Рекурсия - важное и мощное свойство процедур и функций в Delphi. Рекурсия это возможность подпрограммы в процессе работы обращаться к самой себе. Без использования рекурсии приходилось бы применять циклы, а это усложняет чтение программы. Рекурсивный вызов подпрограммы сразу проясняет смысл происходящего. Естественно, приходится следить за тем, чтобы в подпрограмме обязательно было условие, при выполнении которого дальнейшая рекурсия прекращается, иначе подпрограмма зациклится.

Пример. Вычисление факториала
   Вычисление факториала - классическая в программировании задача на использование рекурсии. Факториал числа N - результат перемножения всех чисел от 1 до N (обозначается N!):

N! = 1*2* ... *(N-1)*N = N*(N-1)!

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

   Удобство применения рекурсии особенно наглядно при вычислении дискриминанта матрицы. Дискриминант матрицы можно подсчитать методом Гаусса - приведением матрицы к треугольному виду, что требует использования нескольких вложенных циклов. Алгоритм получается достаточно громоздкий. Используя вместо этого рекурсию, получается очень элегантный алгоритм: вычисление дискриминанта матрицы с использованием рекурсии.


Работа с дополнительными формами           В начало урока          Исключительные ситуации в Delphi  

Уроки Delphi начинающим



Вопросы и комментарии (133)      Решение задач в Delphi

Одиссей, добавлено 1.05.10, 11:14:14 
Факториал большого числа с помощью такой программы не вычислишь!
Автор, добавлено 1.05.10, 11:15:04 
Да, но это всего лишь пример на использование функций и рекурсии.

XGJames, добавлено 26.08.10, 10:55:41 
Отличный блог, мне очень понравился! Жду новых статей
Админам респект!
Avers, добавлено 29.08.10, 09:00:28 
Я вот что хочу спросить как это применимо в жизни а тож писать легко, делать сложно
Автор, добавлено 29.08.10, 09:17:01 
Что делать сложно? Вот когда Вы реально попробуете написать программу, в которой одна и та же последовательность действий понадобится в разных местах и с разными переменными, Вам покажется наоборот, проще функцию написать, чем переписывать одно и то же по многу раз. Да и - глаза страшат, а руки делают. Достаточно один раз попробовать, и всё покажется не так страшно. Посмотрите сами - вся программа на Delphi только из подпрограмм и состоит.
Александр, добавлено 28.12.10, 13:38:04
Здравствуйте, имеется такой код:

sl:= TStringList.Create; k:=1; n:=10;
sl.Sorted:=true; sl.Duplicates:=dupError;
for j:=1 to n do
begin
flag:=false;
try
sl.Add(IntToStr(delta(j));
//delta(j)-это функция, возвращающая
//целочисленные значения
except on EStringListError do begin
flag:=true; k:=k+1; //k – счетчик повторов
end;
end;
if flag=True then Continue else
begin
k:=1;
...//выполняем определенные действия
//над значениями delta(j) и их
//количеством
end
end

Например, по ходу цикла значения delta(j) равны 1500, 1500, 1500, 2800, 2800, 380, 1250 и т.д. В первом шаге цикла повтора нет, соответственно, выполняется код, но в нем присутствует неправильное количество значений delta(j), а именно k=1. Истинное значение повторов появляется только на третьем шаге цикла. Вопрос вот в чем: как можно отловить последнюю ошибку, чтобы количество k было истинным?
Заранее спасибо за помощь.

Автор, добавлено 28.12.10, 14:06:29 
То есть, вам нужно произвести определённые действия над значениями и количеством их повторов функции delta.

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

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

Ну и вот, сначала проходим циклом по j, вычисляем функцию delta и подсчитываем количество её повторов. А затем уже выполняем нужные действия... По-моему, такую программу написать несложно, пока воздержусь, если не получится - пишите! )))
серый, добавлено 21.03.11, 19:20:17
А как с помощью рекурсии найти сумму элементов массива ?
Автор, добавлено 24.03.11, 06:37:10 
Щас чё-нить придумаем :)))!
Короче, обозначаем сумму функцией от количества элементов в массиве. Соответственно, если количество элементов равно 1, то функция равна первому элементу - условие прекращения рекурсии. Ну и всё:

var ar: array[1..10] of Real;// Глобальная переменная

function Sum(i: Integer): Real;// Ну или Integer - тип массива
begin
if i=1 then Result=ar[1]
  else Result=ar[i]+Sum(i-1);
end;


Вызов функции Caption:=FloatToStr(Sum(10)); Следующий вопрос препода: а если номер первого элемента не 1? )))
Доброжелатель добавлено 27.06.11, 20:37:38 
Бесплатный совет: заведи у себя в блоге рубрику типа "самые горячие обсуждения" или что-то в этом роде. Там можно будет комментировать самые обсуждаемые темы блога…
Автор добавлено 27.06.11, 21:55:38
Сейчас идёт некоторая переделка, в ходе которой, такая рубрика может появиться, спасибо за совет.
елена, добавлено 17.08.11, 00:26:18 
а если помимо нахождения факториала числа необходимо делить полученное значение на n^n, то можно 2 дела объеденить вместе? если да, то как?
Автор, добавлено 17.08.11, 07:17:53 
Ну что же, после некоторых высоконаучных изысканий было найдено решение! Нужно в функцию нахождения факториала добавить функцию возведения в степень! То есть умножать каждый раз число само на себя. Однако, остановиться нужно на шаг раньше (то есть, при первой итерации ещё число перемножать не нужно - это же первая степень. Но первую итерацию оказалось сложнее отловить, чем последнюю, где N=1). И в конце вычисления поделить факториал на степерь. Дополнительно нужно добавить ещё одну глобальную переменную NN, где будет храниться результат возведения в степень.

Однако, получается, что вначале нужно находить значения очень больших чисел, а затем эти числа делить друг на друга. Поэтому лучше находить результат последовательно, вычисляя очередное произведение в факториале (или очередную рекурсию, но вариант с рекурсией дольше по времени) и тут же деля его на n. Тем самым, мы можем вычислить значение для гораздо больших чисел (около 11000), тогда как самое большое целое число в Delphi (это тип Int64) не может содержать значение факториала числа 20 (20!), не говоря уже про n^n - это гораздо бОльшее число.

При этом заметим, что n!/n^n=(n-1)!/n^(n-1). Это сократит количество операций для получения окончательного значения.
интерес, добавлено 27.08.11, 10:38:24 
function SumGrid(i,j,z:Integer; var massive:array[2..7] of Integer):Integer;

выдает ошибку: 'OF' expected but '[' found. И что это значит?
Автор, добавлено 27.08.11, 11:05:14 
Это означает, что компилятор не позволяет в данном случае указывать границы массива. И вообще, вы передаёте ссылку (используя параметр var) на переменную некоего типа. Опишите этот тип в основной программе, и ссылайтесь на него:

type
  M = array[2..7] of Integer;

function SumGrid(i,j,z:Integer; var massive: M):Integer;

Сергей, добавлено 5.09.11, 23:27:26 
Здравствуйте, уважаемый Автор, у меня возникла следующая ситуация: я пишу программу для перемножения матриц, при этом задаю значения элементов матрицы при помощи функции Random.Самое интересное начинается, когда я эти данные пытаюсь перенести на форму в элементы StringGrid - выдается сообщение об ошибке:
"Access violation at adress 0045D686 in module "Project2.exe".Read of adress 00000004"
Исходный код таков:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
  StringGrid1: TStringGrid;
  StringGrid2: TStringGrid;
  StringGrid3: TStringGrid;
  Button1: TButton;
  Button2: TButton;
  Button3: TButton;
  Label1: TLabel;
  Label2: TLabel;
  Label3: TLabel;
  Button4: TButton;
  procedure Button4Click(Sender: TObject);
  private
  { Private declarations }
  public
  { Public declarations }
  end;



  type t2DynA = array of array of Integer;

  const n=3;
var

  StringGrid1: TStringGrid;
  Form1: TForm1;
  A,B,C: t2DynA;
  f,g:integer;
implementation

{$R *.dfm}


 procedure setMatrixRandom(M:t2DynA);// генерирование значений матрицы
  var i,j:integer; // как случайных целых чисел
  begin
  setlength(M,n);
  for i:=1 to n do
  begin
  setlength(M[i-1],n);
  end;
  for i:=0 to (n-1)
  do for j:=0 to (n-1)
  do
  begin
  M[i,j]:=1+random(10);
  end;
  end;

procedure TForm1.Button4Click(Sender: TObject);
var k,i,j:integer;
  s:string;
begin

  setmatrixRandom(A);
  k:=A[1,1];
  s:=IntToStr(k);
  stringGrid1.cells[0,0]:=s;

end;

begin

end.


И собственно после нажатия на Button4 и происходит ошибка(все ухищрения с переменными k и s
сделаны ради того, чтобы понять в каком именно месте программа сбоит)

Автор, добавлено 6.09.11, 07:23:49 
Перенёс ваш код к себе, ошибок нет. Но
1. зачем переменная StringGrid1? Уже есть компонент StringGrid1. Вот если бы он был динамически создаваемый - другое дело.
2. перед первым вызовом функции random нужно вызывать процедуру randomize для инициализации, иначе всё время будет выдаваться одна и та же последовательность псевдослучайных чисел, а значит о случайности и речи нет.

А с вашим вопросом, я думаю, нужно поступить так. У меня такие ошибки тоже бывают, когда программа выходит за отведённую ей память (что бы это ни значило, вот недавно была задача на длинные числа, даже больше чем тип Int64, и тоже было такое. Ну неважно.) Приходилось и Delphi перезапускать, и комп перегружать. Так или иначе, у вас ошибок нет, видимо глюк. Если справитесь, напишите как. А знаете что, попробуйте удалить exe-файл, а потом его создать заново командой Project - Build Project. Так, догадка, я не пробовал.
Сергей, добавлено 7.09.11, 18:25:37 
Огромное Спасибо за столь опреативынй ответ!А то я сомневался, думал, что что-то не так написано.
1.Удалил.
2.Странно, но на процедуру randomize у моего компилятора тоже какая-то аллергия))(выдаёт собщения об ошибке при её использовании)

Попробовал ваш способ, даже Delphi другую версию какую-то поставил всё равно не работает (
правда удалось выяснить, что ошибка происходит не во время задания матрицы, а непосредственно при её выведении в форму... в общем что делать не знаю, подумываю перейти на Delphi 2010, читал что она лучше с Windows 7 работает.

Автор, добавлено 7.09.11, 19:14:08 
Что это со мной??? Сразу не заметил. А с вами вот что. Вы вводите матрицу А для инициализации. То есть передаёте в процедуру некие данные, там они обрабатываются. А назад ничего не выводится. Если вы думаете, что А типа глобальная переменная, то напрасно. А-то глобальная, но тогда в процедуре к ней и нужно обращаться по имени А, а не как параметр передавать. А если вы её передаёте как параметр, то нужно передавать не её, а ссылку на неё, то есть передавать с ключевым словом var:

procedure setMatrixRandom(var M:t2DynA);

Сергей, добавлено 8.09.11, 16:07:38 
Огромное спасибо!!!Теперь всё работает!))

Олег, добавлено 11.10.11, 16:12:18 
Заполнить массив случайными двухзначными числами .вывести их на экран .Подчеркнуть четные значения среди четных номеров.помогите решить
Автор, добавлено 11.10.11, 17:17:37 
А что неясного? Или мне делать с нуля?
Олег, добавлено 11.10.11, 18:15:49 
Не ясно "Подчеркнуть четные значения среди четных номеров" ,массив вроде написал: код
Var a:array[1..100] of integer;
w,m,i,j: byte;
begin A:array[10,99];
randomize; form1.refresh; m:=strtoint(edit1.text); for i:=1 to 100 do begin
A[i]:=random(130)-99;
w:=trunc(i-1)/m);
canvas.textout(i-w*m)*35,(w-1)*35/inttostr(A[i]);end
но я могу ошибаться ,проверьте пожалуйста
Автор, добавлено 11.10.11, 19:54:09 
Еду в машине, на первый взгляд - какие-то непонятные вычисления. А где подчеркивание? Через час доеду, проверю.
Олег, добавлено 11.10.11, 19:58:18 
подчеркивание не понимаю как сделать ,а с массивом тоже проблемы есть.
Автор, добавлено 11.10.11, 22:26:54 
Ну давайте по порядку.

1. Заполнить массив случайными значениями. Создаём обработчик нажатия на кнопку "Создать массив". Там пишем:

randomize;
for i:=1 to 100 do
  A[i]:=random(100);

Массив готов. Но сначала его нужно описать как глобальный.

Далее вывод на экран. Странно, вы используете просто вывод на канву Формы. А, например, в таблицу типа StringGrid не удобнее было бы? А на Форме как расположить элементы массива - в строчку, в столбик? Короче, ерунда. Ну, пусть в столбик. Создаём обработчик кнопки "Вывод"

for i:=1 to 100 do
  begin
  Canvas.TextOut(10, 10+(i-1)*(Canvas.TextHeight('A')+10), IntToStr(A[i]));
  end;

Это мы вывели, но подчёркивания пока нет. Подчёркивать нужно только если элемент массива сам имеет чётный индекс. Как определить чётное число? Это если остаток от деления на 2 равен нулю:

if (i mod 2)=0 then

Итак, если индекс чётный, то в случае что и число чётное

if (A[i] mod 2)=0 then

то свойство шрифта канвы Формы нужно задать как "подчёткнутый":

Canvas.Font.Style:=Canvas.Font.Style+[fsUnderLine]

в противном случае - обычный:

Canvas.Font.Style:=Canvas.Font.Style-[fsUnderLine]

Условие нужно объединить в одно:

if (((i mod 2)=0)and((A[i] mod 2)=0))
  then ...
  else ...

Это нужно вставить перед выводом чисел. Но сто чисел в столбик на Форму не поместится.
Олег, добавлено 11.10.11, 22:45:42 
Попробую перенести на код в дельфи,посмотрим что получится А попробовать подчеркнуть через Pen можно?
код примерно так:
Canvas.Pen.color:clred;
canvas.rectangle(j-w*m)*35,(w+1)*35+60,(j-w*m)*35+30,(w+1)*35+63); Как считаете7
Автор, добавлено 12.10.11, 06:58:58 
Не, если работает, то делайте как вам больше нравится. Я лично бы не стал так делать. Выражение слишком длинное, я бы поленился. Да и что за цифры - кому показать (преподу например) - не поймёт. Вот разве что для этого - чтобы враг не понял!
АндрейШю, добавлено 16.10.11, 23:24:13 
Summa=Sum(A, B); // На мой взгляд, сейчас более понятно, откуда что берётся

В этой строчке у вас кажется пропущено двоеточие после Summa
Автор, добавлено 17.10.11, 03:53:55 
Да, спасибо. Исправлю.
ГВОЗДЬ, добавлено 17.10.11, 20:35:34 
procedure peremen(left1,left2,left3,left4:integer);
var i:integer;
randomize;
left1:=120;
left2:=240;
left3:=360;
left4:=480;
while i=1 do begin
checkbox1.left:=random(left1,left2,left3,left4);
checkbox2.left:=random(left1,left2,left3,left4);
checkbox3.left:=random(left1,left2,left3,left4);
checkbox4.left:=random(left1,left2,left3,left4);
затем идет сравнение чтоб друг на друга не наложились
then i=1
почему пишет ошибка?
 

Автор, добавлено 17.10.11, 20:57:48 
А что, у вас там, пишет - одна ошибка??? Там как бы вообще всё неправильно.

В процедуре операторы записываются внутри begin/end. У вас где оно?

Компоненты CheckBox будут неопознаны, т.к. они принадлежат Форме, а процедура о форме ничего не знает. Нужно либо процедуру описывать как Form1.peremen или компоненты с указанием Form1.

random(left1,left2,left3,left4) - это что такое??? Вы, когда скобку ставите после слова random, на подсказку хотя бы посмотрите.

Ну и i=1 - присвоение, сами ошибку заметите или...
ГВОЗДЬ, добавлено 17.10.11, 21:26:12 
Нужно либо процедуру описывать как Form1.peremen или компоненты с указанием Form1. как это сделать?
Автор, добавлено 17.10.11, 21:31:11 
Ну просто: Form1.peremen и процедуру добавить в описание класса Form1, или внутри процедуры ко всем компонентам нужно по полному имени обращаться Form1.CheckBox1

А ещё нужно прежде чем вопросы задавать, текст статьи прочесть - там всё описано.
ГВОЗДЬ, добавлено 17.10.11, 21:40:45 
Да пишу я так он все равно ругается на эту строчку я его ив вар и type ну никак не могу понять

Автор, добавлено 17.10.11, 21:43:02 
Просто приведите весь листинг - я посмотрю.
ГВОЗДЬ, добавлено 17.10.11, 21:47:31 
procedure Tform1.peremen(left1,left2,left3,left4:integer);
 begin
case checkbox of
1:left1:=120;
2:left2:=240;
3:left3:=360;
4:left4:=480;
end;
randomize;
{код присвоения и проверки ошибок в них нет, ошибка в первой строчке}
 end;
Автор, добавлено 17.10.11, 21:51:51 
Я имел в виде весь листинг, а не только процедуру. Ну хорошо. Возможно, вы не выполнили моё указание добавить процедуру peremen в описание класса Form1.
ГВОЗДЬ, добавлено 17.10.11, 21:52:26 
КАк это сделать покажите пример?

ГВОЗДЬ, добавлено 17.10.11, 21:53:12 
type
  TForm1 = class(TForm)
  CheckBox1: TCheckBox;
  CheckBox2: TCheckBox;
  CheckBox3: TCheckBox;
  CheckBox4: TCheckBox;
  Label1: TLabel;
  Button1: TButton;
  private
  { Private declarations }
  public
  { Public declarations }
  end;

var
  Form1: TForm1;
  left1,left2,left3,left4:integer;
  procedure Tform1.peremen(left1,left2,left3,left4:integer);

implementation

{$R *.dfm}
 procedure Tform1.peremen(left1,left2,left3,left4:integer);
 begin
case checkbox of
1:left1:=120;
2:left2:=240;
3:left3:=360;
4:left4:=480;
end;
randomize;
 end;
end.
Автор, добавлено 17.10.11, 22:03:46 
Ну а я про что? Где в описании класса Form1 упоминание peremen? У вас ещё программы есть? в которых есть обработчики событий, с кнопками, например? В этой программе не видно то, о чём написано в конце статьи - где размещаются описания процедур. Вот так должно быть:

type
  TForm1 = class(TForm)
  CheckBox1: TCheckBox;
  CheckBox2: TCheckBox;
  CheckBox3: TCheckBox;
  CheckBox4: TCheckBox;
  Label1: TLabel;
  Button1: TButton;
  procedure peremen(left1, left2, left3, left4 : Integer);
ГВОЗДЬ, добавлено 17.10.11, 22:07:31 
СПАСИБКИ))
Автор, добавлено 17.10.11, 22:18:26 
Пожалуйста.
ПЭВМ, добавлено 18.10.11, 17:07:01 
Здравствуйте, ни как не могу решить данную задачу: "Заполнить массив случайными вещественными числами.Отсортировать по возрастанию дробной части числа" К сожалению идей нет,может поможете?
Автор, добавлено 18.10.11, 17:31:09 
И в какой части заминка?

1. Создать массив
2. Заполнить случайными числами
3. Выделить дробную часть
4. Отсортировать

Я напишу как бы я делал, но для этого мне нужно знать количество знаков после запятой. Допустим, само число от 0 до 99, и два знака после запятой. Тогда массив конструируется так:

var A: Array[1..50] of Real;
  B: Array[1..50] of Integer;// массив для сохранения дробной части
 n, k: Integer;
begin
  randomize;
  for i:=1 to 50 do
  begin
  n:=random(100);
  k:=random(100);
  A[i]:=n+k/100;
  B[i]:=k;
  StringGrid1.Cells[i, 1]:=FloatToStr(A[i]);
  end;
end;

Всё, дальше сортировать. Хотя ваши преподы могут хотеть именно выделения дробной части из числа. Для этого есть процедура Delete(S, Index, Count), удаляющая из строки S Count лишних символов, начиная с Index. В вашем случае лишние это начиная с Count=1 и до позиции запятой, находимой функцией pos(DecimalSeparator, S).

Сейчас подумал, что для хранения элементов массива лучше использовать запись:

type
 TA = Record
  A: Real;
  B: Integer;
end;

var A: Array[1..50] of TA;

Всё остальное то же самое, только обращение к элементам будет такое:

A[i].A - число
A[i].B - дробная часть. Запись лучше использовать потому что при сортировке её можно переносить как единое целое.
ПЭВМ, добавлено 18.10.11, 20:52:46 
благодарю
ГВОЗДЬ, добавлено 18.10.11, 21:27:37 
вы удалили наши сообщения?
Автор, добавлено 18.10.11, 21:47:48 
Ну да. А вы не прочитали? Для вас повторю. У вас ошибка в том что ваш цикл

while i=1 do

никогда не начнётся, так как перед ним оператор

i:=0;
ГВОЗДЬ, добавлено 18.10.11, 21:51:08 
Все понел свою ошибку, извините=) большое спасибо
ГВОЗДЬ, добавлено 18.10.11, 22:00:25 
Суть проблемы осталась
Ка сделать так чтобы рандом брал числа из case of?
Автор, добавлено 19.10.11, 05:43:44 
в case of задавайте значения переменной, которую использует random. Так, наверное.
ГВОЗДЬ, добавлено 19.10.11, 15:12:56 
procedure Tform1.peremen(left1,left2,left3,left4:integer);
 var i,x,n:integer;
 left:array of integer;
 begin
  case checkbox1.left of
0:left1:=120;
1:left2:=240;
2:left3:=360;
3:left4:=480;
end;
 x:=0;
  for I:=0 to 3 do begin
  x:=x+1;
  left[i]:=120*x;
  end;
  n:=0;
 while n=0 do begin


  checkbox1.left:=random(left[i]);
  checkbox2.left:=random(left[i]);
  checkbox3.left:=random(left[i]);
  checkbox4.left:=random(left[i]);
  if (checkbox1.left<>checkbox2.left)and(checkbox3.Left<>checkbox4.left)and(checkbox1.Left<>checkbox4.Left)and(checkbox2.Left<>checkbox3.Left)and(checkbox1.Left<>checkbox3.Left) then I:=1;
  end;

 end;
я попробывал уже с массивом ни так ни сяк не получается подскажите как оформить
Автор, добавлено 19.10.11, 21:51:10 
возьмём фрагмент

 x:=0;
  for I:=0 to 3 do begin
  x:=x+1;
  left[i]:=120*x;
  end;

У вас переменные I и x отличаются на 1.Тогда x не нужен, не так ли?
Просто

for I:=0 to 3 do
  left[i]:=120*(I+1);

Далее - видим, что переменная I после цикла не определена. Что же вы тогда используете left[i], причём 4 раза? То, что после условного оператора всё же происходит присвоение I:=1 вас не оправдывает. Далее - цикл while n=0. Ранее он никогда бы не начался. Теперь он никогда не закончится - ведь n никогда не становится отличным от нуля. Ваша программа зависнет.

ГВОЗДЬ, добавлено 20.10.11, 17:16:21 
Я описался при наборе текста с тетради да там точно then n:=0;
меня больше интересует как определить i распишите пожалуйста

Автор, добавлено 20.10.11, 17:22:51 
Когда цикл for завершается, то переменная цикла больше не существует. Её конечно можно использовать, но значение в ячейке памяти компьютера, соответствующее этой переменной, может быть абсолютно любым - это значит, неопределённым. Как её определить - знаете только вы. Может, вы вообще другое имели в виду, когда набирали

checkbox1.left:=random(left[i]);// i - неопределено, цикл for уже завершён
checkbox2.left:=random(left[i]);
checkbox3.left:=random(left[i]);
checkbox4.left:=random(left[i]);

Может, надо

checkbox1.left:=random(left[1]);
checkbox2.left:=random(left[2]);
checkbox3.left:=random(left[3]);
checkbox4.left:=random(left[4]);

Или бог знает как...
ГВОЗДЬ, добавлено 20.10.11, 17:26:18 
мне нужно чтоб left у checkbox менялся рандомно из этого массива как это оформить?
Автор, добавлено 20.10.11, 17:35:32 
checkbox1.left:=left[random(3)];

Здесь random будет выдавать значения от 0 до 3. Сделайте соответствующие индексы у массива. Но у вас left[i] вообще не заданы, заданы left1, left2, а не left[i]
Александр, добавлено 1.11.11, 17:08:39 
А как сделать чтоб результат отображался в label?
Автор, добавлено 1.11.11, 17:24:53 
Label1.Caption:='Результат'; //Компонент Label
Кирилл, добавлено 1.11.11, 19:45:32 
Здравствуйте, автор,спасибо за ваши советы, многое понял,но все же остались проблемы: ввести строку состоящую из слов разделенных пробелами ,поменять заглавные буквы на строчные и строчные на заглавные ,заново вывести на экран.
1 есть идея:
выводить строку с помощью char но у меня не выходит вывод строки не могу понять как?
2 не пойму, как менять заглавные на прописные ?? спасибо за внимание
Автор, добавлено 1.11.11, 21:47:40
Итак, берём 4 строки, для русского и латинского алфавита (локальные константы):

const
  StrLat: String='a b c d e f g h i j k l m n o p q r s t u v w x y z';
  ZagLat: String='A B C D E F G H I J K L M N O P Q R S T U V W X Y Z';
  StrRus: String='а б в г д е ё ж з и к л м н о п р с т у ф х ц ч ш щ ъ ь ы э ю я';
  ZagRus: String='А Б В Г Д Е Ё Ж З И К Л М Н О П Р С Т У Ф Х Ц Ч Ш Ю Ъ Ь Ы Э Ю Я';

Ну и в обработчике OnClick кнопки вычисляем положение параметра Key в этих константах, и переопределяем на символ, находящийся на этом же месте в аналогичной , но другой раскладки константе:

if AnsiPos(Key, StrLat)<>0
  then Label1.Caption:=Label1.Caption+ZagLat[AnsiPos(Key, StrLat)]
  else Label1.Caption:=Label1.Caption+StrLat[AnsiPos(Key, ZagLat)];
if AnsiPos(Key, StrRus)<>0
  then Label1.Caption:=Label1.Caption+ZagRus[AnsiPos(Key, StrRus)]
  else Label1.Caption:=Label1.Caption+StrRus[AnsiPos(Key, ZagRus)];


Кирилл, добавлено 1.11.11, 22:43:32 
вот что получилось :

procedure TForm3.Button1Click(Sender: TObject);

  var s:String; i:integer; key:char;

const
  StrRus: String='а б в г д е ё ж з и к л м н о п р с т у ф х ц ч ш щ ъ ь ы э ю я';
  ZagRus: String='А Б В Г Д Е Ё Ж З И К Л М Н О П Р С Т У Ф Х Ц Ч Ш Ю Ъ Ь Ы Э Ю Я';
begin
  S:=Edit1.Text;
for i:=1 to Length(S) do
  begin
Key:=S[i];

if AnsiPos(Key, StrRus)<>0
  then Label1.Caption:=Label1.Caption+ZagRus[AnsiPos(Key, StrRus)]
  else Label1.Caption:=Label1.Caption+StrRus[AnsiPos(Key, ZagRus)];
  Label1.Caption:=S;
  end;
end;

Ничего не понимаю,замены не происходит ,странно все ведь правильно.
Автор, добавлено 1.11.11, 22:50:01

А вот скажите на милость, зачем вы написали Label1.Caption:=S; - это ведь стирает результаты всех трудов...
Кристишка, добавлено 6.11.11, 20:37:27 
Помогите пожалуйста. Мне нужно создать программу, где Edit1 - цена, Edit2 - кол-во, Button1 - вычислить, Edit3 - всего. Мне нужно, чтоб после нажатия кнопки в поле Edit3 мне выдавало произведение Edit1 и Edit2.
Заранее СПАСИБО.
Автор, добавлено 6.11.11, 21:22:23 
Кристишка! Это не программа, это один оператор. Создаём обработчик нажатия на кнопку и там пишем:

Edit3.Text:=IntToStr(StrToInt(Edit1.Text)*StrToInt(Edit2.Text));

Это если цена в целых единицах. А если предполагается с плавающей точкой, то StrToInt(Edit1.Text) заменить на StrToFloat(Edit1.Text) и первый IntToStr на FloatToStr.
Олег, добавлено 15.11.11, 20:18:00 
Здравствуйте автор,у меня есть несколько вопросов.
Определить корень функции ((x^2)/2)-3 методом деления отрезка пополам.Стартовый интервал ввести с клавиатуры. есть идея : где а и б границы поиска ,е-точность ,х-корень. код представил ,но он не работает ,вроде сделал правильно.
procedure TForm3.Button1Click(Sender: TObject);
var a,b,x1,x2,x,e:real;
begin
a:=edit1.text; b:=edit2.text; e:=edit3.text; x1:=a;x2:=b;
form3.refresh;randomize;
repeat x:=(x2-x1)/2;
if (((x*x)/2)-3)*((b*b)/2)-3>0 then x2:=x else x1:=x;
until ((x*x)/2)-3label4.Caption:=x;
end;

end.
Автор, добавлено 17.11.11, 13:17:18 
Морока эта математика :) Но в итоге вот что вышло.

function func(x: Real): Real;
begin
  Result:=x*x/2-3;
end;

function root(x1, x2: Real): Real;
begin
  Result:=x1+(x2-x1)/2;
end;

procedure TForm1.Button1Click(Sender: TObject);
var x, x1, x2, e: Real;
begin
  x1:=StrToFloat(Edit1.Text);
  x2:=StrToFloat(Edit2.Text);
  e:=StrToFloat(Edit3.Text);
  x:=root(x1, x2);

  while abs(x)>e do
  begin
  if func(x)*func(x1)<0
  then x2:=x
  else x1:=x;
  x:=root(x1, x2);
end;

Caption:=FloatToStr(root(x1, x2));
end;

У вас ошибка в том, что x2 (или x1) должно быть равно не x, а x1+x. То есть вы присваиваете не значение корня, а разницу между значениями двух границ - чувствуете разницу?
Аноним, добавлено 22.11.11, 19:19:11 
добрый вечер. Вывести на экран три строки случайных заглавных букв .размер строк 40. подчеркнуть цветом в каждой строке буквы ,вошедшие в другую строку ,но не вошедшие в третью. 1.Заполнение и вывод строк. 2.подчеркивание букв алгоритмом (вошедшие в другую строку ,но не вошедшие в третью). есть идея заполнять строку с помощью константы,а вот идеи с алгоритмом не могу придумать.
Автор, добавлено 22.11.11, 19:44:20 
Есть такая структура, называется множество. Есть оператор проверки нахождения элемента во множестве - in. Вот и составляется условие

if ((X[i] in A)and(not(X[i] in B)))

A и B - множества, состоящие из букв в первой и второй строках соответственно.
Аноним, добавлено 22.11.11, 19:50:50 
тогда нужно создавать счетчик и еще одну переменную которая будет сохранять результат от сравнивания 1 и 2 строки и этот результат сравнивать еще с 3ей?
Аноним, добавлено 22.11.11, 19:53:09 
и еще вопрос каким образом задать буквенное множество?с помощью констант?
Автор, добавлено 22.11.11, 19:59:32 
Вы про множество-то прочитайте.
Множество задавайте как set of Char.
Генерируете очередную букву в строках с которыми идёт сравнение и запихиваете её сразу во множество, A или B.
Вам нужно цикл по всем строкам, внутри цикл по длине строки. Тогда X - текущая строка, i - номер буквы в строке.
Запутался, строк всего три! Тогда простым перебором строк, и множества должно быть три, соответственно.

var A, B, C: set of Char; - переменные. Если сделать константы, то нужно сразу с элементами, потом не добавишь.

if ((X1[i] in B)and(not(X1[i] in C))) then {тут подчёркивание}

if ((X2[i] in A)and(not(X2[i] in C))) then {тут подчёркивание}

if ((X3[i] in A)and(not(X3[i] in B))) then {тут подчёркивание}

Аноним, добавлено 22.11.11, 20:16:52 
var
a:set of char;
b:set of char;
c:set of char;
x,i:integer;
Const d=['А','Б','В','Г','Д','Е','Ж','З','И','Й','К','Л','М','Н','О','П','Р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ъ','Ы','Ь','Э','Ю','Я'];
begin
a:=random(d); таким способом могу задать множество?
Автор, добавлено 22.11.11, 20:23:27 
Не, берётся строка без пробелов, состоящая из букв алфавита

А Б В Г Д Е Ж З И К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ы Ь Э Ю Я И - пробелы уберите, если нужна Ё - добавьте.

И тогда не random(d), а random(33)
Автор, добавлено 22.11.11, 20:25:29 
И это только один элемент. Нужен опять же цикл до n=40, а множество получается просто сложением текущего множества с очередным элементом (если про множество прочитать...)
Аноним, добавлено 22.11.11, 20:39:23 
Const d='АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЩЫЬЭЮЯ' ;
procedure TForm3.Button1Click(Sender: TObject);
var
A,B,C:set of char; i,n,x1,x2,x3:integer;
begin
A:=random(33);
B:=random(33);
C:=random(33);
 if ((X1[i] in B)and(not(X1[i] in C))) then Canvas.Font.Style:=Canvas.Font.Style+[fsUnderLine] ;

if ((X2[i] in A)and(not(X2[i] in C))) then Canvas.Font.Style:=Canvas.Font.Style+[fsUnderLine];

if ((X3[i] in A)and(not(X3[i] in B))) then Canvas.Font.Style:=Canvas.Font.Style+[fsUnderLine] ;

end;

end.

ну пока вот что выходит,константу вынес и присвоил каждому множеству.
Автор, добавлено 22.11.11, 21:10:54 
X1 и так далее это не Integer, а ваши строки. Множество и строка создаются в одном цикле по количеству элементов:

X1:='';
A:=[];
for i:=1 to 40 do
  begin
    X:=d(random[31]+1);//вспомогательная переменная типа char
    X1:=X1+X;
    A:=A+X;
  end;

И только потом условие подчёркивания. И ваше подчёркивание будет работать для всего канваса, а не для одной буквы.
Аноним, добавлено 22.11.11, 21:20:54 
Const d='АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЩЫЬЭЮЯ' ;
procedure TForm3.Button1Click(Sender: TObject);
var
A,B,C:set of char; i,n:integer; x1,x2,x3:string; x:char;

begin
X1:='';
A:=[];
for i:=1 to 40 do
  begin
  X:=d(random[31]+1);
  X1:=X1+X;
  A:=A+X;
  end;
X1:='';
B:=[];
for i:=1 to 40 do
  begin
  X:=d(random[31]+1);
  X1:=X1+X;
  B:=B+X;
  end;
 X1:='';
C:=[];
for i:=1 to 40 do
  begin
  X:=d(random[31]+1);
  X1:=X1+X;
  C:=C+X;
  end;
 if ((X1[i] in B)and(not(X1[i] in C))) then Canvas.Font.Style:=Canvas.Font.Style+[fsUnderLine] ;

if ((X2[i] in A)and(not(X2[i] in C))) then Canvas.Font.Style:=Canvas.Font.Style+[fsUnderLine];

if ((X3[i] in A)and(not(X3[i] in B))) then Canvas.Font.Style:=Canvas.Font.Style+[fsUnderLine] ;

end;

end.
так тут разобрался,если правильно понял ,то нужно каждое множество задавать так,перенес на дельфи ,подчеркивает X:=d(random[31]+1);строку вот здесь не понимаю
Автор, добавлено 22.11.11, 22:07:55 
d - строка задающая алфавит
random[31] - случайный номер символа в строке, а плюс 1 потому что рандом выдаёт от нуля.

Аноним, добавлено 22.11.11, 22:13:20 
дельфи на нем спотыкается...
Автор, добавлено 22.11.11, 23:01:32 
Ну да, не квадратные скобки, а круглые.
Аноним, добавлено 22.11.11, 23:05:13 
нет я заменил скобки на противоположные...вылезают ошибки, и думаю их там много будет. Сможете проверить?
Автор, добавлено 22.11.11, 23:08:41 
Ну, разбирайтесь. Без этого никуда. Тиснете - посмотрю.
Аноним, добавлено 22.11.11, 23:27:37

procedure TForm3.Button1Click(Sender: TObject);
const d='АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЩЫЬЭЮЯ' ;
var A, B, C: set of char;
    i, n: integer;
    x1, x2, x3: string;
    x: char;
begin
X1:='';
A:=[];
for i:=1 to 40 do
  begin
  X:=d(random(31)+1);
  X1:=X1+X;
  A:=A+X;
  Canvas.TextOut(10, 10+(i-1)*(Canvas.TextHeight('A')+10), IntToStr(A[i]));
  end;
X1:='';
B:=[];
for i:=1 to 40 do
  begin
  X:=d(random(31)+1);
  X1:=X1+X;
  B:=B+X;
  Canvas.TextOut(10, 10+(i-1)*(Canvas.TextHeight('B')+10), IntToStr(B[i]));
  end;
 X1:='';
C:=[];
for i:=1 to 40 do
  begin
  X:=d(random(31)+1);
  X1:=X1+X;
  C:=C+X;
  Canvas.TextOut(10, 10+(i-1)*(Canvas.TextHeight('C')+10), IntToStr(C[i]));
  end;
 if ((X1[i] in B)and(not(X1[i] in C))) then Canvas.Font.Style:=Canvas.Font.Style+[fsUnderLine] ;

if ((X2[i] in A)and(not(X2[i] in C))) then Canvas.Font.Style:=Canvas.Font.Style+[fsUnderLine];

if ((X3[i] in A)and(not(X3[i] in B))) then Canvas.Font.Style:=Canvas.Font.Style+[fsUnderLine] ;
end;

Автор, добавлено 23.11.11, 10:16:48 
Кое-что я неправильно написал, прибавление элемента ко множеству не

A:=A+X;
а
A:=A+[X];

Ну а вы чего рисуете

IntToStr(A[i])?

Элемент множества (A - множество) не индексируется, его нельзя нарисовать. Всё, что можно сделать с элементом множества, это проверить, входит он во множество или нет, ну и добавить его туда или удалить. Поэтому нужно рисовать символ в строке X1[i].
И скобки нужно было в random истинно заменить на противоположные, а вы на одинаковые круглые.

Далее. Вот это

if ((X1[i] in B)and(not(X1[i] in C))) then Canvas.Font.Style:=Canvas.Font.Style+[fsUnderLine] ;

уже за циклом. Откуда там i? Сначала нужно составить множества и строки, а затем сделать цикл, выводящий их и подчёркивающий нужные буквы, Поэтому и

Canvas.TextOut(10, 10+(i-1)*(Canvas.TextHeight('C')+10), IntToStr(C[i]));

там не к месту. Да и я говорил уже, что

Canvas.Font.Style:=Canvas.Font.Style+[fsUnderLine] ;

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

К тому же вы перепутали Left и Top - у вас буквы в столбик! В общем, у меня всё заработало. Я вроде все ошибки разобрал, и у вас должно получиться. Не справитесь - опубликую (*обречённо покивав головой*) готовый текст. Да, и ещё. Строка алфавита вышла неполная, поищите сами, и поменяйте количество в цикле, а то выходят некоторые непечатаемые символы.
Аноним, добавлено 23.11.11, 21:11:58 
я справился,нащел и изменил все ошибки ,все работает.
Кирилл, добавлено 29.11.11, 19:44:18 
Здравствуйте автор ,помогите решить задачу: вычеркнуть самое короткое слово из строки при помощи процедур. 1.Задаю строку var i,n,l,min:byte; s:string;
begin s :=edit1.text;n:=length(s); l:=0 min:=1;for i:=1 to n do if s[i]<>' ' then l:=l+1 else begin if min>l then min:=l; l:=0; end edit2.text:=intostr(min); end
вот это минимальное слово нашел его ,а как это сделать с помощью процедур понятия не имею и как удалить этот элемент тоже.Надеюсь на вашу помощь.
Автор, добавлено 29.11.11, 20:05:28 
Что же у вас вся программа в одну строку! Читать невозможно.

Вы программу эту в Блокноте Windows писали? И как, работает? У вас Delphi вообще на компьютере установлена?
Без Delphi даже и помогать не буду - без толку.

Короче, запустите ваш код хотя бы без функций, как есть. Чтобы работал, а не как сейчас. Тогда и под функции переделаем.

А удалить слово из строки очень просто. На странице "Работа со строками" есть функция замены, меняете найденное слово на пустые кавычки ''.

Увидел ваше сообщение, пока корректировал текст - случайно стёр. Жду.
Кирилл, добавлено 29.11.11, 20:29:46 
procedure TForm3.Button1Click(Sender: TObject);
var i,n,l:byte; s:string; min:word;
begin
s:=edit1.text;
n:=length(s);
l:=0; min:=1;
for i := 1 to n do if s[i]<>' ' then
l:=l+1 else begin
if min >l then min:=l; l:=0 ;
edit2.text:=inttostr(min);
end;
 end;
end. так я запутался.как я понял по поиску наименьшего слова
: мы просматриваем весь текст, если нашли пробел, то началось новое слово, если ещё один пробел, то закончилось.и ищем их длину и сравниваем ведь так? а код бредовый получился
Кирилл, добавлено 29.11.11, 20:53:48 
procedure TForm3.Button1Click(Sender: TObject);
const n=[' ',',','.','!','?',#13,#10];
var str,s:string;
i,q,kol,b:integer;
begin
str:=edit1.Text;
s:='';q:=20;b:=0;kol:=0;
for i:=1 to length(str) do begin
if str[i]=edit2.Text then
inc(b);
if not (str[i] in n) then
s:=s+str[i] else begin
  if length(s)>0 then begin
  if (q>length(s))and(length(s)>1) then
  q:=length(s);
  inc(kol);
  s:='';
end;
end;
end;
label1.Caption:=inttostr(b); //количество букв в предложении, буква вводится в едит 2
label3.Caption:=inttostr(kol); //количество слов в предложении
label2.Caption:=inttostr(q)+' '+str; //кол-во букв в самом коротком слове и само слово

нашел старый код лабы
Аноним, добавлено 29.11.11, 21:35:19 
хм ничего не вышло.бред получается
Автор, добавлено 29.11.11, 21:37:43 
А у меня вот что получилось. Предложение вводится в первый эдит, с удалённым коротким словом выводится во второй.

procedure TForm1.Button1Click(Sender: TObject);
var i, n: Integer;
 S, wtemp, wresult: String;//wtemp - текущее найденное слово, wresult - текущее самое короткое слово
 Flags: TReplaceFlags;
begin
S:=Edit1.Text;
wresult:=S;
Flags:=Flags-[ rfReplaceAll]-[rfIgnoreCase];
while AnsiPos(' ', S)<>0 do
  begin
  wtemp:=copy(S, 1, AnsiPos(' ', S)-1);
  S:=StringReplace(S, wtemp+' ', '', Flags);
  if Length(wtemp) < Length(wresult)
  then wresult:=wtemp;
  end;
if Length(S) < Length(wresult)
then wresult:=S;
Edit2.Text:=StringReplace(Edit1.Text, wresult+' ', '', Flags);
end;

Кирилл, добавлено 29.11.11, 21:45:01 
if Length(wtemp) then wresult:=wtemp; а у вас не подчеркивает это строку? и еще вопрос как я понимаю это прямой код,а как выполнить при помощи процедур??
Автор, добавлено 29.11.11, 21:55:28 
То есть мы постепенно находим пробелы, копируем слово до пробела, а само слово из предложения удаляем. Найденное слово анализируем по длине, если короче предыдущего, запоминаем его как текущий результат. В остатке, когда пробелов больше нет, последнее слово. Анализируем его точно так же.

Этот код работает не совсем корректно. Если пробел между словами будет не один, то самое короткое слово будет именно он - один пробел. Можно вначале поудалять сдвоенные пробелы из строки, или ещё поработать над кодом.

Те ошибки, что вы показали, я уже успел скорректировать.
Кирилл, добавлено 29.11.11, 22:05:29 
так я понял ход вашей мысли ,но не понял где ошибка в этих строках
if Length(wtemp) then wresult:=wtemp;
  end;
if Length(S) then wresult:=S; а вот тогда я попробовал через процедуры

implementation
procedure stroka (a,b: integer;var и так далее...верно?
Кирилл, добавлено 29.11.11, 22:09:58 
извиняюсь с 1 вопросом разобрался.остался с последний с процедурой.
Автор, добавлено 29.11.11, 22:11:03 
Я скорректировал. Это не ошибка, это особенность html кода - он обрезал символ "меньше".
 Я вот сейчас пробую выделить в виде функции нахождение очередного слова.

Автор, добавлено 29.11.11, 22:20:58 
Я думаю, что функция - тоже процедура, даже ещё лучше. Так что у меня с помощью функции:

function world(var S: String): String;
var Flags: TReplaceFlags;
begin
  Flags:=Flags-[rfReplaceAll]-[rfIgnoreCase];
  Result:=copy(S, 1, AnsiPos(' ', S)-1);
  S:=trim(StringReplace(S, Result+' ', '', Flags));
end;

procedure TForm1.Button2Click(Sender: TObject);
var S, wtemp, wresult: String;
Flags: TReplaceFlags;
begin
Flags:=Flags-[rfReplaceAll]-[rfIgnoreCase];
S:=trim(Edit1.Text);
wresult:=S;
while AnsiPos(' ', S)<>0 do
  begin
  wtemp:=world(S);
  if Length(wtemp) < Length(wresult)
  then wresult:=wtemp;
  end;
if Length(S) < Length(wresult)
  then wresult:=S;
Edit2.Text:=StringReplace(Edit1.Text, wresult, '', Flags);
end;

И лишние пробелы здесь учитываются. А ещё что выделить в виде процедуры, даже и не придумаю...
Кирилл, добавлено 29.11.11, 22:39:02 
да спасибо, понял как сделать, по аналогии доделаю с максимальной длиной слова, но это уже сам. Еще раз спасибо.
Аноним, добавлено 30.11.11, 21:08:45 
Flags: TReplaceFlags; а скажите какие функции может выполнять эта команда, или у нее одна функция?
Автор, добавлено 30.11.11, 21:21:36 
Давайте разберёмся, Flags: TReplaceFlags; - где вы увидели команду. Это служебная переменная, использующаяся в функции StringReplace. Про функцию StringReplace почитайте на странице "Работа со строками".
Аноним, добавлено 6.12.11, 19:26:43 
прочитал Вашу работу с файлами.Спасибо.многое учёл для себя. Помогите решить задачу: ввести с клавиатуры произвольный латинский текст, записать его в файл, обеспечив автоматический забой буквы f символом номер 219. т.е. произвести замену.
Не могу понять каким способом это выполнять. Если не ошибаюсь №219 это символ "кирпич"
Аноним, добавлено 6.12.11, 20:09:23 
procedure TForm1.Button1Click(Sender: TObject);
var f: textfile; a: char;
begin
assignfile(f,'D:\\.dat');
rewrite(1);
a:strtofloat(edit1.Text); writeln(f,a);
end;

end.
дошел до этого момента.запись на файл текстовый файл.
Аноним, добавлено 6.12.11, 20:13:03 
точнее вот исправил ошибки
procedure TForm3.Button1Click(Sender: TObject);
var f:textfile; a:char;
begin
assignfile(f,'D:\lab1.dat');
rewrite(f);
a:=strtofloat(edit1.Text); writeln(f,a);
end;

end.
Автор, добавлено 7.12.11, 00:28:46 
Я в таких случаях пользуюсь всё же компонентом Memo, это проще и быстрее запрограммировать, чем файловые переменные. Можно же сделать его маленьким и невидимым, его функции сохранения от этого не страдают. Но не суть, можно и через переменные.

Вот автоматический забой, это значит, что вместо f сразу должен появляться этот "символ"? Или это должно быть сделано при записи в файл?

Если при вводе, то через Edit1KeyPress:

if Key='f' then Key:=Simbol219; //Заранее определить такую константу типа Char;

А если при сохранении, то воспользоваться функцией StringReplace, там есть опция замены всех вхождений (посмотрите на странице "Работа со строками"). Ну или в цикле проверить каждый символ и заменить на нужный - это не так красиво, но попроще:

S:=Edit1.Text;
for i:=1 to Length(S) do
if S[i]='f' then S[i]:=Simbol219;


А само сохранение через Memo:

Memo1.Text:=Edit1.Text;
Memo1.Lines.SaveToFile('Имя_Файла.txt');
женя, добавлено 13.12.11, 17:29:59 
помогите написать счетчик ходов в FPC-Lazarus Project!!
Автор, добавлено 13.12.11, 18:13:50 
Ни слова не понял. Лазарус не знаю...
женя, добавлено 13.12.11, 23:03:18 
Lazarus интегрированная среда разработки приложений в Delphi....можно просто в Delphi создоть счетчик ходов...с лазарусом я сам разберусь.
Автор, добавлено 14.12.11, 06:12:08 
Да я знаю, что такое Лазарус. А вот что такое счетчик ходов! Каких, куда... FPC - что это?
Максим, добавлено 17.12.11, 23:21:48 
2. Вычислить сумму m! + n!, используя процедуру для вычисления факториала.

Максим, добавлено 17.12.11, 23:22:24 
что не так?
unit Unit622;

interface

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

type
  TForm1 = class(TForm)
  Edit1: TEdit;
  Edit2: TEdit;
  Edit3: TEdit;
  Label1: TLabel;
  Label2: TLabel;
  Button1: TButton;
  Button2: TButton;
  procedure Button2Click(Sender: TObject);
  procedure Button1Click(Sender: TObject);
  private
  { Private declarations }
  public
  { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
begin
close;
end;

procedure F(m:integer;var Fact:integer);
var i:integer;
begin
Fact:=1;
for i:=1 to m do
if m=0 then Fact:=0 else
Fact:=Fact*i;

end;


procedure TForm1.Button1Click(Sender: TObject);
var m,n,z,Fact,Fact1:integer;
begin
m:=strtoint(edit1.Text);
n:=strtoint(edit2.Text);
F(m,Fact);
F(n,Fact1);
z:=Fact+Fact1;
edit3.Text:=inttostr(z);
end;

end.
Автор, добавлено 18.12.11, 00:12:28 
Факториал нуля - единица, а у вас - ноль.
Кирилл, добавлено 23.03.12, 07:35:31 
FUNCTION f1(a,b,c,x:INTEGER):INTEGER;
BEGIN
  f1:=a*sqr(x)+b*x+c;
END;
 
PROCEDURE TForm1.Button1Click(Sender: TObject);
VAR
I, J, C, B, S, F:INTEGER;
BEGIN
  FOR I:=1 TO 5 DO
  BEGIN
  S:=0;
  FOR J:=1 TO I DO
  S:=S+F1(1,1,0,J);
  C:=0;
  FOR J:=1 TO I DO
  C:=C+F1(0,2,3,J);
  F:=0;
  F:=3+S-C
  END;
END;


чему равно значение переменной F для каждого значения I?
Кирилл, добавлено 23.03.12, 07:37:29 
Помогите разобраться..
Автор, добавлено 23.03.12, 16:27:41 
У компа буду к 21 часу. Но сейчас вижу два присвоения подряд переменной F, ноль и следом выражение. Явно ошибка.
Альбина, добавлено 5.04.12, 23:37:30 
что то особо не понятно ...

Антон, добавлено 30.04.12, 21:17:38 
Здравствуйте. Пытаюсь решить такую задачу: Есть дата, записанная в виде строки (string). Нужно к этой дате прибавить 1 день (то есть заменить имеющуюся дату на следующую за ней). Написал вот такую процедуру
procedure uvdate(s : string);
var d, m, y : integer;
  d1, m1, s1 : string;
begin
s1:=s;
d:=StrToInt(copy(s, 0, pos('.', s)-1));
Delete(s, 0, pos('.', s));
m:=StrToInt(copy(s, 0, pos('.', s)-1));
Delete(s, 0, pos('.', s));
y:=StrToInt(s); //Идет разделение даты на число, месяц год
s:=s1;
case m of
1, 3, 5, 7, 8, 10: if d=31 then
  begin
  m:=m+1;//Если в месяце 31 день, то при переходе на следующий день число месяца увеличивается на 1
  d:=1;//А число снова превращается в первое
  end
  else d:=d+1;
4, 6, 9, 11: if d=30 then
  begin
  m:=m+1;
  d:=1;//То же самое для 30-дневных месяцев
  end
  else d:=d+1;
2: if d=30 then
  begin
  m:=m+1;
  d:=1;//И для февраля (Правда не учел високосный год, надо будет доделать)
  end
  else d:=d+1;
12: if d=31 then
  begin
  m:=1;
  d:=1;
  y:=y+1;//Переход на следующий год
  end
  else d:=d+1;
end; //Конец case
if d<10 then d1:='0'+IntToStr(d)
else d1:=IntToStr(d); //Перевод числа в строковый формат (если число однозначное добавляет спереди 0)
if m<10 then m1:='0'+IntToStr(m)
else m1:=IntToStr(m); //То же самое для месяца
s:=d1+'.'+m1+'.'+IntToStr(y);//Окончательная дата на 1 день больше предыдущей
end;

В описании класса TForm2 указал наличие данной прцедуры
procedure uvdate(s : string);
И как раз на последнюю запись он ругается следующими словами:
[Error] Unit2.pas(19): Unsatisfied forward or external declaration: 'TForm2.uvdate
В чем дело?
Автор, добавлено 30.04.12, 22:01:35 
Я думаю, что в этом или в других модулях у вас есть обработчики событий. Чем они хороши, так это тем, что их заголовки обычно создаются Delphi автоматически. Вот пример заголовка обработчика события OnCreate Формы:

procedure TForm1.FormCreate(Sender: TObject);
begin

end;

А теперь сравните с вашим:

procedure uvdate(s : string);

Не нужно обращать внимания на параметры. И та и другая процедуры описаны в типе Формы. Видите разницу?

В общем, добавьте TForm2 перед именем процедуры, о чём вас и просит Delphi:

procedure TForm2.uvdate(s : string);
begin
. . .
end;
Антон, добавлено 30.04.12, 22:18:47 
Странно, остальные процедуры прекрасно работают без этого. То есть при описании процедуры TForm2 есть, а в описании класса - нет.
Антон, добавлено 30.04.12, 22:21:56 
Пардон, не так вас понял, спасибо))
Антон, добавлено 30.04.12, 22:38:00 
Скажите, а в процедуре не находите никаких ошибок? Просто программа запустилась, но после начала обработки даты (при первом же применении процедуры) вылетает с ошибкой
'дата' is not a valid integer value
Автор, добавлено 30.04.12, 22:43:09 
Исходя из вопроса, я на реализацию и не смотрел...

А что вам непонятно? Где-то идёт преобразование, а вместо целого числа там текст "дата". Смотрите сами, не найдёте - пишите, посмотрю. Проще по шагам выполнить - сразу будет видно где.
Антон, добавлено 30.04.12, 22:47:35 
В том то и дело, что не нахожу. Единственное, что вызывает подозрение это
d:=StrToInt(copy(s, 0, pos('.', s)-1));
Delete(s, 0, pos('.', s));
m:=StrToInt(copy(s, 0, pos('.', s)-1));
Delete(s, 0, pos('.', s));
y:=StrToInt(s); //Идет разделение даты на число, месяц год
Может я неправильно понимаю принцип работы процедуры Delete? Я так понял она заманяет строку s на новую, с уже отсутствующей подстрокой.
Автор, добавлено 30.04.12, 22:54:37 
Нет, дело как раз в функции StrToInt. Она не видит целого числа. Там в это время слово "дата". Боюсь, что если я буду проверять, не найду. Это именно у вас в программе где-то так написано.
Антон, добавлено 30.04.12, 22:58:40 
Ругается на процедуру uvdate (выделяет красным)
Автор, добавлено 30.04.12, 23:12:50 
Охохох...

Пошуршал своими ленивыми мозгами. Одну строчку таки из себя выдавил:

procedure TForm2.uvdate(var s: String);
begin
s:=DateToStr(StrToDate(s)+1);
Caption:=S;//Это для быстрой проверки
end;

Как говорится, учитесь пока я жив :)
Антон, добавлено 30.04.12, 23:29:35 
Спасибо, честно говоря где-то предполагал такой вариант (что можно просто прибавить к дате), но сильно сомневался.
Саша, добавлено 16.10.12, 18:42:34 
procedure TForm1.N7Click(Sender: TObject);
 Var s:string;
  b,n,i:real;
 begin
case ComboBox1 of
  1: begin
  case ComboBox2 of
  1:b:=1;
  2:b:=2;
  3:b:=3;
  4:b:=4;
  5:b:=5;
  6:b:=6;
  7:b:=7;
  end;
  s:=Memo1.text;
  n:=length(s);
  for i:=1 to n do l:=char(ord(s[i])+b));
  s:=l;
  Memo1.Text:=s;
  end;

в чому помилка?
Автор, добавлено 16.10.12, 23:16:56 
Предложение

case ComboBox1 of

предполагает перечисляемое значение, а ComboBix1 это не значение, а имя компонента...
Пётр, добавлено 28.11.13, 18:42:37 
Большое спасибо за описание, уже полгода года забыл что такое паскаль.
Станислав, добавлено 6.12.13, 04:25:53 
Помогите пожалуйста,решить задачу:Создать определитель одного числа на другое.
Автор, добавлено 6.12.13, 06:42:16 
Поясните. Иначе, кроме иронии, ничего предложить не могу.

В любом случае, помощь предполагает, что вы сделали что-то сами, и возникла заминка, которую нужно преодолеть - тогда давайте ваши наработки сюда. Если же вы сами ничего не сделали, то это уже не "Помогите", а "СделайтеВместоМеня". Для решения задач с нуля есть соответствующая страничка на сайте.
Оставить комментарий:

Имя  

Текст комментария

  





Интернет-магазин электрооборудования