Funkcja wywoływana dwa razy daje te same parametry (błąd) + procedura która sumuje dwie tablice

Odpowiedz Nowy wątek
2018-11-05 16:31
0

program ma działać następująco:

  • prosi użytkownika o podanie zakresu liczb jakie mają być wpisywane do tablic;
  • funkcja wczytajTablice generuje losowe wartości z podanego zakresu i wpisuje je do tablic;
  • procedura pokazTablice wyświetla zawartość tablicy na ekranie podanej jako parametr;
  • procedura zsumujTablice pobiera dwie tablice (tab1 i tab2) i oblicza elementy trzeciej (tab3) jako sumę elementów dwóch wcześniej wymienionych.

Do tej pory napisałem takie procedury i funkcje:

function wczytajtablice(var z:integer):typtablica;
var
 i:integer;

 begin
  randomize;
  for i:=0 to n-1 do
  result[i]:=random(z);
 end;

procedure pokaztablice(tablica:typtablica);
var
 i:integer;

 begin
   writeln('--------------------------');
   i:=0;
   repeat
     write('e[',i+1:2,']=',tablica[i]:4,'   ');
     writeln();
     i:=i+1;
   until i>=n;
 end;                 

kod wygląda następująco:

begin

  write('Podaj zakres liczb: ');
  readln(zakres);

  tab1:=wczytajTablice(zakres);
  tab2:=wczytajTablice(zakres);

  pokazTablice(tab1);
  pokazTablice(tab2);

  zsumujTablice(tab1,tab2,tab3);
  pokazTablice(tab3);

  readln;
end.     

Do tej pory natknąłem się na pierwszy problem, a mianowicie gdy wywołuje się procedura "pokaztablice" to pokazuje ona dwie identyczne tablice.
Co trzeba zrobić, aby wyświetlane tablice były różne?
Jak powinien wyglądać kod procedury "zsumujTablice", aby ta dodała do siebie elementy dwóch tablic?

edytowany 2x, ostatnio: furious programming, 2018-11-05 18:18

Pozostało 580 znaków

2018-11-05 16:59
0

1) co to jest typtablica? Gdzieś sobie to musiałeś zdefiniować, bo "raczej" nie jest to żaden typ wbudowany w język, ale nie wkleiłeś tutaj tej definicji.
2) wiem, że to jest mały programik ćwiczeniowy, ale mógłbyś poprawić nazwy zmiennych. Teraz może pamiętasz czym są Z oraz I, ale za pewien czas to się pomiesza. Nazwy powinny być opisowe - tak, żeby ktokolwiek, kto siądzie do tego programu, mógł się od razu połapać, za co odpowiada dana zmienna.
3) nie widzę deklaracji zmiennych tab1, tab2 oraz n.

Czy możesz wkleić cały kod, a nie tylko fragmenty? Chyba przeoczyłeś kilka fragmentów, które mogą mieć znaczenie.
Napisz też w czym piszesz - Delphi, Lazarus, FPC?


That game of life is hard to play
I'm gonna lose it anyway
The losing card I'll someday lay
So this is all I have to say
edytowany 1x, ostatnio: cerrato, 2018-11-05 17:10

Pozostało 580 znaków

2018-11-05 17:08
1
  1. Zakres to a..b a nie jedna liczba. Trzeba zmienić opis z zakresu od 0 do ... albo wprowadzić dolną i górną granicę zakresu.
  2. Jeśli zakres jest to X, to random robisz z X+1.
  3. Gdzie masz zmienną 'n' bo odwołujesz się do niej a nie wiadomo co to jest.
  4. To co pisał @cerrato - co to typtablica? Co by to nie było to nie masz deklaracji rozmiaru tablic.
  5. Sumujesz podobnie do wczytywania (rozmiar tablic musi być oczywiście taki sam), czyli iteracja po rozmiarze i jak result będzie trzecia tablica a po prawej suma dwóch wejściowych.
  6. Podaj pełny kod bo z tego co podesłałeś raczej nic nie wychodzi.

Pozostało 580 znaków

2018-11-05 17:48
0

