Wyświetlanie choinki za pomocą pętli for – nieprawidłowe wyjście

0

Hej
Ostatnio chciałem wrócić po wielu latach do postaw programowania, bo kiedyś w to się bawiłem trochę.
Jako, że bardzo dużo wyleciało już mi z głowy zacząłem kurs od podstaw żeby odświeżyć pamięć i doszedłem do procedur i pętli.

Mam taki program jako przykład:

Program NAUKA;

{$APPTYPE CONSOLE}

uses
  SysUtils;

Var
  q: integer;
  ile:integer;

Procedure Szlaczek(znak : char; ile:integer);
Begin
  For q:=1 to ile do
    Write(znak);
    WriteLn;
End;

Begin
  For q:=1 to 20 do
    Szlaczek('.', q);
  ReadLn
End.

Mam trochę problem z nim, bo jego wynik to

.
...
.....
.......
.........
...........
.............
...............
.................
...................

a ja za nic nie mogę zrozumieć dlaczego wypisuje to właśnie tak. To pewnie proste jak drut, ale tyle już nad tym siedzę no i nie wiem czemu wypisuje to tak, że najpierw 1 kropka, potem 3 itd.

Mógłby ktoś przedstawić to z jakimś komentarzem jak dla kompletnego laika? Byłbym bardzo wdzięczny

1

Problem polega na tym, że nie uruchamiasz tego programu.
Jak byś uruchomił to otrzymałbyś to:

.
..
...
....
.....
......
.......
........

(itd)

0

No właśnie chodzi o to, że go uruchamiam.
Mogę wysłać projekt jeżeli trzeba

No tak, ta strona podaje taki wynik, a ja używając Delphi 7 i Delphi 10.2 mam wynik taki jak powyżej

1

Sprawdziłem pod Lazarusem – kod działa prawidłowo i emituje poprawną choinkę.

Problemem natomiast jest to, że piszesz kod co najmniej dziwnie i przez to nie potrafisz zrozumieć jego działania. Zmienna Globalna zmienna ile nie jest używana, a zmienną q używasz do iteracji dwóch pętli jednocześnie, w dwóch blokach kodu. Nie rób takich cudów – pisz kod w taki sposób, aby w ogóle nie korzystał ze zmiennych globalnych.

Tak więc działające rozwiązanie może wyglądać tak:

  procedure Szlaczek(AChar: Char; ACount: Integer);
  var
    I: Integer;
  begin
    for I := 1 to ACount do
      Write(AChar);

    WriteLn();
  end;

var
  I: Integer;
begin
  for I := 1 to 20 do
    Szlaczek('.', I);
end.

a rozwiązanie czytelne, nie wymagające wołania zbędnych procedur, tak:

var
  X, Y: Integer;
begin
  for Y := 1 to 20 do
  begin
    for X := 1 to Y do
      Write('.');

    WriteLn();
  end;
end.

Poza tym pisz kod dokładnie, ładnie go formatując. Używaj odpowiednich wcięć, pisz słowa kluczowe małymi literami, zawsze zakańczaj instrukcje średnikami i wstawiaj puste nawiasy okrągłe przy wywołaniach bezparametrowych procedur/funkcji. I nie rób niepotrzebnych odstępów.

0

Dziękuję za odpowiedź.
Kod nie był mojego autorstwa. Znalazłem go w jakieś prezentacji, która tłumaczyła wykorzystanie pętli for oraz procedury i brałem za pewnik, że jest ok.

Co do tych pustych nawiasów to u mnie kompilator wyrzuca błąd. Z tego co się orientowałem kiedyś zawsze tak było w Pascalu dlatego ich nie dodaję.

0
soob napisał(a):

Kod nie był mojego autorstwa. Znalazłem go w jakieś prezentacji, która tłumaczyła wykorzystanie pętli for oraz procedury […]

Szkoda, że jego autor nie nauczył się pisania czystego kodu przed napisaniem tego poradnika.

Co do tych pustych nawiasów to u mnie kompilator wyrzuca błąd. Z tego co się orientowałem kiedyś zawsze tak było w Pascalu dlatego ich nie dodaję.

Kiedyś, czyli kiedy? Bo nawet Turbo Pascal nie zabraniał podawania pustych nawiasów, a jest starszy ode mnie. Używaj współczesnych narzędzi, a nie będziesz miał problemów z brakiem wsparcia cukru składniowego i nie będziesz musiał tworzyć potworków.

0

Używałem Turbo Pascala i teraz używam Delphi i nie przechodzą polecenia typu

WriteLn();

Wyskakuje zawsze błąd "[Error] Project2.dpr(9): 'END' expected but ')' found"

0

Wklej cały kod, bo treść błędu sugeruje zupełnie inny powód. Poza tym, z którego Delphi korzystasz?

0
program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils, Crt;
var
  X, Y: Integer;
begin
  for Y := 1 to 20 do
  begin
    for X := 1 to Y do
      Write('.');
      WriteLn;
  end;
  ReadLn;
end.

Działa bez problemu tak jak powiedziałeś

program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils, Crt;
var
  X, Y: Integer;
begin
  for Y := 1 to 20 do
  begin
    for X := 1 to Y do
      Write('.');
      WriteLn();
  end;
  ReadLn;
end.

Nie działa. Błąd taki jak napisałem wyżej i zaznacza tę linię z WriteLn().

Przyznam się, że zaskoczyłeś mnie,bo w żądnej książce do Pascala nie spotkałem się, żeby ktoś stosował zapisy typu ReadLn() czy Write().

1

Zapewne ten kod nie kompiluje się w Delphi 7 – spróbuj w tym drugim, nowszym.

Tylko dla uporządkowania dyskusji, bo problem z tego co pamiętam będzie występował wyłącznie w przypadku pseudoprocedur, czyli w przypadku Write, WriteLn, Read, ReadLn i pewnie jeszcze kilku innych. W pozostałych przypadkach puste nawiasy nie będą powodować błędu w trakcie kompilacji.

soob napisał(a):

Przyznam się, że zaskoczyłeś mnie,bo w żądnej książce do Pascala nie spotkałem się, żeby ktoś stosował zapisy typu ReadLn() czy Write().

IMO błędem było zezwolenie na dowolność w temacie stawiania pustych nawiasów za identyfikatorem podprogramu. Dzięki temu każdy pisze inaczej i mnożą się style, zamiast wypracować jeden uniwersalny. Sam zawsze je stawiam, aby patrząc na identyfikator było wiadomo czy coś jest podprogramem, czy zmienną lub właściwością. Dzięki temu nie trzeba się zagłębiać w kod, aby zrozumieć przepływ sterowania.

Natomiast możliwość pominięcia średnika po ostatniej instrukcji w danym bloku wywodzi się z dawnych czasów. Dziś jest to możliwość, ale dla pierwszych kompilatorów była to konieczność. Tak więc nie jest durny ficzer, a po prostu zaszłość historyczna. Nawiasy być może też są nią, ale tego nie jestem pewien.

0

Rozumiem
Dzięki bardzo za pomoc i krótką lekcje. Będę się starał na przyszłość porządkować kod w lepszy sposób :)

1

Wyrzuć Delphi 7 i albo korzystaj z najnowszego darmowego, albo pobierz Lazarusa i poczuj wolność. ;)

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