Урок Delphi 5

Собственные и структурные типы данных 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 программист может для своих целей конструировать собственные типы данных. Чтобы ввести в программу (описать) новый тип данных, применяется оператор с ключевым словом type:
   type название_типа = описание_типа;

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

   type FootballTeam = (Spartak, Dinamo, CSKA, Torpedo, Lokomotiv);
   var MyTeam: FootballTeam;
   begin
     MyTeam:=Spartak;
   end;

Вообще, под перечислимыми типами понимают все типы, для которых можно определить последовательность значений и их старшинство. К ним относятся:

  • все целочисленные типы, для которых всегда можно указать число, следующее за числом N;
  • символьные типы (Char): за символом 'a' всегда следует 'b', за '0' следует '1', и так далее;
  • логические типы - тип Boolean также представляет собой перечислимый тип: type Boolean = (false, true);
   Структурные типы данных используются практически в любой программе. Это такие типы, как
  • массивы
  • записи
  • множества

   Массив - это структура данных, доступ к элементам которой осуществляется по номеру (или индексу). Все элементы массива имеют одинаковый тип.
Описание массива имеет вид:

   type имя_типа_массива = array [диапазон] of тип_элемента;

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

   type TMyArray = array [1 .. 100] of Integer;

Теперь можно описать переменные типа TMyArray:

   var A, B: TMyArray;

Вместо присвоения типа можно явно описать переменные как массивы:

   var A, B : array [1..100] of Integer;

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

var N: Integer;
begin
   N := 65;
   A[5] := 101;
   A[N] := 165;
   A[N+3] := 200;
   B := A;
end;

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

   High() - вернёт число, являющееся верхней границей массива;
   Low() - вернёт число, являющееся нижней границей массива.

В скобки нужно подставить массив, границы которого требуется узнать.

Выражение B := A означает, что каждый элемент массива B будет равен элементу с таким же индексом массива A. Такое присвоение возможно только если оба массива объявлены через некий поименованный тип, или перечислены в одном списке. И в случае:

   var A: array[1..100] of String;
           B: array[1..100] of String;

его использовать невозможно (но возможно поэлементное присвоение B[1] := A[2]; и т.д.).

Массивы могут иметь несколько измерений, перечисляемых через запятую. Например, таблицу из четырёх столбцов и трёх строк:
1234
5678
9101112
можно описать в виде массива с двумя измерениями:

   type MyTable = array[1..4, 1..3] of Integer;
   var X : MyTable;
           Y : Integer;
   begin
       Y:=X[3, 2];   
   end;

Теперь в результате операции присвоения Y будет равен 7.
Многомерный, например, двумерный массив можно описать как массив массивов:

   type TMyArray = array [1 .. 4] of array [1 .. 3] of Integer;

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

   type TDinArray = array of Integer;
   var A : TDinArray;

После создания в динамическом массиве нет ни одного элемента. Необходимый размер задаётся в программе специальной процедурой SetLength. Массив из ста элементов:

   begin
    SetLength(A, 100);
   end;

Нижняя граница динамического массива всегда равна нулю. Поэтому индекс массива A может изменяться от 0 до 99.
Многомерные динамические массивы описываются именно как массивы массивов. Например, двумерный:

   type T3DinArray = array of array of Integer;
   var A : T3DinArray;

В программе сначала задаётся размер по первому измерению (количество столбцов):

   SetLength(A, 3);

Затем задаётся размер второго измерения для каждого из трёх столбцов, например:

   SetLength(A[0], 3);
   SetLength(A[1], 2);
   SetLength(A[2], 1);

   Таким образом создаётся треугольная матрица:    A00 A10 A20
A01 A12
A02
Чтобы освободить память, выделенную динамическому массиву, нужно массиву как целому присвоить значение nil:
    A:=nil;
Ключевое слово nil в Delphi означает отсутствие значения.

   Записи очень важный и удобный инструмент. Даже не применяя специальные технологии, с его помощью можно создавать собственные базы данных. Записи - это структура данных, каждый элемент которой имеет собственное имя и тип данных. Элемент записи иначе называют поле. Описание записи имеет вид:
   type имя_типа_записи = record
      название_поля : тип_поля ;
      . . .
      название_поля : тип_поля ;
   end;
Названия полей, имеющих одинаковый тип, можно, как и в случае описания переменных, указывать в одну строку через запятую. Для обращения к полю записи сначала указывают имя записи, затем точку, затем имя поля. Например, данные о персонале предприятия могут быть организованы таким типом записи:

   type TPers = record
     Fam, Name, Par : String;
     Year : Integer;
     Dep : String;
   end;
   var Pers : TPers;
   begin
    Pers.Fam:='Иванов';
    Pers.Name:='Иван';
    Pers.Par:='Иванович';
    Pers.Year:=1966;
    Pers.Dep:='Цех №1';
   end;

Теперь осталось записать эти данные в файл, предварительно объявив и его тип как TPers, и база данных готова. С файлом в Delphi также ассоциируется переменная, называемая файловой переменной, которая описывается так:
   VFile : file of тип_файла;
В качестве типа может использоваться любой ограниченный тип Delphi. При этом не допускается тип String, так как он допускает переменный размер до 2 ГБайт. Его необходимо ограничивать: String[N], где N - количество символов. Тип TPers из предыдущего примера должен быть описан, например, так:

   type TPers = record
     Fam, Name, Par : String[20];
     Year : Integer;
     Dep : String[10];
   end;

Теперь переменная такого типа занимает строго определённое место в памяти, и может быть записана в файл. Как это сделать, рассказывается во 2-й части Урока №7.

   Множество - это группа элементов, объединённая под одним именем, и с которой можно сравнивать другие величины, чтобы определить, принадлежат ли они этому множеству. Количество элементов в одном множестве не может превышать 256. Множество описывается так:

   type имя_множества = set of диапазон_значений_множества ;

В качестве диапазона может указываться любой тип, количество элементов в котором не больше 256. Например:

   type TMySet = set of  0 .. 255;
   type TMySet = set of  Byte;

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

   var MySet : TMySet;
   begin
    MySet:=[1, 3 .. 7, 9];
   end;

Чтобы проверить, является ли некое значение элементом множества, применяется оператор in в сочетании с условным оператором:

   var Key : Char;
           Str : String;
   begin
    if Key in ['0' .. '9', '+', '-'] then Str:='Math';
   end;

   Чтобы добавить элемент во множество, используется операция сложения, удалить - вычитания:

var Digit: set of Char=['1'..'9'];
var Math: Set of Char;
begin
  Math:=Digit+['+', '-', DecimalSeparator*];
end;

*Примечание: DecimalSeparator - встроенная в Delphi константа типа Char, имеющая значение символа-разделителя целой и дробной частей, который может быть равен точке ('.') либо запятой (','), в зависимости от текущих настроек Windows.


Переменные, константы и их типы           В начало урока          Выражения и операторы Delphi  

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



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

Арман, добавлено 5.09.09, 08:54:12 
Спасибо вам огромное! С вашей помощью написал первый калькулятр и текстовый редактор, изучаю делфи всего 3 дня=) я ваш постоянный посетитель=)
Макс, добавлено 17.09.09, 10:24:36 
Только вот примеров бы побольше... и примеры сразу входе программы, а не отрывками...
Владимир Семин, добавлено 4.11.09, 12:40:29 
Автор, посты у вас, конечно, очень интересные. Но вы не подумывали заменить дизайн?

Автор, добавлено 4.11.09, 15:16:52 
Думал, думал. Хочу, конечно, что-нибудь предпринять. К Новому Году, наверное, рожу.

джaн, добавлено 7.11.09, 01:18:21 
Все-таки на самом деле нравится мне Ваш блог. Всегда интересно читать, включая и эту тему. :)

dEpdribeKer, добавлено 8.11.09, 21:26:28 
Отличный сайт и материалы очень познавательные
Захар Сенников, добавлено 28.11.09, 01:46:15 
В посте много чего упрощено, в отличии от реальности... :)

Оксана, добавлено 4.12.09, 20:35:25 
Спасибо, не надо тратить кучу времени на сканирование
XAЛAШKA, добавлено 14.01.10, 18:43:15 
Занятно написано, но как говорится, для полноты информации нужно минимум хотя бы три источника :)