Używam Lazarusa... Cały kod mam w trzech modułach dlatego tak to wkleiłem sorka... Poniżej mogłem namieszać w kolejności.


uses
  Classes, SysUtils, defunit,fununit2;

function wczytajtablice(var zakres1:integer):typtablica;
procedure pokazTablice(tablica: typtablica); 

implementation
function wczytajtablice(var zakres1:integer):typtablica;
var
 i:integer;

 begin
  randomize;
  for i:=0 to n-1 do
  result[i]:=random(zakres1)+1;
 end;

procedure pokaztablice(tablica:typtablica);
var
 i:integer;

 begin
   writeln('--------------------------');
   i:=0;
   repeat
     write('e[',i+1:2,']=',tablica[i]:4,'   ');
     writeln();
     i:=i+1;
   until i>=n;
 end;                         

const
n=10; 

type
typtablica = array[0..n-1] of integer;

var
  tab1,tab2,tab3:typTablica;
  zakres:integer;

begin

  write('Podaj zakres liczb: ');
  readln(zakres);

  tab1:=wczytajTablice(zakres);
  tab2:=wczytajTablice(zakres);

  pokazTablice(tab1);
  pokazTablice(tab2);

  zsumujTablice(tab1,tab2,tab3);
  pokazTablice(tab3);

  readln;
end.                 

tak to wygląda no i zamiast wyświetlać dwie różne tablice wyświetla to samo.

Pozostało 580 znaków

2018-11-05 18:14
2
brotomasz napisał(a):

Co trzeba zrobić, aby wyświetlane tablice były różne?

Randomie woła się raz na cały program, więc najlepiej będzie, jeśli przeniesiesz wywołanie tej procedury go głównego bloku kodu, na sam jego początek. A Ty wołasz ją tuż przed każdym losowaniem, dlatego w tablicy lądują takie same wartości.

Poza tym nazwa funkcji wczytajtablice kłamie o przeznaczeniu tej funkcji, bo służy ona do losowania zawartości tablicy, a nie jej wczytywania. Zresztą te nazwy są złe – użyj angielskich i stosuj się do przyjętej konwencji.

Jak powinien wyglądać kod procedury "zsumujTablice", aby ta dodała do siebie elementy dwóch tablic?

Np. tak:

type
  TMyArray = array [0 .. n - 1] of Integer;

  procedure SumArrays(const ALeft, ARight: TMyArray; out ADest: TMyArray);
  var
    I: Integer;
  begin
    for I := Low(ADest) to High(ADest) do
      ADest[I] := ALeft[I] + ARight[I];
  end;

edytowany 9x, ostatnio: furious programming, 2018-11-05 23:11

Pozostało 580 znaków

2018-11-05 18:30
0

