Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.75/16: Рейтинг темы: голосов - 16, средняя оценка - 4.75
21 / 21 / 2
Регистрация: 14.10.2009
Сообщений: 202
1

Немного изменить программу в Delphi Console. (Массивы)

14.10.2009, 17:14. Показов 3117. Ответов 7
Метки нет (Все метки)

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

Мое решение:

Код
program Project1;

{$APPTYPE CONSOLE}

uses
  RusConsole, StopOnEnd;

const
  n = 10;
var
  i, j, k, t: Integer;
  Povtor: Boolean;
  a: array [1..n] of Integer;
  b: array [1..n] of Integer;
begin
  {Ввод исходного массива}
  for i := 1 to n do begin
    write('a[', i, ']=');
    readln(a[i]);
  end;
  {Сравнение элементов исходного массива между собой}
  for i := 1 to n do
    begin
      t := a[i];
      Povtor := false;
      for j := 1 to n do
        if (a[j] = t) and (j <> i) then
          Povtor := true;
        if not Povtor then begin
          k := k + 1;
          b[k] := a[i];
        end;
    end;
  {Вывод результирующего массива b}
  writeln;
  for i := 1 to k do
    writeln('b[', i, ']=', b[i]);
end.
Преподаватель сказал, что решение правильно, но надо переделать, используя процедуры, функции и динамические массивы. Вот заготовка новой программы:

Код
program peredelat;

{$APPTYPE CONSOLE}

uses
  RusConsole, StopOnEnd;

type
  TDynIntArray = array of Integer;

var

function ReadArray: TDynIntArray;
var I:Integer;
begin

end;


procedure WriteArray(IntArray: TDynIntArray);
var I:Integer;
begin

end;


function Solve(IntArray: TDynIntArray): TDynIntArray;
begin

end;


begin
  A:=ReadArray;
  B:=Solve(A);
  WriteArray(B);
end.
Задача в целом несложная и надеюсь вы мне поможете.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.10.2009, 17:14
Ответы с готовыми решениями:

Delphi Console Массивы
Вот есть такая задача: Даны действительные числа a1, a2, ..., a2n. Эти точки определяют n...

Массивы в Delphi Console
Помогите с задачей: Даны действительные числа x1, x2, ... , xn, y1, y2, ... , yn, r1, r2, ... ,...