Ольга, добавлено 29.01.10, 23:36:02 
Захар Сенников, ВСЕ ГЕНИАЛЬНОЕ - ПРОСТО!
Зачем все усложнять? Всегда можно обойтись простыми решениями, разбивать программу на процедуры и функции, которые всегда можно вызвать. Стремиться к блочной структуре. В этом весь смысл.
Ольга, добавлено 30.01.10, 13:11:44 
Уважаемый Автор! Позвольте Вам задать несколько вопросов:
1. Индексы массива всегда начинаются с 1, а множества с 0?
2. В описании элемента массива A[i, j], i - номер столбца, а j - номер строки? А не наоборот?
3. Возможно ли создать массив записей, к примеру, используя такую структуру из Вашего урока:
type TPers = record
  Fam, Name, Par : String[20];
  Year : Integer;
  Dep : String[10];
end;
var Pers: array [1..100] of TPers;


Прошу извинить, если мои вопросы не корректны. Просто хочу разобраться. Заранее благодарна.
Автор (Андрей!), добавлено 30.01.10, 13:53:38 
1. Почему индексы массива только с 1, из описания следует, что диапазон массива задаёт программист, за исключением динамических массивов, они - только с 0.
Множество вообще не индексируется. Можно лишь сказать, принадлежит ли элемент множеству или нет, добавить или исключить элемент из множества. То есть у конкретного элемента множества нет своего порядкового номера, это не нужно. Начертите круг, напишите внутри в произвольных местах любые например цифры. Все они элементы множества, никто не первый.

2. В массиве действительно сначала идёт индекс столбца, затем - строки. Хотя это субъективно, что Вы считаете тем или другим, это же только в нашем мозгу! Но в компоненте TStringGrid это именно так - а это уже наглядно. Так что, чтобы не путаться...

3. Всё правильно!
Ольга, добавлено 30.01.10, 14:49:58 
Андрей! Спасибо за ответы!
Тогда еще такой вопрос по моему предыдущему посту по пункту 3: Тогда автоматически Fam, Name, Par, Year, Dep тоже станут массивами соответствующих типов и их можно будет писать, к примеру, Fam[i]?
Андрей, добавлено 30.01.10, 15:31:36 
Fam и другие - в составе записи, а запись - элемент массива, поэтому обращаться к ним нужно будет так:
Pers[i].Fam
Ольга, добавлено 30.01.10, 16:29:57 
Андрей, Спасибо!
Филипп Смирнов, добавлено 17.03.10, 18:39:37 
Вот про это я почитал с превеликим интересом. И прочитал бы еще больше! Планируете и в дальнейшем писать на эту же тему? Спасибо

CTИЛЯГA, добавлено 22.03.10, 13:23:20 
Данный пост на самом деле помог мне принять очень важное для себя решение. За что автору отдельное спасибо! Жду от Вас новых сообщений!

Евгений, добавлено 28.03.10, 12:56:32 
Побольше-бы конкретных примеров!
smersh36, добавлено 2.05.10, 16:12:18 
Да, сколько людей, столько и мнений, но истина где - то рядом :)
Михаил, добавлено 22.05.10, 13:15:54 
Отличные уроки!!!

Женя, добавлено 18.08.10, 21:05:03 
Всё очень интересно, но хотелось бы более конкретные примеры которые можно было написать у себя и посмотреть результат.
Аноним, добавлено 12.11.10, 13:50:37 
Здравствуйте. Такое дело. У меня есть множество edit, но предположим, что их 3. Так вот в эти editы вводятся параметры (числа) вводятся они каждый час. Т.е. Таймер каждый час делает enable:=true, оператор вводит параметры и нажимает кнопку OK я так думаю что при нажатии этой кнопки enable:=false у эдитов и таймер должен снова начать отсчитывать время, так вот мне надо, чтобы из эдитов информация по нажатию кнопки ок попадала в массив, наверное в 3 непомерных. Позже мне из этих массивов надо будет постоить график каждого параметра (чисел вводимых в эдит) от времени. Как мне записать эти массивы.
Автор, добавлено 12.11.10, 15:17:36 
Я так понял, речь идёт о динамических массивах. Вот запись:

var Array1, Array2, Array3: Array of Integer;

Перед каждым добавлением нужно увеличить количество элементов в массивах:

SetLength(Array1, Length(Array1)+1);
SetLength(Array2, Length(Array2)+1);
SetLength(Array3, Length(Array3)+1);

Затем можно присваивать значения последним элементам:

Array1[High(Array1)]:=StrToInt(Edit1.Text);
Array2[High(Array2)]:=StrToInt(Edit2.Text);
Array3[High(Array3)]:=StrToInt(Edit3.Text);


А если edit-ов много, я вообще организовал бы массив динамических массивов и массив edit-ов! Тогда можно было бы упростить запись, организовав эти действия в цикле.
Аноним, добавлено 13.11.10, 10:54:11 
Editoв много, очень много, 28 штук, но я что-то эти массивы не догоняю. Буду разбираться.
Аноним, добавлено 13.11.10, 11:04:50 
Спасибо большое
Аноним, добавлено 13.11.10, 11:58:44 
Такой вопрос еще, у меня есть 2еdita и стринггрид из 2 строчек и 3 столбцов, то есть 1 строка и 1 столбец фиксированные. Как сделать так чтобы по нажатию кнопки числа из еditов заносились в таблицу. Проблема в том-как сделать так, чтобы по нажатии кнопки добавлялась строка, которой до этого не было, то есть если я 30 раз нажму кнопку, то у меня получится 31 строка.
Автор, добавлено 13.11.10, 12:05:49 
Массив едитов: var edits: Array[1..28] of TEdit; А теперь нужно создать эти едиты в цикле edits[i]:=TEdit.Create(Form1); edits[i].Parent:=Form1; Настроить размеры и местоположение.

Автор, добавлено 13.11.10, 12:12:28 
Добавление строки в таблицу: StringGrid.RowCount:=StringGrid.RowCount.+1;
Аноним, добавлено 13.11.10, 12:40:04 
А как-нибудь так вариант писать: " stringgrid.cells[1,i+1]:=edit1.text; ", чтобы заполнять столбец?
Автор, добавлено 13.11.10, 16:46:15 
Не я пишу программу и не знаю что такое i+1. A индекс последней строки всегда равен RowCount-1.
Сергей, добавлено 15.03.11, 02:56:44 
Ув Автор, можете подсказать как вызывать строки у FileListBox?
Автор, добавлено 15.03.11, 18:43:10 
Честно признаюсь, что в моей D7 этого компонента (как и других компонентов работы с файлами) нет... Но я сильно подозреваю, что работать с FileListBox следует так же, как и с обычным ListBox. Кстати, если проясните этот вопрос, черкните сюда...
Децл, добавлено 18.05.11, 19:36:09 
Здравствуйте, помогите пожалуйста сложить два динамических массива(дельфи7). Массивы размещены в Стринггрид1,2 и их надо сложить и вывести в Стринггрид3, как это сделать можете помочь плз!! Размерность массивов вводится в едит1,2 и при нажатии на баттон они создается.
Автор, добавлено 18.05.11, 21:38:02 
Выше прочтите как создаются динамические массивы:

A, B, C: array of Real;
SetLength(A)=StrToInt(Edit1.Text)-1; ну и т.д.

Вот вам и массивы... Складывать-то умеете? Это знак +. Только нужно поэлементно... )))
Децл, добавлено 19.05.11, 20:01:58 
Массивы я создаю так но выбивает ошибку

procedure TForm1.Button1Click(Sender: TObject);
begin
 StringGrid1.FixedCols :=0;
  StringGrid1.FixedRows :=0;

  StringGrid1.ColCount := StrToInt(Edit1.Text);
  StringGrid1.RowCount := StrToInt(Edit2.Text);

  StringGrid1.Options := StringGrid1.Options + [goEditing];

  StringGrid2.FixedCols :=0;
  StringGrid2.FixedRows :=0;

  StringGrid2.ColCount := StrToInt(Edit1.Text);
  StringGrid2.RowCount := StrToInt(Edit2.Text);
  StringGrid2.Options := StringGrid2.Options + [goEditing];

  StringGrid3.FixedCols :=0;
  StringGrid3.FixedRows :=0;

  StringGrid3.ColCount := StrToInt(Edit1.Text);
  StringGrid3.RowCount := StrToInt(Edit2.Text);
  StringGrid3.Options := StringGrid3.Options + [goEditing];
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
i:=strtoint(edit1.Text);
j:=strtoint(edit2.Text);
with StringGrid1 do
SetLength(mas1, i * j);
with StringGrid2 do
SetLength(mas2, i * j);
with StringGrid3 do
SetLength(mas3, i * j);
StringGrid3.Cells[j, i] :=FloatToStr( StrToFloat(StringGrid1.Cells[j,i]) + StrToFloat(StringGrid2.Cells[j,i]) );


