Технический форум

Технический форум (http://www.tehnari.ru/)
-   Помощь студентам (http://www.tehnari.ru/f41/)
-   -   Паскаль. Обработка массива. (http://www.tehnari.ru/f41/t31014/)

Montespan 10.12.2009 22:12

Паскаль. Обработка массива.
 
Изменить таблицу, заменив каждый ее элемент на сумму исходных элементов, лежащих не выше и не правее его, а также не ниже и не левее.

Подскажите, пожалуйста,
1) имеет ли смысл в данной задаче использовать рекурсию?
2) начать обработку таблицы лучше всего с конца? или с начала?
ведь результат получится разным.

Montespan 19.12.2009 16:26

Вложений: 1
При решении нельзя создавать таблицу таких же размеров, массив должен быть динамическим.
Примерное решение: Вложение 140044
подсчитать сумму элементов в массиве, а значения элементов новой таблицы посчитать как (сумма элементов исходной матрицы - значение самого элемента - сумма элементов, лежащих "выше и правее" - сумма элементов, лежащих "ниже и левее" ). Создать 2 одномерных массива, первый- для подсчета суммы элементов по столбцам, второй- для подсчета суммы элементов по строкам.
При реализации этого алгоритма возникают проблемы- не понимаю, как правильно написать это на паскале, использую динамику.

Long Cat 19.12.2009 16:57

1)Использовать рекурсию здесь нежелательно. Слишком сложно будет уместить в голове происходящее.
2)На мой взгляд, считать нужно так, чтобы полученные значения не вовлекались в процесс счета.
3)Иногда стоит создать решение типа "лишь бы работало" - без ограничений задачи, а затем, как следует на него насмотревшись, построить решение по всем правилам.

Montespan 19.12.2009 17:57

Long Cat, спасибо.
Без динамики написать получилось, но возникло несколько вопросов.
1)Если в функции массив входно-выходной параметр, как правильно его описать? в var?
2)Если использовать дополнительно одномерный динамический массив, выделять для него память нужно в самой функции?
И вообще при работе с динамическими массивами освобождать память под них достаточно один раз?

Montespan 19.12.2009 19:58

Код:

type
TInt=integer;
MyType=real;
Matrix=array[1..1] of MyType;
PMatrix=^Matrix;      {cтроки}
MyArray=array[1..1] of PMatrix;
PMyArray=^MyArray;        {массив указателей на строки}
{-------------------------------------------------}
Function Summa( a:PMyArray; c,d,n,m: TInt): MyType;
{вх.параметр a-динамический двумерный массив, c,m-счетчики по столбцам, n,d- по строкам, функция считает сумму элементов, лежащих не выше и не правее и не ниже и не левее данного}
var i,j: TInt;
s: MyType;
begin
s:=0;
for i:=1 to d do
 for j:=1 to c do
  s:=s+a^[i]^[j];
for i:=d to n do
 for j:=c to m do
  s:=s+a^[i]^[j];
summa:=s-2*a^[d]^[c];
end;
{------------------------------}
Function Tabl (a:PMyArray; n,m: TInt): Boolean;
var b: Matrix; {дополнительный массив для хранения новых элементов}
c,d,e,i,j: TInt;
begin
if(m<0) or (n<0) or (a=nil) then
Tabl:=false
else
begin
 for c:=1 to m do
  begin
  for d:=1 to n do
    b[m*(d-1)+c]:=summa(a,c,d,n,m);
    end;
 begin
  for i:=1 to n do
  begin
  for j:=1 to m do
    begin
    for e:=1 to m*n do
    a^[i]^[j]:=b[e];
    end;
  end;
end;
end;

Выдает синтаксическую ошибку во второй функции на этом месте for j:=1 to m do
Подскажите, пожалуйста, что неверно?

Vladimir_S 19.12.2009 21:20

Цитата:

Сообщение от Montespan (Сообщение 271991)
Выдает синтаксическую ошибку во второй функции на этом месте for j:=1 to m do
Подскажите, пожалуйста, что неверно?

Я не вникал в Вашу программу, тем более, что с динамическими переменными "плаваю", но у Вас имеется нестыковка в количестве begin - end ("begin" на 1 больше). И вообще, расстановка этих т.н. "операторных скобок" вызывает некоторые недоумения. Какой, например, смысл в том "begin", который идет сразу после строк
b[m*(d-1)+c]:=summa(a,c,d,n,m);
end; ?

Long Cat 20.12.2009 00:38

Цитата:

Без динамики написать получилось, но возникло несколько вопросов.
1)Если в функции массив входно-выходной параметр, как правильно его описать? в var?
2)Если использовать дополнительно одномерный динамический массив, выделять для него память нужно в самой функции?
И вообще при работе с динамическими массивами освобождать память под них достаточно один раз?
Чтобы передавать массив функции в качестве параметра, правильнее всего использовать передавать указатель на массив. В противном случае, программа при каждом вызове функции будет копировать в стек весь массив - либо стека не хватит, либо программа будет работать очень долго.

Про динамические переменные:
Здесь нужно соблюдать строгий порядок работы:
1) Выделяем память.
2) Работаем.
3) Освобождаем память.
Т. е. на каждую операцию new должна в процессе работы должна вызываться соответствующая dispose. (Количество вызовов new и dispose во время работы программы должно совпадать).

При форматировании текста программы удобно придерживаться таких правил:
1) begin и парный ему end должны быть напечатаны с одной горизонтальной позиции - тогда меньше придется искать синтаксических ошибок и проще разбирать код.
2) Даже если тело цикла или условного оператора состоит из одной команды, стоит поставить begin и end - лечит огромное количество ошибок.

И да, чтобы получить быстрый ответ на вопрос "компилятор там-то выдает ошибку", стоит приводить полный и оригинальный текст сообщения об ошибке.

Vladimir_S 20.12.2009 08:47

Цитата:

Сообщение от Long Cat (Сообщение 272100)
При форматировании текста программы удобно придерживаться таких правил:
1) begin и парный ему end должны быть напечатаны с одной горизонтальной позиции - тогда меньше придется искать синтаксических ошибок и проще разбирать код.
2) Даже если тело цикла или условного оператора состоит из одной команды, стоит поставить begin и end - лечит огромное количество ошибок.


С п.1 соглашаюсь абсолютно - но увы, новички народ упрямый.
А вот п.2 представляется весьма и весьма спорным. Во всяком случае, я этого правила никогда не придерживаюсь. Потому что, с моей точки зрения, например, заполнять матрицу единицами лучше (читабельнее) так:
Код:

for i:=1 to N do
 for j:=1 to M do
  A[i,j]:=1;

чем так:
Код:

for i:=1 to N do
 begin
  for j:=1 to M do
  begin
    A[i,j]:=1;
  end;
 end;

А Montespan как раз и наворотила столько этих операторных скобок, что в них же малость и утонула.
Но это, конечно, дело вкуса и стиля. Ни в коем случае не пытаюсь свою точку зрения кому бы то ни было навязать.

Long Cat 20.12.2009 08:57

На вкус и цвет... :-)

Montespan 20.12.2009 11:20

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

program tablica;
uses crt;

type
  TInt
=integer;
  
MyType=real;
  
