Translacja kodu z C++ do Delphi

0

Cześć, w programowaniu nie jestem zaawansowany a z delphi dopiero zaczynam przygodę na potrzeby szkoły. Ogólnie rzecz biorąc mam do napisania program, który poszuka liczby półpierwsze a dokładniej wypisze trójki (maksymalnie występują trzy liczby półpierwsze obok siebie). Nie mam już siły na ten program, nie mam wgl pomysłu na program. Znalazłem identyczny program tylko że napisany w C++, staram sie go teraz przerzucić do Delphi.
http://mattomatti.com/a74
http://mattomatti.com/PGES/a74/task1.cpp

var
a,b,i:integer;

begin
b:=StrToInt(Edit1.Text);

wypisztrojki;

function pierwszydzielnik(a:integer):integer;
  begin
    for i := 2 to sqrt(a) do
      if a mod i =0 then
      pierwszydzielnik:=i;
  end;

function czypolpierwsza(a:integer)integer;
  begin
  czypolpierwsza:=(dzielnik <> 0 AND pierwszydzielnik(a div dzielnik=0);
  pierwszydzielnik:=dzielnik;
  end;

procedure wypisztrojki(a:integer;b:integer);
  begin
    p1,p2,p3:boolean;
    p1:=czypolpierwsza(a);
    p2:=czypolpierwsza(++a);
    p3:=czypolpierwsza(++a);
    for a := a to b do
      p1:=p2;
      p2:=p3;
      p3:=czypolpierwsza(a);
        if p1 AND p2 AND p3 then
          writeln (a-2), (a-1), (a);

  end;

end;
 

Program pewnie do zaorania, wywala dużo błedów ale może macie jakieś pomysły co zrobić z tym fantem, bardzo mi zależy.

1

Nie ma najgorzej, choć w kodzie widnieje wiele błędów wynikających z niewiedzy oraz pośpiechu.

Zacznij od przepisania samej funkcji pierwszyDzielnik - nie zapomnij, że return xyz; w C++ powoduje od razu zakończenie wykonywania danej funkcji, podczas gdy nazwaFunkcji := xyz; w Pascalu dalej kontynuuje jej działanie.

0

To w takim razie jak zakończyć działanie funkcji, przepraszam ale nigdzie nie mogę znaleźć. Mógłbyś ewentualnie podpowiedzieć co jest nie tak, na co zwrócić uwagę, co poprawić? Wtedy mógłbym przysiąść do tego jutro i podziałać dłużej.

0

ech pomijając już "poprawność" tego algorytmu to na pierwszy rzut oka powinno to wyglądać mniej więcej tak:

function pierwszydzielnik(a:integer):integer;
var
  i: Integer;
begin
  result := 0;
  for i := 2 to Trunc(sqrt(a)) do
    if a mod i =0 then
    begin
      result :=i;
      break; //przerywamy pętlę jeśli faktycznie szukamy pierwszego dzielnika
    end;
end;

function czypolpierwsza(a:integer): boolean;
var dzielnik: integer;
begin
  dzielnik := pierwszydzielnik(a);
  result :=(dzielnik <> 0) AND ((pierwszydzielnik(a div dzielnik)=0));
end;

procedure wypisztrojki(a,b:integer);
var
  licznik: integer;
  p1,p2,p3:boolean;
  i: Integer;
begin
    p1:=czypolpierwsza(a);
    p2:=czypolpierwsza(a+1);
    p3:=czypolpierwsza(a+2);
    for i := a to b do
    begin
      p1:=p2;
      p2:=p3;
      p3:=czypolpierwsza(a);
        if p1 AND p2 AND p3 then
        begin  
          Writeln(IntToStr(i-2) + ' '+  IntToStr(i-1) + ' ' + IntToStr(i));
          Inc(licznik); 
        end;
 end;
0

Dziękuję woolfik, jeśli faktycznie to działa to spróbuję to sobie wyjaśnić samemu co i jak. Mając na myśli "poprawność" uważasz że nie jest to dobry sposób?

1
function pierwszydzielnik(a:integer):integer;
var
  i: Integer;
begin
  result := 0;
  for i := 2 to Trunc(sqrt(a)) do
    if a mod i =0 then
    begin
      result :=i;
      break; //przerywamy pętlę jeśli faktycznie szukamy pierwszego dzielnika
    end;
end;

Co nieco podpowiem - wartość domyśla powinna być nadawana za pętlą, natomiast Break nie jest potrzebne, dlatego że można skorzystać z rozszerzonej wersji Exit; Przykład:

function GetFirstDivider(ANumber: Integer): Integer;
var
  LDivider: Integer;
begin
  for LDivider := 2 to Trunc(Sqrt(ANumber)) do
    if ANumber mod LDivider = 0 then
      Exit(LDivider);
      
  Result := 0;
end;

Przy czym pamiętamy, aby kod porządnie formatować, używać przyjętej konwencji nazewnictwa, pisać kod po angielsku; Dzięki temu każdy będzie wiedział co kod robi i dlaczego działa tak, a nie inaczej.

0
Andrzej Kowalski napisał(a):

Dziękuję woolfik, jeśli faktycznie to działa to spróbuję to sobie wyjaśnić samemu co i jak. Mając na myśli "poprawność" uważasz że nie jest to dobry sposób?

Nie nie po prostu chodziło mi o to, że na oko poprawiłem Ci procedury, które zrobiłeś nie zgłębiając logiki algorytmu bo po prostu nie miałem na to czasu.

0

Dzięki Panowie! To tak, mam dwie funkcje i jedną procedurę, moje pytanie teraz jak to złożyć do kupy żeby działało.

var
a,b:integer;
begin
wypisztrojki;
end. 

Zrobiłem tak bo wydawało mi się że powinno działać ale wywala błąd "Not enough actual parameters".

Sprawdziłem samo wypisywanie liczb półpierwszych i działa, nie działa wypisywanie "trójek". Dodam, że pokazuje jeszcze "Value Assigned to p1 never used".

0

Musisz tam podać parametry a i b czyli w twoim przypadku coś takiego

wypisztrojki(StrToIntDef(edit1.text,0), StrToIntDef(edit2.text));

czy jakiś readln czy co tam potrzebujesz ... w każdym razie chodzi o parametry wejściowe z klawiatury zapewne

0
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
a,b:integer;
begin
  a:=StrToInt(Edit1.Text);
  b:=StrToInt(Edit2.Text);
  wypisztrojki(a,b);
end;

function pierwszydzielnik(a:integer):integer;
var
  i: Integer;
begin
  for i := 2 to Trunc(sqrt(a)) do
    if a mod i =0 then
       Exit(i);

  Result := 0;
end;

function czypolpierwsza(a:integer): boolean;
  var dzielnik: integer;
begin
  dzielnik := pierwszydzielnik(a);
  result :=(dzielnik <> 0) AND ((pierwszydzielnik(a div dzielnik)=0));
end;

procedure wypisztrojki(a,b:integer);
var
  p1,p2,p3:boolean;
  i: Integer;
begin
    p1:=czypolpierwsza(a);
    p2:=czypolpierwsza(a+1);
    p3:=czypolpierwsza(a+2);
    for i := a to b do
    begin
      p1:=p2;
      p2:=p3;
      p3:=czypolpierwsza(a);
        if p1 AND p2 AND p3 then
        begin
          Memo1.Lines.Add(IntToStr(i-2) + ' '+  IntToStr(i-1) + ' ' + IntToStr(i));
        end;
    end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
close;
end;

end. 

Kod wygląda tak.
Blędy:

wypisztrojki(a,b); 

undeclared identifier 'wypisztrojki'

Memo1.Lines.Add(IntToStr(i-2) + ' '+  IntToStr(i-1) + ' ' + IntToStr(i)); 

undeclared identifier 'memo1' oraz missing operation or semicolon

0
  1. Przenieś wypisztrojki powyżej TForm1.Button1Click, wraz z resztą funkcji.
  2. Memo1 jest polem klasy TForm1, zatem tak znikąd nie możesz się do niego odwołać wewnątrz funkcji wypisztrojki - musisz wykorzystać Form1.Memo1.
0

Chodzi o to żebym wszystkie funkcje przeniósł nad TForm1.Button1Click czy tylko fukcję:

var
a,b:integer;
begin
  a:=StrToInt(Edit1.Text);
  b:=StrToInt(Edit2.Text);
  wypisztrojki(a,b);
end; 

?

0

Może inaczej: zrób forward deklarację procedury wypisztrojki, będzie ładniej.
inb4 nie pytaj co to jest forward deklaracja - wpisz w Google.

0

Dzięki, już wszystko gra.
Można się jakoś odwdzięczyć na tym forum?

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