Автор, добавлено 19.05.11, 20:41:15 
Ну что, всё верно. А какя ошибка-то выскакивает?
Недочёты есть, конечно.
1. Вот этого: with StringGrid1 do (ну и StringGrid2, StringGrid3) не нужно.
2. Массивы не описаны. Они глобальные?
3. А где собственно суммирование? Ведь это делается в двух вложенных циклах

   for k:=0 to i-1 do
   for n:=0 to j-1 do
     StringGrid3.Cells[k, n] :=FloatToStr( StrToFloat(StringGrid1.Cells[k, n]) + StrToFloat(StringGrid2.Cells[k, n]) );


Складывать нужно поэлементно, я уже писал об этом. Кстати, а зачем вы массивы-то создали? Они же не используются у вас...
Децл, добавлено 22.05.11, 16:20:57 
Большое Вам спасибо Автор все пошло только можете мне объяснить почему такой именно цикл?
for k:=0 to i-1 do
  for n:=0 to j-1 do

Вы не представляете как я Вам благодарен!!!! столько парил голову из-за своего незнания и не понимания, большое Вам спасибо!!!!
Децл, добавлено 22.05.11, 17:55:33 
Я хотел еще спросить умножение матриц делается аналогично?
for k:=0 to i-1 do
  for n:=0 to j-1 do
  StringGrid3.Cells[k, n] :=FloatToStr( StrToFloat(StringGrid1.Cells[k, n]) + StrToFloat(StringGrid2.Cells[k, n]) );
Автор, добавлено 22.05.11, 18:58:30 
Ну, чего ещё-то объяснять... Весь урок про массивы выше - обещаете прочитать? Тогда ладно:
Динамические массивы всегда имеют номер первого элемента равный нулю. Таблицы тоже отсчитывают количество строк и столбцов от нуля. Предположим, в таблице (массиве) 5 элементов. Считаем 0, 1, 2, 3, 4 - сколько элементов? Пять. А номер последнего? Пять минус 1 сколько будет - четыре (как ни странно). В таблице номер последнего столбца (ну и строки) равен всегда количество столбцов (ну или строк) минус одЫн. Вот вам и цикл, от нуля до количества столбцов (строк) -1. Только переменные цикла не перепутайте местами в Cells. А порядок вложенности циклов (по строкам сначала или по столбцам) неважно.

Во втором вопросе непонятно. Вопрос про умножение, а в примере плюс... Ну да неважно. А какая разница какое действие? Хотя, математически, умножение МАТРИЦ это не просто поэлементное умножение ячеек. Гораздо сложнее. Но, думаю, вы не это имеете в виду.
Децл, добавлено 22.05.11, 19:47:22 
Извините, урок уже начинаю читать))))
ну а про второй вопрос, как бы перемножить динамические массивы, если я их создаю все тем же способом:
Рrocedure TForm1.Button1Click(Sender: TObject);
begin
 StringGrid1.FixedCols :=0;
  StringGrid1.FixedRows :=0;

  StringGrid1.ColCount := StrToInt(Edit1.Text);
  StringGrid1.RowCount := StrToInt(Edit2.Text);

  StringGrid2.FixedCols :=0;
  StringGrid2.FixedRows :=0;

  StringGrid2.ColCount := StrToInt(Edit3.Text);
  StringGrid2.RowCount := StrToInt(Edit4.Text);
Во втором вопросе я просто скопировал код и забыл поставить знак *, извените
Автор, добавлено 22.05.11, 21:11:38 
Я так и понял. Но тогда речь идёт о поэлементном умножении. В этом случае таблицы и массивы должны совпадать. Поэтому значения Edit1 и Edit3, Edit2 и Edit4 должны совпадать. Вывод: Edit3 и Edit4 не нужны, они могут служить источником ошибок, если вдруг не совпадут с Edit1 и Edit2.
Децл, добавлено 23.05.11, 16:54:48 
procedure TForm1.Button3Click(Sender: TObject);
var i,j,k,n:integer;
begin

  if edit2.text= edit3.text then
  StringGrid3.FixedCols :=0;
  StringGrid3.FixedRows :=0;

  StringGrid3.ColCount := StrToInt(Edit2.Text);
  StringGrid3.RowCount := StrToInt(Edit3.Text);

  i:=strtoint(edit2.Text);
  j:=strtoint(edit3.Text);

  with StringGrid3 do begin
for k:=0 to i-1 do
  for n:=0 to j-1 do
  StringGrid3.Cells[k, n] :=FloatToStr( StrToFloat(StringGrid1.Cells[k, n]) * StrToFloat(StringGrid2.Cells[k, n]) );
  end;

if edit1.text=edit4.text then
StringGrid3.FixedCols :=0;
  StringGrid3.FixedRows :=0;

  StringGrid3.ColCount := StrToInt(Edit1.Text);
  StringGrid3.RowCount := StrToInt(Edit4.Text);
 

begin
i:=strtoint(edit1.Text);
j:=strtoint(edit4.Text);
with StringGrid3 do begin
for k:=0 to i-1 do
  for n:=0 to j-1 do
  StringGrid3.Cells[k, n] :=FloatToStr( StrToFloat(StringGrid1.Cells[k, n]) * StrToFloat(StringGrid2.Cells[k, n]) );
end;
end;
if edit2.text<>edit3.text and edit1.text<>edit4.text then label1.Caption:='Неправильна розмірність матриць';
end;

Ошибка делается на второй части(после and) на знаке <>(edit1.text<>edit4.text) если елементы менять местами то на edit2.text<>edit3.text
Автор, добавлено 23.05.11, 17:41:52 
Ошибка, говорите? Программа вообще неправильная.
1.вместо

  StringGrid3.ColCount := StrToInt(Edit2.Text);
  StringGrid3.RowCount := StrToInt(Edit3.Text);

  i:=strtoint(edit2.Text);
  j:=strtoint(edit3.Text);

нужно:

  i:=strtoint(edit2.Text);
  j:=strtoint(edit3.Text);

  StringGrid3.ColCount := i;
  StringGrid3.RowCount := j;
Потому что компьютер он таки да, железный, но и его не нужно заставлять два раза одно и то же вычислять.

2. StringGrid3.FixedRows ВСЕГДА будет равно нулю, потому что правильно так:

  if edit1.text=edit4.text then
  begin
  StringGrid3.FixedCols :=0;
  StringGrid3.FixedRows :=0;
  end;
 А может, end нужно и ещё дальше переместить? Посмотрите.
Всё это не ошибки, но программа может работать неверно.

3. Ну а насчёт ошибки, нужно условия в скобки заключать, как всё условие, так и его части:

  if ((edit2.text<>edit3.text) and (edit1.text<>edit4.text)) then label1.Caption:='Неправильна розмірність матриць';
Децл, добавлено 23.05.11, 18:06:06 
Ладно да я офигенно ошибся написал что программа правильна потому что в ходе испытаний она все-таки коем образом заработала но потом я забыл наверное сохранить ну и все пошло в ж..пу, мне вообщем то можно все делать с квадратными матрицами просто хотел сделать умножение с матрицами разных размеров, ну ладно БОЛЬШОЕ СПАСИБО!!!
Автор, добавлено 23.05.11, 18:55:47 
Блин, вы меня путаете с умножением МАТРИЦ. То что у вас, называется поэлементное умножение. НЕ обязательно квадратные матрицы, просто количество строк и столбцов у этих двух матриц должно быть одинаково. Вот проверка:

if ((StringGrid1.ColCount = StringGrid2.ColCount) and (StringGrid1.RowCount = StringGrid2.RowCount)) then
  begin
  n:=StringGrid1.ColCount;
  k:=StringGrid1.RowCount;
  StringGrid3.ColCount:=n;
  StringGrid3.RowCount:=k;
  //Ну и дальше умножение:
  for i:=0 to n do
  for j:=0 to k do
  StringGrid3.Cells[i, j]:=FloatToStr(StrToFloat(StringGrid3.Cells[i, j])*StrToFloat(StringGrid3.Cells[i, j]));
  end else label1.Caption:='Неправильна розмірність матриць';
Децл, добавлено 25.05.11, 15:55:22 
Нашел в интернете умножение матриц(динамические) но заполняется только последняя клетка матрицы, можете написать в чем ошибка и как ее исправить?
  if StringGrid1.ColCount=StringGrid2.RowCount then
  StringGrid3.FixedCols :=0;
  StringGrid3.FixedRows :=0;

  StringGrid3.ColCount := StringGrid2.ColCount;
  StringGrid3.RowCount := StringGrid1.RowCount;

  j:=strtoint(edit1.Text);
  i:=strtoint(edit4.Text);
  with StringGrid3 do
  for k:=0 to j-1 do {цикл по строкам первой матрицы}
  begin
  Sum :=0;
  for n:=0 to j-1 do {цикл по столбцам метрицы и строкам вектора-столбца}
  Sum:=Sum + StrToInt(StringGrid1.Cells[j-1,i-1]) * StrToInt(StringGrid2.Cells[0,j-1]);
  StringGrid3.Cells[0,i-1] :=IntToStr(Sum);
  end;
  end;
Децл, добавлено 25.05.11, 16:06:00 
То есть одна клетка StringGrid3
Автор, добавлено 26.05.11, 14:34:04 
Я бы решал задачу нахождения произведения таблиц так. Во-первых, сразу переименовал бы таблицы, не StringGrid1, 2, 3 а SG1, SG2, SG3, чтобы записи были покороче, тут оператором with не отделаешься.

Далее, ввёл бы две вспомогательные переменные R1, R2 типа запись с полями Col, Row, где содержались бы размерности таблиц SG1, SG2:

type Razmer = Record
  Col, Row: Integer;
end;
var R1, R2: Razmer;

R1.Col:=StrToInt(Edit1.Text);
R1.Row:=StrToInt(Edit2.Text);
R2.Col:=StrToInt(Edit3.Text);
R2.Row:=StrToInt(Edit4.Text);

Теперь можно делать проверку на правильную размерность, т.е. чтобы количество строк первой таблицы совпадало с количеством столбцов второй:

if R1.Row = R2.Col then
  begin

  end else ShowMessage('Неправильна розмірність матриць');

И уже внутри этих begin/end вычислять само произведение. Правильно?
Сначала нужно определить размерность третьей таблицы:

SG3.ColCount:=R1.Col;
SG3.RowCount:=R2.Row;

Теперь можно записать вложенные циклы для подсчёта элементов этой таблицы:

for i:=0 to R1.Col-1 do
for j:=0 to R2.Row-1 do
  begin
  //Здесь сам подсчёт элемента SG3.Cells[i, j]
  end;

Википедия, умножение матриц (найдено через Google):



Видим, что для подсчёта элемента с индексами (i, j) нужен ещё один цикл. Для него введём переменную цикла r

for r:=0 to R1.Row-1 do //ну или R2.Col-1, у нас же они равны по первому условию
  Sum:=Sum+StrToFloat(SG1.Cells[i, r])*StrToFloat(SG2.Cells[r, j]);
SG3.Cells[i, j]:=FloatToStr(Sum);

Вот что получилось:

procedure TForm1.Button1Click(Sender: TObject);
type Razmer = Record
  Col, Row: Integer;
end;
var R1, R2: Razmer;
 i, j, r: Integer;
 Sum: Real;
begin
R1.Col:=StrToInt(Edit1.Text);
R1.Row:=StrToInt(Edit2.Text);
R2.Col:=StrToInt(Edit3.Text);
R2.Row:=StrToInt(Edit4.Text);

SG1.ColCount:=R1.Col;
SG1.RowCount:=R1.Row;
SG2.ColCount:=R2.Col;
SG2.RowCount:=R2.Row;

if R1.Row = R2.Col then
  begin
  SG3.ColCount:=R1.Col;
  SG3.RowCount:=R2.Row;

for i:=0 to R1.Col-1 do
for j:=0 to R2.Row-1 do
  begin
  Sum:=0;
  for r:=0 to R1.Row-1 do
    Sum:=Sum+StrToFloat(SG1.Cells[i, r])*StrToFloat(SG2.Cells[r, j]);
  SG3.Cells[i, j]:=FloatToStr(Sum);
  end;
  end else ShowMessage('Неправильна розмірність матриць');
end;

Децл, добавлено 26.05.11, 16:14:12 
Большое спасибо все работает и все ясно!!!
Децл, добавлено 26.05.11, 16:15:07 
Автору Respect!!!!!!!!
Андрей, добавлено 26.05.11, 18:56:08 
Здравствуйте Автор! Вы бы не могли мне помочь, у меня вопрос например при сложении динамических массивов забыли ввести в ячейку число можно ли как-то записать что бы если пустая ячейка то она автоматически равнялась нулю?
Андрей, добавлено 26.05.11, 18:56:39 
Массивы StringGrid
Автор, добавлено 26.05.11, 21:44:13 
Само по себе ничего не бывает. Всё нужно программировать самому! И делать проверки на действия пользователя, и защиту от ошибок.
Есть функция trim, удалающая пробелы слева и справа. Вот и проверяйте перед суммированием ячейку, и при необходимости вписывайте ноль.

if trim(Cells[i, j])='' then Cells[i, j]:='0';