Matrix=array[1..1of MyType;
  
PMatrix=^Matrix;
   {
cтроки}
  
MyArray=array[1..1of PMatrix;
  
PMyArray=^MyArray;
    {
массив указателей на строки}
  
TF=file of MyType;
  
TStr=string;

const 
k=50;

var
  
n,m,i,j,key,z,q:TInt;
  
a:PMyArray;
  
IOR:word;
  
flag1flag2boolean;
  
fTF;
  
nameTstr;

{------------------------------------}
Function 
GetMemory(m,nTInt; var aPMyArray):boolean;
{
Функция выделяет память под динамический массиввходные параметры:
 
mстолбцыnстрокиадвумерный динамический массив}
var  
iTInt;
begin
  
Выделяем память под указатели на "строки" }
  
getmem(a,  n*sizeof(PMatrix));
  if(
a<>nilthen
    begin
      
for i:= 1 to n do
         
getmem(a^[i], m*sizeof(MyType));
      
GetMemory:=true;
    
end
    
else
      
GetMemory:=false;
end;
{--------------------------------}
Function 
Summaa:PMyArrayc,d,n,mTInt): MyType;
{
функция считает для каждого элемента сумму элементов,
 
стоящих не выши и не правееа также не ниже и не левее его,
 
cсчетчик по столбцамd-счетчик по строкам}
var 
i,jTInt;
    
sMyType;
begin
  s
:=0;
  for 
i:=1 to d do
    for 
j:=1 to c do
      
s:=s+a^[i]^[j];
  for 
i:=d to n do
    for 
j:=c to m do
      
s:=s+a^[i]^[j];
  
summa:=s-2*a^[d]^[c];
end;
{------------------------------}
Function 
Tabl (var a:PMyArrayn,mTInt): Boolean;
{
функция присваивает элементам одномерного массива b
 значения функции Summa
затем переприсваивает их массиву а,
  
тем самым изменяя его}
var
  
bPMatrix;
  
c,d,e,i,jTInt;
begin
  
if(m<0) or (n<0) or (a=nil)
    
then
      Tabl
:=false
    
else
      
begin
        Tabl
:=true;
    
GetMem(bn*sizeof(MyType));
        for 
c:=1 to m do
          
begin
            
for d:=1 to n do
              
b^[m*(d-1)+c]:=summa(a,c,d,n,m);
            for 
i:=1 to n do
              for 
j:=1 to m do
                for 
e:=1 to m*do
                  
a^[i]^[j]:=b^[e];
          
end;
      for 
i:=1 to n do
      
begin
        
for j:=1 to m do
          
write(a^[i]^[j]:6:2);
        
writeln;
      
end;
      
readln;
    
FreeMem(bn*sizeof(MyType));
      
end;
end;
{---------------------------------------------------------------}
Procedure FreeMemory(var a:PMyArray;n,m:TInt);
var 
i:TInt;
begin
  
for := 1 to m do
    
freemem(a^[i], m*sizeof(MyType));
  
freemem(an*sizeof(PMatrix));
end;
{--------------------------------}
Procedure Make_Tabl(n,mTInt; var aPMyArray);
var
  
i,jTInt;
  
ffile of MyType;
  
tempMyType;
begin
  n
:=-1;
  
m:=-1;
  {
$I-}
  
repeat
    clrscr
;
    
writeln ('Введите длину таблицы.  ');
    
readln (n);
    
IOR:=ioresult;
  
until (IOR=0) and (n>=1);
  
repeat
    clrscr
;
    
writeln ('Введите ширину таблицы. ');
    
readln (m);
    
IOR:=ioresult;
  
until (IOR=0) and (m>=1);
  {
$I+}

  if(
GetMemory(m,n,a)=true)
  
then
    begin
      
{$I-}
      
repeat
        clrscr
;
        
writeln ('Выберете способ ввода значений таблицы');
        
writeln ('1- если хотите выполнить ввод с клавиатуры');
        
writeln ('2- для случайного вводa');
        
writeln ('3- для чтения из файла');
        
readln (z);
        
IOR:=ioresult;
      
until (IOR=0) AND ((z=1) or (z=2) or (z=3));
      {
$I-}
      if 
z=1
      then
        begin
          
for i:=1 to n do
              for 
j:=1 to m do
                
begin
                  
{$I-}
                  
repeat
                    write
('Введите значение ячейки таблицы a[',i,',',j,'] ');
                    
readln (a^[i]^[j]);
                    
IOR:=ioresult;
                    if 
IOR<>0 THEN WriteLn('Неверное значение!');
                  
until IOR=0;
                  {
$I+}
                
end;
        
end;

      if 
z=2
      then
        begin
          randomize
;
          for 
i:=1 to n do
            for 
j:=1 to m do
              
a^[i]^[j]:=random(k);
        
end;

      if 
z=3
      then
        begin
          
{$I-}
          
repeat
            writeln
('Введите полное имя файла: ');
            
readln(name);
            
assign(f,name);
            
reset(f);
            
IOR:=IOResult;
            if 
IOR<>0 then writeLn('Неверное имя файла!');
          
until IOR=0;
          {
$I+}
          
read(f,temp); {строки}
          
n:=trunc(temp);
          
read(f,temp); {cтолбцы}
          
m:=trunc(temp);
            
FreeMemory(a,n,m);
          if (
GetMemory(m,n,a)=true)
          
then
            begin
              
for i:=1 to n do
                for 
j:=1 to m do
                  
begin
                  
{$I-}
                    
read(fa^[i]^[j]);
                    
IOR:=IOResult;
                  {
$I+}  
                    if 
IOR<>0
                    then
                      begin
                        writeLn
('Неверное содержание файла. Нажмите Enter для выхода.');
                        
readLn;
                        
close(f);
                        
halt; {завершение работы программыкод завершения 0}
                      
end;
                  
end;    
                  
close(f);
            
end
          
else
            
writeln('Произошла ошибка.');
        
end
      
else
        
writeln('Error!');
    
end;
end;
{-------------------------------------------}
begin
  repeat
  clrscr
;
  
writeln('Меню');
  
writeln('1.Создание таблицы.');
  
writeln('2.Обработка таблицы и вывод результата.');
  
writeln('3.Сохранение файла.');
  
writeln('4.Выход из программы.');
  
readln(key);
  case 
key of
  1
:
  
begin
    Make_Tabl
(n,m,a);
    
flag1:=true;
  
end;
  
2:
  if 
flag1 then
    begin
      Tabl
(a,m,n);
    
end;
    
end;
  
until key=4;
end



Часовой пояс GMT +4, время: 08:34.

Powered by vBulletin® Version 4.5.3
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.