@furious programming: pozwolę sobie się nie zgodzić. Funkcja RANDOMIZE wrzuca do RANDSEED wartość wyznaczoną ma podstawie aktualnego zegara (https://www.freepascal.org/docs-html/rtl/system/randomize.html). Nie ma niczego złego w wywołaniu jej ile razy ma się ochotę.

Fakt, że wyniki są takie same jest jakby skutkiem ubocznym wywołania RANDOMIZE kilka razy - po prostu czas pomiędzy wywołaniami jest tak krótki, że do RANDSEED prawdopodobnie trafia dokładnie taka sama wartość. Dlatego - w tym przypadku masz rację i wystarczyło by (a nawet by było lepiej) wywołać to raz na samym początku, ale nie zmienia to faktu, że nie ma niczego złego w inicjowaniu generatora liczb losowych częściej (o ile się rozumie jak działa ten mechanizm i jak się powinno go używać).


That game of life is hard to play
I'm gonna lose it anyway
The losing card I'll someday lay
So this is all I have to say

Pozostało 580 znaków

2018-11-05 18:34
0
cerrato napisał(a):

Nie ma niczego złego w wywołaniu jej ile razy ma się ochotę.

Fakt, że wyniki są takie same jest jakby skutkiem ubocznym wywołania RANDOMIZE kilka razy - po prostu czas pomiędzy wywołaniami jest tak krótki, że do RANDSEED prawdopodobnie trafia dokładnie taka sama wartość.

Te dwa zdania są ze sobą sprzeczne – albo nie ma niczego złego, albo są paskudne skutki uboczne. Tak więc sam sobie odpowiedziałeś na pytanie, dlaczego Randomize nie powinien być wołany wielokrotnie. A to że można tak zrobić, wynika wyłącznie ze specyfiki ustalania ziarna – to zwykła procedura, która nie jest w żaden sposób kontrolowana.


edytowany 2x, ostatnio: furious programming, 2018-11-05 18:35

Pozostało 580 znaków

2018-11-05 18:35
0

Czyli nie da się zrobić tak żeby tablice były różne? Może jakieś polecenie w procedurze, które zatrzymuje program na 1 sekundę

edytowany 1x, ostatnio: brotomasz, 2018-11-05 18:37
Da się. Tak, jak pisał @furious programming - zrób RANDOMIZE jeden raz gdzieś na poczatku aplikacji - cerrato 2018-11-05 18:38

Pozostało 580 znaków

2018-11-05 18:36
0

"Te dwa zdania są ze sobą sprzeczne" - nieladnie jest wyrywać fragment wypowiedzi z kontekstu i to w dodatku w taki sposób, żeby przekręcić jej wymowe.

Na końcu dodałem przecież, że można używać tego wiele razy, pod warunkiem że się rozumie jak to działa.


That game of life is hard to play
I'm gonna lose it anyway
The losing card I'll someday lay
So this is all I have to say

Pozostało 580 znaków

2018-11-05 18:38
1

Przecież Ci napisałem – wywal Randomize z funkcji wczytajtablice i dodaj wywołanie tej procedury na samej górze głównego bloku kodu, tak abyś miał pewność, że wołana jest tylko raz:

function wczytajtablice(var z: integer): typtablica;
var
  i: integer;
begin
  for i:=0 to n-1 do
    result[i]:=random(z);
end;

{..}

begin
  randomize;

  write('Podaj zakres liczb: ');
  readln(zakres);

  {..}

Poza tym sformatuj sobie ten kod – jest nieco nieczytelny i chaotyczny.


cerrato napisał(a):

"Te dwa zdania są ze sobą sprzeczne" - nieladnie jest wyrywać fragment wypowiedzi z kontekstu i to w dodatku w taki sposób, żeby przekręcić jej wymowe.

Gdzie wyrwałem tę wypowiedź z kontekstu? Z pierwszego cytowanego paragrafu usunąłem definicję i działanie tej funkcji, bo nie ma ona tutaj większego znaczenia. Poza tym znam jej działanie, więc nie musisz mi tego opisywać.

W jednym paragrafie piszesz, że nie ma problemu w wywoływaniu jej wielokrotnie, a w drugim, że jednak jest problem powtarzalności emitowanych liczb. To się nie klei.

Na końcu dodałem przecież, że można używać tego wiele razy, pod warunkiem że się rozumie jak to działa.

Nie wiem czy są jakiekolwiek praktyczne powody, dla krótych wielokrotne wołanie Randomize ma sens – nie znam ani jednego. W końcu bez względu na liczbę wywołań, funkcja Random działać będzie z taką samą losowością, a jedyną różnicą będzie powtarzalność wyników, co zaletą wcale nie jest. W końcu te procedurki/funkcje mają zapobiegać powtarzalności, a nie ją powodować.


edytowany 4x, ostatnio: furious programming, 2018-11-05 18:48

Pozostało 580 znaków

2018-11-05 19:01
0

Dziękuję, działa, działa też z użyciem Delay(500); w kodzie funkcji...
Nie wiem jak napisać procedurę która zsumuje elementy tablicy, to chyba proste, ja napisałem coś takiego i nie działa:

procedure zsumujTablice(tablica1,tablica2,tablica3:typtablica);
var
 i:integer;

 begin
  for i:=0 to n-1 do
  tablica3[i]:=tablica1[i]+tablica2[i];
 end; 

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0