А если пользователь (вот лошидзе) вместо цифры букву тиснет?..
Андрей, добавлено 26.05.11, 21:58:57 
Не у меня только цифры вводятся
procedure TForm1.StringGrid1KeyPress(Sender: TObject; var Key: Char);
begin
If not (Key in ['0'..'9',DecimalSeparator,#8]) then
Key:=#0;
end;
Большое спасибо, а где именно это вводить в цикл, пусть будет такой цикл, где именно вводить это?
for k:=0 to i-1 do
  for n:=0 to j-1 do
  StringGrid3.Cells[k, n] :=FloatToStr( StrToFloat(StringGrid1.Cells[k, n]) + StrToFloat(StringGrid2.Cells[k, n]) );
Вопрос туповатый но просто ошибку выбивает
Автор, добавлено 27.05.11, 08:58:24 
Пока ничего нового не придумали, ни в жизни, ни в программировании. Это вставляется перед тем оператором, где возникает ошибка. Всё строго по поговорке:
"Знал бы что упаду, соломки бы ЗАРАНЕЕ подстелил". Так если знаете, где ошибка, так исправляйте ранее.

первый цикл
второй цикл
???????????
происходит ошибка
Андрей, добавлено 27.05.11, 13:11:57 
Да, все получилось, спасибо. А возможно ли сделать так что бы при нажатии на button stringGrid как бы не то что очищалась а ставала такая как когда мы ее на форму кидаем(то есть например я создал там 10х10 таблицу а при нажатии на button все клетки иcщезают и stringGrid стает начальным. таким каким он отображается в форме)?
А еще как бы сделать что бы в клетку stringGrid вводился десятичный разделитель на так что бы в пустую клетку нельзя было а только после цифры нашел такое для едита и пробовал написать для stringGrid но что-то вообще не возможно вводить запятую(десятичный разделитель):

procedure TForm1.SG1KeyPress(Sender: TObject; var Key: Char);
var i,j:integer;
begin
If not (Key in ['0'..'9',DecimalSeparator,#8]) then
Key:=#0;
if Key=DecimalSeparator then if (Length(SG1.Cells[j, i])<=0)or(Pos(DecimalSeparator,SG1.Cells[j, i])<>0) then Key:=#0;
end;
Андрей, добавлено 27.05.11, 13:41:08 
не с запятой разобрался но не могу сделать так что бы нельзя было вводить запятую сначала, при пустой клетке
If not (Key in ['0'..'9',DecimalSeparator,#8]) then
Key:=#0;
with SG1 do begin
if (Pos(DecimalSeparator, SG1.Cells[Col, Row]) > 0) and (Key = DecimalSeparator) then Key := #0;
Автор, добавлено 27.05.11, 14:21:37 
Это происходит потому, что вы ищете запятую в предыдущем значении Cells[Col< Row]. Запятой там ещё нет. То есть, вы нажимаете на запятую при пустой ячейке, и эту пустоту анализируете. Конечно, запятой нет, и ввод разрешён. Выход заключается в том, что анализировать это нужно не в обработчике OnKeyPress, а в OnKeyUp, то есть при отпускании клавиши. Запятая уже "записалась" в ячейку, и можно анализировать. Конечно, предотвратить появление запятой уже возможности нет. Но что мешает сразу приписать впереди ноль? Ведь так и делается, например, в калькуляторе. Он же вам не препятствует на запятую нажимать, сами попробуйте.
Соответственно, в обработчике OnKeyPress мы отсеиваем неверные символы, а в обработчике OnKeyUp - положение запятой.
Кстати, на этом сайте я сделал целую статью как обеспечить правильный ввод только цифр. Там ещё кое-какие полезные вещи есть, почитайте. Например, пользователь может ввести вместо запятой (ну, которая DecimalSeparator) точку и, когда она не появится, будет в недоумении. Он же заранее не знает, какой символ является разделителем.
Децл, добавлено 28.05.11, 10:31:27 
Здравствуйте, у меня такой вопрос, с Вашим кодом все ок но если создавать матрицы 3х2 и 4х3 то выбивает ошибку, а при умножении можно ведь поменять местами матрици и выйдет 4х3 и 3х2 и матрица получится 4х2 но выбивает ошибку при вычислении, Вы бы не могли бы помочь разобратся в чем дело( в принципе я то знаю приблизительно в чем дело но додуматся как написать правильно не могу):

procedure TForm1.Button9Click(Sender: TObject);
type Razmer = Record
  Col, Row: Integer;
end;
var R1, R2: Razmer;
 i, j, r: Integer;
 Sum: Real;
begin
if (Length(Edit1.Text)>=1) and (Length(Edit2.Text)>=1) and (Length(Edit3.Text)>=1)and (Length(Edit4.Text)>=1) then begin
R1.Col:=StrToInt(Edit1.Text);
R1.Row:=StrToInt(Edit2.Text);
R2.Col:=StrToInt(Edit3.Text);
R2.Row:=StrToInt(Edit4.Text);

SG1.ColCount:=R1.Col;
SG1.RowCount:=R1.Row;
SG2.ColCount:=R2.Col;
SG2.RowCount:=R2.Row;

if R1.Row = R2.Col then
  begin
  SG3.ColCount:=R1.Col;
  SG3.RowCount:=R2.Row;

for i:=0 to R1.Col-1 do
for j:=0 to R2.Row-1 do
  begin
  Sum:=0;
  for r:=0 to R1.Row-1 do
  Sum:=Sum+StrToFloat(SG1.Cells[i, r])*StrToFloat(SG2.Cells[r, j]);
  SG3.Cells[i, j]:=FloatToStr(Sum);
  end;
  end else ShowMessage('Неправильна розмірність матриць');
end;
end;
Автор, добавлено 28.05.11, 12:08:01 
Почитайте про умножение матриц. А*В не равно В*А. Так что всё правильно. Матрицы менять местами нельзя.
Иными словами, матрицу 4х3 можно умножать на 3х2, а наоборот нельзя.
И оператор if R1.Col=R2.Row как раз и служит для соблюдения этого условия.
Децл, добавлено 28.05.11, 13:50:21 
Спасибо!
Видел что Вы писали про то как сделать что бы если забыли ввести в клетку число значение ставало автоматически 0, но у меня не все заполняется нулями почему-то( вот создал матрицу 3х2 и 2х3 но при нажатии вычислить ошибка и вижу что стринггриды заполнены не полностью нулями):
with SG1 do
for i:=0 to SG1.ColCount-1 do
for j:=0 to SG1.RowCount-1 do
if trim(Cells[j, i])='' then Cells[j, i]:='0';
with SG2 do
for i:=0 to SG1.ColCount-1 do
for j:=0 to SG2.RowCount-1 do
if trim(Cells[j, i])='' then Cells[j, i]:='0';
with SG3 do begin
i:=strtoint(edit1.Text);
j:=strtoint(edit2.Text);
SG3.ColCount:=SG1.ColCount;
  SG3.RowCount:=SG1.RowCount;
for k:=0 to i-1 do
  for n:=0 to j-1 do
  SG3.Cells[k, n] :=FloatToStr( StrToFloat(SG1.Cells[k, n]) * StrToFloat(Edit5.Text) );
А и еще Вы бы не могли подсказать хорошие книги(по своему опыту) по delphi(у меня delphi 7 но думаю это не имеет значения)
Автор, добавлено 28.05.11, 17:15:43 
Смысл оператора with в том чтобы не писать потом SG1.ColCount а просто ColCount. А у вас чего? Вот и вылезает ошибка. Так что уберите либо with либо SG.
А сама ошибка в том что перепутано вместо SG2 написано SG1.
Децл, добавлено 1.06.11, 16:24:56 
Спасибо, все понятно!!
Илья, добавлено 18.10.11, 00:19:12 
вот из самого начала... куда надо вписывать код чтобы появлялись массивы я вписываю в : procedure TForm1.FormCreate(Sender: TObject);
но на форме ничего не появляется подскажите пожалуйсто неопытному, но стремящемуся!
Автор, добавлено 18.10.11, 07:06:26 
Илья, интересно, что вы раньше изучали? Basic наверное? Откуда убеждение, что на Форме должно что-то появляться? На Форме появляются только визуальные объекты такие как компоненты, выми лично выбираемые из палитры компонентов. А массивы - это ячейки памяти в компьютере, и никак на Форме появиться не могут. Чтобы значения некоторых элементов массива появились на Форме, нужно их вывести в один из визуальных компонентов, для этого специально предназначенных - например, Label.

Вот например, поставим на Форму Label, а в обработчике OnCreate напишем:

procedure TForm1.FormCreate(Sender: TObject);
var A: Array[1..10] of Integer;
begin
  A[1]:=1;
  A[2]:=2;
  A[3]:=A[1]+A[2];
  Label1.Caption:=IntToStr(A[3]);
end;

Мы организовали локальный массив (то есть он не будет существовать после завершения процедуры OnCreate), присвоили некоторым ячейкам значения, провели требуемые вычисления и вывели результат. А вообще, нужно бы не с пятого урока начинать, а с первого - к пятому это всё уже описано.
Илья , добавлено 18.10.11, 14:54:28 
кстати с первого и начал.
Илья, добавлено 18.10.11, 14:55:49 
для чего же тогда нужен массив если он не отображается графически на форме? чтобы брать от туда значения?
Автор, добавлено 18.10.11, 15:43:42 
Ну да, конечно! А зачем отображать графически на Форме то, с чем нужно просто оперировать? Ведь отображение графики будет тормозить процесс! Вот нашли результат - тогда и выводи себе на здоровье. Кстати, есть всё же компонент, который может отображать массивы - это таблица StringGrid. Но всё равно это не на Форме, а в соответствующем компоненте. Хотя, может вы это и имели в виду.
Илья, добавлено 18.10.11, 16:12:32 
спасибо автор, радует что ты упорно следишь за комментариями
Автор, добавлено 18.10.11, 16:13:54 
Чтобы спам вовремя удалять...
Олег, добавлено 25.10.11, 17:51:05 
здравствуйте автор,у меня возник ряд вопросов ,по которым вы возможно мне ответите: дана задача: заполнить квадратную матрицу случайными заглавными символами Кириллицы.Вывести на форму.Сформировать новую матрицу исключив диагональные элементы исходной матрицы.Вопрос первый, сделал программу выводящую матрицу
procedure TForm3.Button1Click(Sender: TObject); var A:array[1..10,1..10] of char;
B:char; i,j,k,l,m:byte;
begin randomize; form3.Refresh;
for i:=1 to 10 do for j:=1 to 10 do
begin
A[i,j]:=chr(random(33)+128 );
canvas.TextOut(j*25,i*30,A[i,j]);
end;
end;
end.
но вместо кириллицы я увидел ряд символов... 2 вопрос:каким способом вычеркнуть диагонали? спасибо.
Автор, добавлено 25.10.11, 19:05:28 
Вместо сложной формулы, вычисляющей код символа, проще использовать текстовую константу, содержащую весь ряд кириллических символов. Не самому же печатать - с полпинка нашёл в сети. И вот что получилось:

var A: array[1..10,1..10] of char;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var i, j, k, l, m: byte;
const B = 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ';
begin
 randomize;
 Refresh;
 for i:=1 to 10 do
 for j:=1 to 10 do
  begin
  A[i,j]:=B[random(32)+1];
  canvas.TextOut(j*25, i*30, A[i,j]);
  end;
end;

С вычёркиванием диагоналей пока непонятно. Смог только удалить диагональные элементы, ну, грубо - заменить на пробелы. Сейчас думаю, что дальше делать.


Олег, добавлено 25.10.11, 19:17:09 
сделал ошибку в визуальном делфи везде ANSI!!!))
а в анси:
А-Я 192-223
а-я 224-255 тогда A[i,j]:=chr(random(33)+192 ); вот исправил строку

Автор, добавлено 25.10.11, 20:28:51 
В общем, получилось сдвинуть в строке символы на место пробелов. В строке их два. Сначала удалил один, затем повторным циклом - второй. Что-то в одном цикле не вышло. В результате получилась матрица 10 строк 8 столбцов:

procedure TForm1.Button2Click(Sender: TObject);
var i, j, k: byte;
begin
 Refresh;
 for i:=1 to 10 do
 for j:=1 to 10 do
  if ((i=j)or(i+j=11)) then A[i, j]:=' ';
 for j:=1 to 10 do
  begin
  k:=0;
//Удаляем первый пробел
 for i:=1 to 10 do
  begin
  if A[i, j]=' ' then k:=k+1;
if k=2 then k:=1; //Убираем влияние второго пробела
  A[i, j]:=A[i+k, j];
  end;
  end;
// Удаляем второй пробел
 for j:=1 to 10 do
  begin
  k:=0;
 for i:=1 to 10 do
  begin
  if A[i, j]=' ' then k:=k+1;
  A[i, j]:=A[i+k, j];
  end;
  end;
 for j:=1 to 10 do
 for i:=1 to 8 do
  canvas.TextOut(i*30, j*25, A[i, j]);
end;

Циклы по i и j местами поменять пришлось, в том числе и при создании матрицы, т.к. по моему менталитету, вначале идёт индекс столбца...
Олег, добавлено 25.10.11, 20:44:31 
Да, все осознал, все работает, спасибо.
Илья, добавлено 28.12.11, 12:53:31 
делаю свой тип:
type
  TForm1 = class(TForm)
  ComboBox1: TComboBox;
  Label1: TLabel;
  Edit1: TEdit;
  ComboBox2: TComboBox;
  Button1: TButton;
  Label2: TLabel;
  SystemSCH16 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 0, a, b, c, d, e, f, A, B, C, D, E, F);
Выбивает постоянно ошибку: "Ecpected ':' but '=' found"
Что делать?
п.с. SystemSCH16 это типа шестнадцатиричный тип (не знаю только нужны ли маленькие буквы...)
Автор, добавлено 28.12.11, 15:35:18 
Свой тип делается как СВОЙ, а не внедряется в тип, описывающий Форму. Но у вас, похоже, не свой тип, а просто множество. Создайте переменную типа множество, содержащее либо символы (тогда они в кавычках должны быть '1' и так далее, либо это целые числа в 16-ричном виде, тогда перед числом $: $A (это равно 10 в 10-ричной системе):

var Form1: TForm1;
  SystemSCH16: set of Char=['0', '1'..'9', 'a'..'f', 'A'..'F'];//или:
  SystemSCH16: set of Byte=[$1..$F];

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

И больше никогда не лепите отсебятину туда, куда вы сейчас это вставили - там сама Delphi описывает тип создаваемой Формы.
Коля, добавлено 7.02.12, 22:36:36 
Помогите реализовать произведение каждого элемента StringGrid1 в одну ячейку StringGrid2.Т.е. в StringGrid1 есть динамический массив, который необходимо перемножить ел.1 * ел.2 * ел.3 и тд. построчно, и записать результат в одну ячейку StringGrid2.
Коля, добавлено 7.02.12, 23:52:15 
Вот код:
[21:47:55] Ольчик Кордик: var
i,j:Integer;
a,b,ab:Extended;
  begin
  a:=1;
for i:=1 to SG1.ColCount - 1 do
  for j:=1 to SG1.RowCount - 1 do
  begin
  a:=a*StrToFloat(SG1.Cells[i,j]);
  end;
SG2.Cells[1,1]:=FloatToStr(a);
end;
 если кому надо.
Коля , добавлено 7.02.12, 23:57:16 
отредактируйте пост выше.3тья строка.
Автор, добавлено 8.02.12, 05:44:55 
Сейчас уезжаю, некогда. Вечером проверю.
Денис, добавлено 22.02.12, 23:29:30 
блин ребят, 3й раз читаю, нечего не понял =(
Михаил, добавлено 29.02.12, 12:34:24 
Ничего не понимаю, что куда писать и как это работает, что я в итоге получу должен увидеть и как это применить... перечитал уже раз 10... можно конкретный пример чтобы можно было скопировать вставить и увидеть что в итоге получилось... работа горит выручи автор
Автор, добавлено 29.02.12, 13:07:51 
Ну вот например массив из 5 ячеек:

var X: array[34..38] of Integer;

Он может хранить 5 ЦЕЛЫХ (Integer) чисел.

Обратиться к первому из них:

X[34];

Найти сумму всех чисел:


S:=0;
for i:=34 to 38 do
  S:=S+X[i];

Это пример на массивы.

Известно, что разделитель дробной части в системе может быть и точка и запятая. Пользователь вводит числа в Edit, и не знает заранее о том, что является разделителем в системе. Вы должны ему помочь. Делаем множество:

const
 D: set of Char = ['.', ','];

Далее в обработчике KeyPress компонента Edit пишем:

if Key in D
  then Key:=DecimalSeparator;

Таким образом, что бы пользователь ни ввёл, он получит нужный разделитель.

А записи вообще удобный вид данных. Он хранит ВСЕ значения, объединённые чем-либо одним. Например все сведения про человека можно хранить в одной структуре, такой как запись. Каждое отдельное сведение о нём храниться как ПОЛЕ такой записи. Поле от имени записи отделяется точкой:

type M = Record
  Family: String[20];
  Vozrast: Integer;
end;

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

var Man, Woman: M;

Присвоить значения этим переменным так:

Man.Family:='Иванов';
Woman.Family:='Иванова';
Man.Vozrast:=25;
Woman.Vozrast:=21;

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

var Stu: Array[1..100] of M;

Теперь задать фамилии и возраст всем студентам так:

Stu[1].Family:='Иванов';
Stu[1].Vozrast:='18';
Stu[2].Family:='Петров';
Stu[2].Vozrast:='19';
Stu[3].Family:='Сидоров';
Stu[3].Vozrast:='21';

И так далее.

Что непонятного?
СергейМ, добавлено 2.03.12, 09:41:14 
Доброго времени суток!
По последнему ответу: Как из группы ступентов (массив записей) выбрать, для работы, например студентов возрасту которых=18?
Спасибо.
Автор, добавлено 2.03.12, 09:59:54 
Это нужно ещё "владеть" таким оператором как условный и циклом for.

Перебираем в цикле все записи от первой до последней, смотрим поле Vozrast. Если устраивает, то переписываем их фамилии, ну например в компонент Memo построчно.

фор и:=1 то 100 до
  иф Stu[и].Возраст=18
    тхен Мемо1.Адд(Stu[и].Фамилия);

Можно целиком запись переписать, но тогда это тоже должен быть массив таких же записей.

СергейМ, добавлено 2.03.12, 10:23:31 
Это понятно! А непосредственно в записи можно делать выбор? Например запись с 5 полями храниться в типизированном файле, там 6 записей. Как выбрать нужную запись определяем по значению в поле? Все записи выгрузить в массив и там с ними работать?
СергейМ, добавлено 2.03.12, 10:42:22 
Еще вопрос по записям: такую структуру данных можно хранить в типизированном файле и брать их оттуда по запросам (похоже на базу данных)?
type TCommands=record
  Model: Strind[15];
  Blok: Strind[10];
  Dat1,Dat2,Dat3: byte;
end;
Model(модель) может быть много, у каждой Model может быть много Blok(блок), у каждого Blok может быть много Dat1,Dat2,Dat3. Все хранится в одном типизированном файле, нужно выбирать Dat1,Dat2,Dat3 по Model и Blok (в разных сочитаниях)? Может использовать "запись в записи", запись с вариантами?
Спасибо.
Автор, добавлено 2.03.12, 11:52:52 
Не, файл это не база данных. Придётся читать по одной записи, и её анализировать. Или считать всё в массив, и анализировать в массиве. Но это то же самое, только быстрее, если постоянно анализировать, и оперативной памяти достаточно.
СергейМ, добавлено 2.03.12, 12:22:27 
А как "ходить" по записям? Выгружать в массив, а в массиве обращаться к конкретному элементу?

Автор, добавлено 2.03.12, 12:26:09 
Зачем? Считываете очередную запись из файла, анализируете. И так далее.
Михаил, добавлено 2.03.12, 13:44:57 
Я всё равно ничего не понял))) Но в любом случае СПАСИБО! Что занимаешься вообще этим, помогаешь людям освоиться! Нашёл сайт, где мне легче всё даётся. Но вот хотел спросить, если ты помогаешь так людям, по аське или через почту можно как то связываться с тобой? Вопросы задавать? =)
Михаил, добавлено 2.03.12, 13:51:22 
Сразу спрошу, потому что нигде не могу найти инфу (если вопрос не уместен, удали):
Есть вот такой отрывок кода:
procedure TForm1.Button9Click(Sender: TObject);
var R1, R2, R :Real;
begin
 R1 := StrToFloat(Edit8.Text);
 R2 := StrToFloat(Edit9.Text);
if RadioButton1.Checked
 then R := R1 + R2
 else R := (R1 * R2) / (R1 + R2);
 Label8.Caption := 'Ñîïðîòèâëåíèå öåïè '+FloatToStr(RoundTo(R,-2))+' Îì';
end;
Как мне вместо вместо RadioButton1.Checked в данном случае использовать RadioGroup с двумя радио-кнопками
СергейМ, добавлено 2.03.12, 14:03:03 
Делаю так:
type
  TByte=record
  Byte3: Byte;
  Byte4: Byte;
  Byte5: Byte;

procedure TForm1.btn4Click(Sender: TObject);
var
  F: file of TByte;
  L: TByte;
  S: string;

begin
  AssignFile(F,ExtractFilePath(Application.ExeName)+'command.dat');
  Reset(F);
  while not Eof(F) do
  begin
  Read(F,L);
  if L.Byte3=$11 then
  S:=IntToHex(L.Byte3,2)+IntToHex(L.Byte4,2)+IntToHex(L.Byte5,2);
  mmo1.Lines.Add(S);
  end;
  CloseFile(F);
end;

Записей в файле 8, 1-я и последняя удовлетворяют условию в мемо выводятся согласно своему расположению в файле 1 запись повторяется до 7, на 8 месте вторая запись подходящая под условие.
 Вывод в мемо
110016
110016
110016
110016
110016
110016
11FFFF

В файле так:
110016
2300В2
12FF16
410015
000011
AA0016
11FFFF
Что не так в коде?
 
Автор, добавлено 2.03.12, 14:16:40 
В конструкции:

if L.Byte3=$11 then
  S:=IntToHex(L.Byte3,2)+IntToHex(L.Byte4,2)+IntToHex(L.Byte5,2);
  mmo1.Lines.Add(S);

к условию относится только вторая строка. Третья будет выполнена в любом случае. Поэтому и повторяется первая запись 7 раз. Правильно так:

if L.Byte3=$11 then
  begin
  S:=IntToHex(L.Byte3,2)+IntToHex(L.Byte4,2)+IntToHex(L.Byte5,2);
  mmo1.Lines.Add(S);
  end;
Автор, добавлено 2.03.12, 14:21:43 
К предыдущему вопросу.

А как без двух радиобуттонов? Условие одно - вариантов два, и либо радиобуттон включён, либо выключен. Естественно, нужен второй, иначе как выключить первый?

Кстати, радиогруппа необязательна, если она одна. Просто два компонента RadioButton.
Михаил, добавлено 2.03.12, 16:15:56 
Да я собирался и для второй радио-кнопки сделать...
Просто хочу понять как сделать это с радио-группой
Автор, добавлено 2.03.12, 17:36:41 
Ну, мне ваш замысел неизвестен....
СергейМ, добавлено 3.03.12, 16:37:00 
Автор спасибо! Следующий этап, эти записи надо загрузить в массив, при пробной загрузке, массив заполнился случайным образом, а не в порядке расположения записей??? Перед загрузкой в отладчике посмотрел значение переменной L: TByte; там есть значения, файл еще не открыт, откуда там беруться данные???
СергейМ, добавлено 3.03.12, 16:39:34 
Еще вопрос: Как сделать, чтобы количество элементов массива всегда было равно количеству записей в файле???
Автор, добавлено 3.03.12, 21:54:20 
Что-то я вас не пойму. Вроде всё правильно делаете, но такие вопросы...

Я конечно не телепат, но если описать переменную, то необязательно в ней сразу будет пустое значение - скорее, случайное.

Так что вы лучше текст программы тисните, а там посмотрим.
СергейМ, добавлено 4.03.12, 07:43:58 
Вопросов много. Читаю, читаю про Дельфи. А в некоторых основах "спотыкаюсь" скорей всего логика действия программы, переменной, массива .... не доходит. А массив думаю для загрузки записей нужен динамический. Текс программы выложу позже, пишу с другого компьютера.
Автор, добавлено 4.03.12, 08:35:53 
Давайте лучше сразу на почту andrzejx(a)yandex.ru архив с проектом. Так проще.
СергейМ, добавлено 4.03.12, 09:45:21 
У меня там проект проекта. Одни "намеки" на "хотелки"
Автор, добавлено 4.03.12, 09:56:36 
Тогда - на неясные вам самому вопросы скорее всего ответить не смогу.
СергейМ, добавлено 6.03.12, 11:54:24 
Автор сделал так: Все правильно? Заполнение массива можно сделать "красивее"?

procedure TForm1.btn4Click(Sender: TObject);
var
  F: file of TByte;
  L: TByte;
  S: string;
  K: Integer;
  MasCom: array of array of byte;

begin
  AssignFile(F,ExtractFilePath(Application.ExeName)+'command.dat'); // указываем файл
  Reset(F); //открываем для чтения
  K:=0;
  while not Eof(F) do //цикл до последней записи
  begin
  Read(F,L); //читаем запись
  if L.Byte3=$11 then //проверяем если соответствует выводим в мемо
  begin
  S:=IntToHex(L.Byte3,2)+IntToHex(L.Byte4,2)+IntToHex(L.Byte5,2);
  Inc(K);
  mmo1.Lines.Add(S);
  SetLength(MasCom,K,7); //определяем массив и заполняем его
  MasCom[K-1,0]:=$20;
  MasCom[K-1,1]:=$E7;
  MasCom[K-1,2]:=$23;
  MasCom[K-1,3]:=L.Byte3;
  MasCom[K-1,4]:=L.Byte4;
  MasCom[K-1,5]:=L.Byte5;
  MasCom[K-1,6]:=not (MasCom[K-1,0]+MasCom[K-1,1]+MasCom[K-1,2]
  +MasCom[K-1,3]+MasCom[K-1,4]+MasCom[K-1,5]);
  end;

  end;
  CloseFile(F);
  //вывод количества команд по условию
  lbl2.Caption:='Выбрано '+IntToStr(K)+' команд';
end;

Что хотел:
1) Хранение данных в виде записей в файле
2) Отбор нужных записей по значению поля
3) Вывод данных в массив, удобный для работы
4) Подсчет количества записей удовлетворяющих условию
Автор, добавлено 6.03.12, 12:59:35 
Если удовлетворяет вашей задаче, значит всё правильно.

