Технический форум
Вернуться   Технический форум > Программирование > Форум программистов > Помощь студентам


Ответ
 
Опции темы Опции просмотра
Старый 10.12.2009, 22:12   #1 (permalink)
Montespan
Member
 
Регистрация: 01.11.2009
Сообщений: 13
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 10
По умолчанию Паскаль. Обработка массива.

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

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

Старый 10.12.2009, 22:12
Helpmaster
Member
 
Аватар для Helpmaster
 
Регистрация: 08.03.2016
Сообщений: 0

Рекомендую вам сразу пользоваться поиском схожих тем на форуме

Паскаль. Обработка натурального числа
Турбо Паскаль или Фри Паскаль. Задание по теме Типизированный файл
Обработка txt
Обработка матриц. Паскаль
Сортировка массива

Старый 19.12.2009, 16:26   #2 (permalink)
Montespan
Member
 
Регистрация: 01.11.2009
Сообщений: 13
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 10
По умолчанию

При решении нельзя создавать таблицу таких же размеров, массив должен быть динамическим.
Примерное решение: cc9c4254ae0b.jpg
подсчитать сумму элементов в массиве, а значения элементов новой таблицы посчитать как (сумма элементов исходной матрицы - значение самого элемента - сумма элементов, лежащих "выше и правее" - сумма элементов, лежащих "ниже и левее" ). Создать 2 одномерных массива, первый- для подсчета суммы элементов по столбцам, второй- для подсчета суммы элементов по строкам.
При реализации этого алгоритма возникают проблемы- не понимаю, как правильно написать это на паскале, использую динамику.
Montespan вне форума   Ответить с цитированием
Старый 19.12.2009, 16:57   #3 (permalink)
Long Cat
Banned
 
Регистрация: 01.09.2009
Сообщений: 4,396
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 2544
По умолчанию

1)Использовать рекурсию здесь нежелательно. Слишком сложно будет уместить в голове происходящее.
2)На мой взгляд, считать нужно так, чтобы полученные значения не вовлекались в процесс счета.
3)Иногда стоит создать решение типа "лишь бы работало" - без ограничений задачи, а затем, как следует на него насмотревшись, построить решение по всем правилам.
Long Cat вне форума   Ответить с цитированием
Старый 19.12.2009, 17:57   #4 (permalink)
Montespan
Member
 
Регистрация: 01.11.2009
Сообщений: 13
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 10
По умолчанию

Long Cat, спасибо.
Без динамики написать получилось, но возникло несколько вопросов.
1)Если в функции массив входно-выходной параметр, как правильно его описать? в var?
2)Если использовать дополнительно одномерный динамический массив, выделять для него память нужно в самой функции?
И вообще при работе с динамическими массивами освобождать память под них достаточно один раз?
Montespan вне форума   Ответить с цитированием
Старый 19.12.2009, 19:58   #5 (permalink)
Montespan
Member
 
Регистрация: 01.11.2009
Сообщений: 13
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 10
По умолчанию

Код:
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
Подскажите, пожалуйста, что неверно?

Последний раз редактировалось Long Cat; 20.12.2009 в 00:20
Montespan вне форума   Ответить с цитированием
Ads

Яндекс

Member
 
Регистрация: 31.10.2006
Сообщений: 40200
Записей в дневнике: 0
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 55070
Старый 19.12.2009, 21:20   #6 (permalink)
Vladimir_S
Специалист
 
Регистрация: 27.08.2008
Адрес: Санкт-Петербург
Сообщений: 27,807
Сказал(а) спасибо: 340
Поблагодарили 583 раз(а) в 208 сообщениях
Репутация: 113184
По умолчанию

Цитата:
Сообщение от Montespan Посмотреть сообщение
Выдает синтаксическую ошибку во второй функции на этом месте for j:=1 to m do
Подскажите, пожалуйста, что неверно?
Я не вникал в Вашу программу, тем более, что с динамическими переменными "плаваю", но у Вас имеется нестыковка в количестве begin - end ("begin" на 1 больше). И вообще, расстановка этих т.н. "операторных скобок" вызывает некоторые недоумения. Какой, например, смысл в том "begin", который идет сразу после строк
b[m*(d-1)+c]:=summa(a,c,d,n,m);
end; ?
Vladimir_S вне форума   Ответить с цитированием
Старый 20.12.2009, 00:38   #7 (permalink)
Long Cat
Banned
 
Регистрация: 01.09.2009
Сообщений: 4,396
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 2544
По умолчанию

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

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

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

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

Последний раз редактировалось Long Cat; 20.12.2009 в 00:42
Long Cat вне форума   Ответить с цитированием
Старый 20.12.2009, 08:47   #8 (permalink)
Vladimir_S
Специалист
 
Регистрация: 27.08.2008
Адрес: Санкт-Петербург
Сообщений: 27,807
Сказал(а) спасибо: 340
Поблагодарили 583 раз(а) в 208 сообщениях
Репутация: 113184
По умолчанию

Цитата:
Сообщение от Long Cat Посмотреть сообщение
При форматировании текста программы удобно придерживаться таких правил:
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:58
Vladimir_S вне форума   Ответить с цитированием
Старый 20.12.2009, 08:57   #9 (permalink)
Long Cat
Banned
 
Регистрация: 01.09.2009
Сообщений: 4,396
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 2544
По умолчанию

На вкус и цвет... :-)
Long Cat вне форума   Ответить с цитированием
Старый 20.12.2009, 11:20   #10 (permalink)
Montespan
Member
 
Регистрация: 01.11.2009
Сообщений: 13
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 10
По умолчанию

Спасибо, буду иметь ввиду.
Теперь компиллятор ошибок не выдает, но и исправленная функция не работает.
Программа реализована как меню. Первый пункт работает хорошо, когда выбираю второй, ничего не происходит.
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
Montespan вне форума   Ответить с цитированием
Ads

Яндекс

Member
 
Регистрация: 31.10.2006
Сообщений: 40200
Записей в дневнике: 0
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 55070
Ответ

Опции темы
Опции просмотра

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

BB коды Вкл.
Смайлы Вкл.
[IMG] код Выкл.
HTML код Выкл.
Trackbacks are Вкл.
Pingbacks are Вкл.
Refbacks are Выкл.




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

Powered by vBulletin® Version 6.2.5.
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.