Массивы в Delphi (Console): Определить, является ли интервалом объединение этих интервалов
Даны действительные числа a1, a2, ... , a2n. Эти точки определяют n интервалов числовой оси (a1,...

Немного изменить программу
как сделать что бы программа СЧИТАЛА мои баллы??

7
13067 / 5853 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
15.10.2009, 18:51 2
Реализовал с динамическими массивами:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
program Project1;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils, Windows;
 
type
 
  //Тип динамического массива, состоящего из целых чисел.
  TArr  = array of Integer;
 
//Функция берёт строку в ANSI кодировке (Windows)
//и возвращает её перевод в OEM кодировку (DOS) в виде отдельной строки.
function AnsiToOem(aStr : String) : String;
begin
  Result := '';
  if Length(aStr) > 0 then begin
    SetLength(Result, Length(aStr));
    CharToOem(PChar(aStr), PChar(Result));
  end;
end;
 
//Процедура для ввода данных от пользователя через консоль.
//Создаётся динамический массив, содержащий все введённые пользователем числа.
function ReadArr : TArr;
var
  StrTmp      : String;
  i           : Integer;
  LengthOfArr : Integer;
begin
  //Начальная длина массива - 10 элементов.
  LengthOfArr := 10;
  //Выделяем память для массива.
  SetLength(Result, LengthOfArr);
 
  //Вывод текста в консоль.
  Writeln(AnsiToOem('Ввод элементов массива целых чисел.'));
  Writeln(AnsiToOem('Ввод каждого числа завершайте нажатием клавиши "ENTER"'));
  Writeln(AnsiToOem('Для завершения ввода массива нажмите клавишу "ENTER" без ввода числа.'));
  Writeln;
 
  //Последовательный ввод элементов массива через консоль.
  i := -1;
  repeat
    Writeln(AnsiToOem( 'Введите элемент с индексом: [ ' + IntToStr(Succ(i)) + ' ]' ));
    //Читаем строку, которую ввёл пользователь.
    Readln(StrTmp);
    //Если пользователь ввёл не пустую строку, то считаем, что введён очередной
    //элемент массива.
    if StrTmp <> '' then begin
      Inc(i);
      //Если требуется, расширяем массив.
      if i > Pred(LengthOfArr) then begin
        Inc(LengthOfArr, 10);
        SetLength(Result, LengthOfArr);
      end;
      Result[i] := StrToInt(StrTmp);
    end;
    //Ввод прекращаем, если пользователь ввёл пустую строку (нажал ENTER без ввода числа).
  until StrTmp = '';
  //Переустанавливаем длину массива в соответствии с количеством записанных в него значений.
  //Длина может быть и нулевая.
  SetLength(Result, Succ(i));
end;
 
//Выводит на консоль элементы массива aArr.
procedure WriteArr(aArr : TArr);
var
  i         : Integer;
begin
  if Length(aArr) = 0 then begin
    Writeln(AnsiToOem('Результирующий массив пуст.'));
    Exit;
  end;
  Writeln(AnsiToOem('Перечень элементов результирующего массива:'));
  for i := Low(aArr) to High(aArr) do begin
    if i > 0 then begin
       //Делаем так, чтобы в строку выводилось 10 значений и затем выполнялся
       //переход на следующую строку.
       if i mod 10 = 0 then
         Writeln(';')
       else
         Write('; ');
    end;
    //Выводим очередной элемент массива.
    Write(aArr[i]);
  end;
end;
 
//Функция проверяет, присутствует ли число aVal
//в массиве aArr. При проверке используются индексы, не превышающие aLastIndex.
function IsPresent(aArr : TArr; aLastIndex : Integer; aVal : Integer) : Boolean;
var
  i         : Integer;
begin
  Result := False;
  for i := Low(aArr) to aLastIndex do begin
    if aArr[i] = aVal then begin
      Result := True;
      Break;
    end;
  end;
end;
 
//Функция обработки массива.
//Возвращает динамический массив, состоящий из неповторяющихся элементов входного массива.
function ProcessArr(aArr : TArr) : TArr;
var
  i, j             : Integer;
begin
  //Выделяем память для результирующего массива.
  SetLength(Result, Length(aArr));
  j := -1;
  for i := Low(aArr) to High(aArr) do begin
    if not IsPresent(Result, j, aArr[i]) then begin
      Inc(j);
      Result[j] := aArr[i];
    end;
  end;
  //Корректируем длину результирующего массива в соответствии с количеством записанных
  //в него значений.
  SetLength(Result, Succ(j));
end;
 
var
  //Исходный массив.
  ArrSrc   : TArr;
  //Результирующий массив.
  ArrTrg   : TArr;
 
begin
 
  //Решаем задачу.
 
  //Ввод элементов исходного массива через консоль.
  ArrSrc := ReadArr;
  //Создание результирующего массива на основе значений из введённого массива.
  ArrTrg := ProcessArr(ArrSrc);
  //Вывод элементов результирующего массива на консоль.
  WriteArr(ArrTrg);
 
  //Освобождаем память, выделенную для массивов.
  Finalize(ArrSrc);
  Finalize(ArrTrg);
 
  Writeln;
  Writeln(AnsiToOem('Конец.'));
  Writeln('------------------------------');
  Writeln(AnsiToOem('Чтобы выйти нажмите ENTER.'));
 
  //Ждём нажатия ENTER.
  Readln;
end.
1
21 / 21 / 2
Регистрация: 14.10.2009
Сообщений: 202
15.10.2009, 20:43  [ТС] 3
Mawrat, Большое спасибо! Все работает, но по условию нужно сформировать новый массив из чисел которые входят в старый только по одному разу, то есть, если я правильно понял то при вводе такого массива:

1, 2, 3, 2, 4, 5, 5, 6, 7

Результат должен быть:

1, 3, 4, 6, 7

По твоей программе результат будет:

1, 2, 3, 4, 5, 6, 7.

Что в ней нужно изменить, чтобы она выдавала нужный результат? И нужно ли вообще менять в соответствии с условием?
0
13067 / 5853 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
15.10.2009, 22:46 4
А, да - немного подругому надо сделать. Я подругому условию сделал: "новый массив состоит из чисел, которые встречаются в исходном массиве ХОТЯБЫ один раз" - да это другое... Надо подправить...

Добавлено через 22 минуты
Теперь точно по тому условию, которое у тебя в задании:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
program Project1;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils, Windows;
 
type
 
  //Тип динамического массива, состоящего из целых чисел.
  TArr  = array of Integer;
 
//Функция берёт строку в ANSI кодировке (Windows)
//и возвращает её перевод в OEM кодировку (DOS) в виде отдельной строки.
function AnsiToOem(aStr : String) : String;
begin
  Result := '';
  if Length(aStr) > 0 then begin
    SetLength(Result, Length(aStr));
    CharToOem(PChar(aStr), PChar(Result));
  end;
end;
 
//Процедура для ввода данных от пользователя через консоль.
//Создаётся динамический массив, содержащий все введённые пользователем числа.
function ReadArr : TArr;
var
  StrTmp      : String;
  i           : Integer;
  LengthOfArr : Integer;
begin
  //Начальная длина массива - 10 элементов.
  LengthOfArr := 10;
  //Выделяем память для массива.
  SetLength(Result, LengthOfArr);
 
  //Вывод текста в консоль.
  Writeln(AnsiToOem('Ввод элементов массива целых чисел.'));
  Writeln(AnsiToOem('Ввод каждого числа завершайте нажатием клавиши "ENTER"'));
  Writeln(AnsiToOem('Для завершения ввода массива нажмите клавишу "ENTER" без ввода числа.'));
  Writeln;
 
  //Последовательный ввод элементов массива через консоль.
  i := -1;
  repeat
    Writeln(AnsiToOem( 'Введите элемент с индексом: [ ' + IntToStr(Succ(i)) + ' ]' ));
    //Читаем строку, которую ввёл пользователь.
    Readln(StrTmp);
    //Если пользователь ввёл не пустую строку, то считаем, что введён очередной
    //элемент массива.
    if StrTmp <> '' then begin
      Inc(i);
      //Если требуется, расширяем массив.
      if i > Pred(LengthOfArr) then begin
        Inc(LengthOfArr, 10);
        SetLength(Result, LengthOfArr);
      end;
      Result[i] := StrToInt(StrTmp);
    end;
    //Ввод прекращаем, если пользователь ввёл пустую строку (нажал ENTER без ввода числа).
  until StrTmp = '';
  //Переустанавливаем длину массива в соответствии с количеством записанных в него значений.
  //Длина может быть и нулевая.
  SetLength(Result, Succ(i));
end;
 
//Выводит на консоль элементы массива aArr.
procedure WriteArr(aArr : TArr);
var
  i         : Integer;
begin
  if Length(aArr) = 0 then begin
    Writeln(AnsiToOem('Результирующий массив пуст.'));
    Exit;
  end;
  Writeln(AnsiToOem('Перечень элементов результирующего массива:'));
  for i := Low(aArr) to High(aArr) do begin
    if i > 0 then begin
       //Делаем так, чтобы в строку выводилось 10 значений и затем выполнялся
       //переход на следующую строку.
       if i mod 10 = 0 then
         Writeln(';')
       else
         Write('; ');
    end;
    //Выводим очередной элемент массива.
    Write(aArr[i]);
  end;
end;
 
//Функция проверяет, присутствует ли число aVal
//в массиве aArr. При проверке используются индексы, не превышающие aLastIndex.
function IsOnePresent(aArr : TArr; aIndex : Integer) : Boolean;
var
  i         : Integer;
begin
  Result := True;
  for i := Low(aArr) to High(aArr) do begin
    if (i <> aIndex) and (aArr[i] = aArr[aIndex]) then begin
      Result := False;
      Break;
    end;
  end;
end;
 
//Функция обработки массива.
//Возвращает динамический массив, состоящий из тех элементов, которые только
//по одному разу присутствуют во входном массиве.
function ProcessArr(aArr : TArr) : TArr;
var
  i, j             : Integer;
begin
  //Выделяем память для результирующего массива.
  SetLength(Result, Length(aArr));
  j := -1;
  for i := Low(aArr) to High(aArr) do begin
    if IsOnePresent(aArr, i) then begin
      Inc(j);
      Result[j] := aArr[i];
    end;
  end;
  //Корректируем длину результирующего массива в соответствии с количеством записанных
  //в него значений.
  SetLength(Result, Succ(j));
end;
 
var
  //Исходный массив.
  ArrSrc   : TArr;
  //Результирующий массив.
  ArrTrg   : TArr;
 
begin
 
  //Решаем задачу.
 
  //Ввод элементов исходного массива через консоль.
  ArrSrc := ReadArr;
  //Создание результирующего массива на основе значений из введённого массива.
  ArrTrg := ProcessArr(ArrSrc);
  //Вывод элементов результирующего массива на консоль.
  WriteArr(ArrTrg);
 
  //Освобождаем память, выделенную для массивов.
  Finalize(ArrSrc);
  Finalize(ArrTrg);
 
  Writeln;
  Writeln(AnsiToOem('Конец.'));
  Writeln('------------------------------');
  Writeln(AnsiToOem('Чтобы выйти нажмите ENTER.'));
 
  //Ждём нажатия ENTER.
  Readln;
end.
Если надо, чтобы были приняты меры по увеленчению быстродействия программы, то можно исходный массив сделать объявленным, как глобальная переменная. - Тогда он (все его элементы) не будет каждый раз передаваться в функции в качестве парметра (через стек). Здесь массив пользователь вводит и предполагается, что он небольшой. Для случаев, когда имеем дело с большими массивами - их или как глобальные надо оформлять - если код простой. Либо в более сложных задачах - в процедуры надо передавать только ссылки (указатели) на массивы.
Если что-то из этого надо - то лучше как глобальный оформить входной массив. Через ссылки (указатели) - я могу сделать, но читать такую программу будет труднее.

Добавлено через 13 минут
И еще там в коде старый комментарий для функции IsOnePresent() остался. Теперь его надо поменять на:
"Функция возвращает True, если число aArr[aIndex] встречается в массиве aArr только один раз. В остальных случаях - False."
1
21 / 21 / 2
Регистрация: 14.10.2009
Сообщений: 202
15.10.2009, 23:40  [ТС] 5
Все исправил. Все работает. Еще раз большое спасибо.
0
simpletest
29.11.2009, 17:57 6
Если надо, чтобы были приняты меры по увеленчению быстродействия программы, то можно исходный массив сделать объявленным, как глобальная переменная. - Тогда он (все его элементы) не будет каждый раз передаваться в функции в качестве парметра (через стек).
В отличие от обычных массивов (массивов фиксированного размера) динамические в Delphi - ссылочный тип данных, так что содержимое массива в стек не передается, не вводите людей в заблуждение.
Следующий код это вполне доказывает:

Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
program Project1;
{$APPTYPE CONSOLE}
 
type
  TIntArray=array of Integer;
 
procedure Test(TestData: TIntArray);
begin
  TestData[1]:=100;
end;
 
var
  TestData: TIntArray;
 
begin
  SetLength(TestData, 3);
  TestData[0]:=0;
  TestData[1]:=1;
  TestData[2]:=2;
  Test(TestData);
  WriteLn(TestData[1]);       // 100
  WriteLn(SizeOf(TestData));  // 4
  ReadLn;
end.
Да и в случае с обычными массивами достаточно описать формальный параметр функции как параметр, передаваемый по ссылке (т.е. c var), и указатели не нужны.

А за глобальные переменные надо бить по рукам.
13067 / 5853 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
29.11.2009, 19:28 7
Цитата Сообщение от simpletest Посмотреть сообщение
В отличие от обычных массивов (массивов фиксированного размера) динамические в Delphi - ссылочный тип данных, так что содержимое массива в стек не передается, не вводите людей в заблуждение.
Ты ошибаешься. Динамические массивы хоть и ссылочный тип, но в процедуры передаются не как ссылки а полностью со всеми своими данными через стек! Это конечно странно, но так реализовали разработчики Delphi.
Проверь сам - в Delphi в отладчике есть окно для просмотра стека. Передай в роцедуру динамический массив и увидишь, как в стек вывалятся все его данные!
Это не радует, ясно дело, но так реализован механизм. Именно благодаря этому внутри процедур работают такие функции как Low() и High().
Тем не мнее передавать по ссылки динамические массивы можно. Для этого надо в процедуру кидать указатель на динамический массив. Т. е. это как бы получится указатель на указатель - так делать можно. И я так делаю в своих прогах.

Добавлено через 4 минуты
Цитата Сообщение от simpletest Посмотреть сообщение
Да и в случае с обычными массивами достаточно описать формальный параметр функции как параметр, передаваемый по ссылке (т.е. c var), и указатели не нужны.
А за глобальные переменные надо бить по рукам.
Simpletest, а этот твой коммент здесь вообще не к месту. Нет смысла в этой проге заморачивать код. Вообще, если бы я тут приводил коды в своём привычном стиле (как я на работе пишу) - их здесь мало бы кто понимал (из студентов и начинающих).
0
13067 / 5853 / 1705
Регистрация: 19.09.2009
Сообщений: 8,807
30.11.2009, 11:56 8
Произвёл раскопку в отношении динамических массивов.
Меня смутила вот эта часть в справке Delphi 7:
XML
1
2
3
4
5
6
7
When you pass an array as an open array value parameter, the compiler creates a local copy of the array
within the routine's stack frame. Be careful not to overflow the stack by passing large arrays.
 
The following examples use open array parameters to define a Clear procedure that assigns zero to each
element in an array of reals and a Sum function that computes the sum of the elements in an array of reals.
 
procedure Clear(var A: array of Real);
Здесь имеется предупреждении о копировании данных массива в стек.
Но на самом деле, понимать надо, видимо, так.
Если в процедуре объявлен параметр вот так:
procedure Proc1(Arr: array of Integer);
то через этот параметр можно передавать процедуре не только динамические массивы, но и статические. При этом, статический массив скопируется в стек. А динамический будет передан, всё-же по ссылке. Т. е. данные динамического массива не попадют в стек.
А если объявить так:
procedure Proc2(var Arr: array of Integer);
То и статический массив не станет копироваться в стек. Т. е. передача произойдет по ссылке.
В инете нашёл очень полезную статью о дин. массивах и стороках:
Рекомендую всем прочитать.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.11.2009, 11:56

Заказываю контрольные, курсовые, дипломные работы и диссертации здесь.

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

нужно немного изменить программу)
подскажите, пожалуйста, что нужно изменить в программе, чтобы, например, вместо (5) + i(2) было 5 +...

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

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.