Только не пойму, зачем хранить в массиве первые три значения, если они не меняются? Они и так хранятся в тексте этой самой программы! И следовательно,

MasCom[K-1,0]+MasCom[K-1,1]+MasCom[K-1,2]

равно константе, зачем каждый раз пересчитывать? Подсчитайте ручками и прибавляйте это значение.
СергейМ, добавлено 6.03.12, 16:15:00 
$20+$E7+$23=$12A Вы меня путаете! На выходе мне надо получить массив, в моем случае это четыре 7-ми байтные команды, у которых первые 3 байта одинаковы (постоянны), следующие 3 байта разные (хранятся в виде записей в файле), последний 7 байт расчетный (контрольная сумма первых шести байт)
Вот так
1) 20 E7 23 11 byte4 byte5 KS
2) 20 E7 23 11 byte4 byte5 KS
3) 20 E7 23 11 byte4 byte5 KS
4) 20 E7 23 11 byte4 byte5 KS

Автор, добавлено 6.03.12, 16:30:18 
Ясно. Но из программы же этого не видно, вот я и отреагировал. Но суммирование точно лишнее.
СергейМ, добавлено 6.03.12, 18:02:47 
Что еще заметил! Если указывал сначала значение второго элемента массива программа вылетала с ошибкой при нажатии на кнопку, оказалось все просто! Забыл, что нумерация в массиве начинается с нуля, вот поэтому K-1!
А суммирование нужно - это последний и обязательный элемент массива (по условию задачи, которую себе поставил). Хотя идея на счет константы вместо постоянных элементов в подсчете KS понравилась. Спасибо.
"Обкатаю" команды и приступлю к следующему этапу: подстановка из записи (256 полей или массивом сделать) на место значения в HEX виде = значения типа real
Автор, добавлено 6.03.12, 18:07:54 
Да и я как раз про MasCom[K-1,0]+MasCom[K-1,1]+MasCom[K-1,2].
БорисЧ, добавлено 23.03.12, 21:45:17 
если динамический массив сначала вызвать,заполнить,а потом когда становится ненужен использовать nil,то если далее понадобится вызвать одноименный массив через setlength то это будет пустой массив никак не связанный с ранее существовавшим ?
Автор, добавлено 23.03.12, 22:15:12 
Да, конечно. Новый массив будет указывать на другое место в памяти. Может, и на прежнее, но знать об этом мы не можем. Старые данные потеряны, по-любому.
БорисЧ, добавлено 23.03.12, 22:43:58 
Спасибо большое
Александр , добавлено 27.04.12, 08:43:24 
В общем не понимаю ничего, поясните пожалуйста.

