Передача массива в функцию или процедуру

Задачи из Урока 15

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

a[1] = 1;
a[2] = 2;
a[3] = 3;

превращается в:

a[0] = 1;
a[1] = 2;
a[2] = 3;

Так происходит и в этом коде. В процедуре происходит смещение номеров ячеек. Первое
значение вообще пропадает, а последнее значение повторяется в двух последних ячейках :

type
  randArr = array[1..7] of integer;
var
  r:randArr;
  i:integer;

procedure moveZero(var r: array of integer;k,k2:integer);
var j:integer;
  begin

    for j:= k2 to 6 do
      r[j]:= r[j + 1];
    r[high(r)]:= 0;
    for j:= k to 6 do
      r[j]:= r[j + 1];
    r[high(r)]:= 0;
  end;
function chekArr(funArr:randArr):integer;
var n,m:integer;
begin
  for n:= 1 to 7 do
    begin
      m:= n + 1;
    while ((m>=1)and(m<=7)) do
      //begin
      if funArr[n] = funArr[m] then
        begin
          moveZero(funArr,n,m);
          m:= n + 1;
        end
        else
          m += 1;
      //end;
    end;
end;
BEGIN
  r[1]:= 2;
  r[2]:= 26;
  r[3]:= 12;
  r[4]:= 2;
  r[5]:= 22;
  r[6]:= 11;
  r[7]:= 18;
  randomize();
  //for i:= low(r) to high(r) do
    //r[i]:= 1 + random(15);
  for i:= low(r) to high(r) do
    write(r[i],'|');
  writeln();
  chekArr(r);
  for i:= low(r) to high(r) do
    write(r[i],'|');
  readln;
END. 

В этом коде была похожая ситуация, но я исправил проблему,
а как не понял :

var i:integer;
a:array [1..7] of integer;
function fff(a:array of integer):string;
var c:array [1..7] of integer;
i,j,n,m:integer; s:string;
begin
  c:=a;
  for i:= low(c) to high(c) do
  begin
    if (s = 'NE unikalnii') then
      break
    else
    begin
      for j:= i+1  to high(c) do
      begin
        if c[i] = c[j] then
        begin
          s:= 'NE unikalnii';
          break;
        end;
      end;
    end;
  end;
  if (s <> 'NE unikalnii') then
    s:= 'unikalnii';
  result:= s;
end;
BEGIN
  randomize();
  for i:=low(a) to high(a) do
    a[i]:= 1 + random(15);
  for i:=low(a) to high(a) do
    write(a[i],'|');
  writeln();
  writeln('massiv - ', fff(a));
  readln();
END.  

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

vedro-compota's picture

В этом коде была похожая ситуация, но я исправил и не понял как :

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

Кстати, вот такой код в вашем случае:

for j:= i+1  to high(c)

- не выведет последний элемент массива (т.е. сокрее всего это не полное исправление проблемы)

Но в целом вопрос понятен, подготовлю разбор

_____________
матфак вгу и остальная классика =)

Второй код нормально работает. Выложил его как пример рабочего для сравнения
(может ни к чему).Просто с ним было то же, что и с первым. Что исправил не смогу
сказать потому как с ним бился дня2)) методом "тыка" и с отладчиком не понимая
до конца в чем причина.
Первый код работает если нет одинаковых значений в массиве. Если есть
одинаковые числа, что то ломается. Выяснил что в процедуре идёт смещение
номеров ячеек массива и обратился за помощью. Хочется понимать, а не применять
"научный тык"))).

for j:= i+1  to high(c) do

Такая строка тоже получилась после ошибок, из за которых
не запускалась программа.
Изначально было скорее всего так :

for j:= c[i + 1] to high (c) do

Потом как- нибудь:

for j:= low(c[i + 1] to high(c) do

В общем оставил, как работать стало. Я ж учусь)

В этом коде на строке 40( в сигнатуре функции ) при передаче массива
с именем "с" массив не меняется. А с именем "а" происходит смещение
и массив начинается с [0].

var i:integer;
a:array [1..4] of integer;

procedure moveZero(var a: array of integer; k,k2,k3,k4:integer);
var j:integer;r:array[1..4] of integer;
begin
    r:= a;
    if k4 = 4 then
      r[high(r)]:= 0;
    if k3 = 4 then
      r[high(r)]:= 0;
    if k2 = 4 then
      r[high(r)]:= 0;
    if (k4<>0) then
    begin
      for j:= k4 to 3 do
        r[j]:= r[j + 1];
      r[high(r)]:= 0;
    end
        else if k3<> 0 then
        begin
          for j:= k3 to 3 do
            r[j]:= r[j + 1];
          r[high(r)]:= 0;
        end
            else if k2 <>0 then
            begin
              for j:= k2 to 3 do
                r[j]:= r[j + 1];
              r[high(r)]:= 0;
            end
                else
                begin
                for j:= k to 3 do
                  r[j]:= r[j + 1];
                r[high(r)]:= 0;
                end;
end;

function fff( c:array of integer):integer;
var //c : array [1..4] of integer;
i,j,n,m,k,k2,k3,k4:integer;
begin
 // c:=a;
  k:= 0;
      k2:= 0;
      k3:= 0;
      k4:= 0;
  for i:= low(c) to high(c) do
  begin
    if k<>0 then
      moveZero(a,k,k2,k3,k4)
    else
    begin
      for j:= i+1  to high(c) do
      begin
        if c[i] = c[j] then
        begin
          if k = 0 then
          begin
            k:= i;
            k2:= j;
          end
          else if k3 = 0 then
            k3 := j
            else if k4 = 0 then
              k4 := j;
        end;
      end;
    end;
  end;
end;

BEGIN
 { randomize();
  for i:=low(a) to high(a) do
    a[i]:= 1 + random(15);}
  a[1]:= 1;
  a[2]:= 2;
  a[3]:= 3;
  a[4]:= 1;
  for i:=low(a) to high(a) do
    write(a[i],'|');
  fff(a);
  writeln();
  for i:=low(a) to high(a) do
    write(a[i],'|');
  readln();
END.  

В этом коде на строке 40( в сигнатуре функции ) при передаче массива
с именем "с" массив не меняется. А с именем "а" происходит смещение
и массив начинается с [0].

Но в целом вопрос понятен, подготовлю разбор

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

type tenArr = array [1..10] of integer;
var i,j,k,n,m:integer;
  t: tenArr;
BEGIN
  randomize();
  i:= 1;
  while ((i>=1) and (i<=10)) do
  begin
    n:= random(20);
    m:= 0;
    for j:= 1 to i do
      if t[j] = n then
        begin
          m:= 1;
          writeln('Znacheniya povtoralis :',n);
          break;
        end;
      if m = 0 then
      begin
        t[i]:= n;
        i += 1;
      end;
  end;
  for i:= low(tenArr) to high(tenArr) do
    write(t[i],'|');
  readln;
END. 

Зачем строка 3? Почему в строке 20 нельзя написать так :

tenArr[i] := n;

Удалил вопрос

vedro-compota's picture

Разбор проблемы по потере индекса добавлен в 15 урок - немного примеров в тексте + два видео: https://fkn.ktu10.com/?q=node/8614

Видео дополнительно сюда скопирую:

  • Разбор проблемы "потери индексов" при передаче массива в подпрограмму: https://youtu.be/K2zpmZtoYWk
  • Еще про работу с индексами и про выход за границы массивов: https://youtu.be/fZqNMseOPow

Основной вопрос про индексы это должно закрыть, остальные вопросы если остануться - оформляем отдельно

_____________
матфак вгу и остальная классика =)