У нас есть код
var N: Integer;
begin
  N := 65;
  A[5] := 101;
  A[N] := 165;
  A[N+3] := 200;
  B := A;
end;

N мы задана 65, а А[5]=101. Значит А[1]=97 ( т к элементы у нас маства с 1 до 100)
значит А[N]=65+97

в чем я не догоняю?

Спасибо
Автор, добавлено 27.04.12, 10:18:27 
Если A[1]=97, то A[2]=98 и так далее - A[n]:=n+96;

Отсюда
 A[n+3]:=n+3+96=n+99=65+99=164;откуда 200?
 A[65]:=65+96=161; откуда 165?

Но вообще я из этих условий ничего не "догоняю". Элементу массива можно присвоить любое значение. Я исходил из того, что закон его формирования в данном случае - прогрессия с шагом 1.
Александр, добавлено 28.04.12, 16:48:18 
"Я исходил из того, что закон его формирования в данном случае - прогрессия с шагом 1."

а как изменить прогрессию?
Александр, добавлено 28.04.12, 16:53:07 
откуда 200? откуда 165?

это у вас так написано
Автор, добавлено 28.04.12, 21:36:57 
Всё ясно. То что я написал, это просто демонстрация присваивания в массивах. Никакого закона формирования массива здесь нет. Любому элементу массива можно присвоить любое значение, а также присвоить массиву B значения массива A ЦЕЛИКОМ: B:=A; Закон формирования массива, о котором я писал в моём предыдущем сообщении, я обнаружил в ваших словах - именно вы пытались найти значение первого элемента, зная пятый. То что всё это вы взяли в моей статье, мне и в голову не пришло... Запамятовал, знаете ли.
Александр, добавлено 30.04.12, 19:38:34 
Понятно спасибо
Александр, , добавлено 30.04.12, 20:12:31 
а зачем в_имени_названия_типа Вы пишите букву T
Автор, добавлено 30.04.12, 20:23:26 
Это общепринятая практика, чтобы отличать тип от переменной:

var MyArray: Array of TMyArray;

TMyArray - тип

MyArray - переменная этого типа.

Но это дело добровольное, называйте как хотите хоть тип, хоть переменную.
Александр, добавлено 30.04.12, 20:49:07 
и не понятно что такое за зверь DecimalSeparator, хоть убейте
Александр, добавлено 30.04.12, 20:50:39 
без него не получится добавить в массив новых символов?
Автор, добавлено 30.04.12, 21:46:28 
Итак, если переменные и константы мы можем называть как хотим, то вот есть такая константа - DecimalSeparator. Если вы хотите быть программистом, то истинно говорю вам, что есть больше одного - вашего - компьютера на свете! И настройки системы Windows на этих компьютерах не на вас рассчитаны. А как раз наоборот, вы должны писать такие программы, чтобы они учитывали эти настройки. Так вот, есть, да-да, есть настройка символа, которым отделяют целую от дробной части в числе - или точка (.) или запятая (,). И константа DecimalSeparatord в любой системе будет иметь правильное значение такого разделителя. Кстати, в конце статьи есть описание, что такое DecimalSeparator. И сейчас я пишу для тех кто написанное плохо понял. Очень надеюсь, что данного объяснения будет достаточно, чтобы понять.
Ксения Дмитриевна, добавлено 15.06.12, 18:19:43 
А такая запись будет правильной
var A:array[1..m] of real,
если на форме содержаится edit с числовым значением для m? если нет, то как это реальзовать?
Автор, добавлено 15.06.12, 22:02:17 
Нет. При компиляции m будет не определена. Можете сами убедиться, что будет ошибка. Такая возможность есть для динамических массивов. Их размер определяется уже при работе программы.

Описание: var A: Array of Real;

Количество элементов: SetLength(А, m-1);

Минус один - так как нумеруются они от нуля.
Сергей, добавлено 12.01.14, 14:55:43 
Хочу определить множество состоящее из 17 чисел [5,12,14,33,39,143,1291,6711,6712,6714,6727,6730,6731,6732,6733,6734,6750]
type TMySet = set of ; // можете подсказать как правильно указать его тип?

Автор, добавлено 12.01.14, 16:17:26 
Если числа уже известны, можно задать как константу, тип допускается не указывать, просто перечисление в скобках. Более точно смогу ответить после 21 часа.
Антон, добавлено 8.02.14, 19:49:05 
"Выражение B := A означает, что каждый элемент массива B будет равен элементу с таким же индексом массива A."

А как можно такой фокус проделать, если мне нужно "приравнять" два массива из разных модулей?
Автор, добавлено 8.02.14, 20:45:09 
Для приравнивания двух массивов нужно, чтобы они были описаны как один тип. Неважно из каких модулей.
Антон, добавлено 8.02.14, 22:22:11 
Странно. У меня не сработала такая структура.
В Unit1 описал свойй тип так:
type MyType = array of TListBox;
В Unit2 - все то же самое (даже по буквам сравнил).
Далее задал в каждом из модулей переменную:
var ListBox: MyType;
Но на строку:
Unit2.Listbox:=ListBox;
Выдает ошибку несовместимости типов.
Ошибка вылезает как при использовании динамических, так и при использовании статических массивов.
P.S. Впринципе проблема решилась просто созданием массива только во втором модуле и обращением к нему из первого, но все же интересно понять, почему не сработал первый вариант.

Автор, добавлено 9.02.14, 05:36:25 
Это потому что типы описаны дважды. Неважно, что тип называется одинаково. Это вам так кажется, а компилятор видит два описания, и всё тут. Тип нужно описать в каком-либо одном модуле, а потом через него задавать переменные в других.
Антон, добавлено 9.02.14, 08:53:25 
Ну, да, предполагал такой вариант, но не был уверен, а переписывать то, что уже сделал как-то не очень хотелось. Спасибо за ответ.
Оставить комментарий:

Имя  

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

  





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