Pascal einfache Procedure

Gast #2911572
Lesenswert?

Hallo

Ich versuche eine erste einfache Procedure in Lazarus in 
Pascal-Programmiersprache zum laufen zu bringen aber irgendwas mit den 
"end" stimmt noch nicht, ich dachte ich kenne die Regeln aber brauche 
jetzt eure Hilfe.

das Programm ist folgendees:
1
program Project1;
2

3
{$mode objfpc}{$H+}
4

5
uses
6
  {$IFDEF UNIX}{$IFDEF UseCThreads}
7
  cthreads,
8
  {$ENDIF}{$ENDIF}
9
  Classes
10
  { you can add units after this };
11
   Procedure EinfacheProcedure(a,b:real;
12
                                 out Ergebnis1, Ergebnis2: real);
13
 begin
14
    Ergebnis1:=a+b;
15
    Ergebnis2:=a-b
16

17
 end;
18
end
Gast #2911600
Lesenswert?

mal anders formatiert und ein begin mehr und den Punkt zum Schluß:
1
program Project1;
2

3
{$mode objfpc}{$H+}
4

5
uses
6
  {$IFDEF UNIX}{$IFDEF UseCThreads}
7
  cthreads,
8
  {$ENDIF}{$ENDIF}
9
  Classes
10
  { you can add units after this };
11

12
begin  { !!!!!!!!!!! }
13

14
  {
15
   var global:real;
16
  }
17

18
  Procedure EinfacheProcedure(a,b:real;
19
                                 out Ergebnis1, Ergebnis2: real);
20
   begin
21
      Ergebnis1:=a+b;
22
      Ergebnis2:=a-b
23

24
   end;
25

26
end.
Gast #2911751
Lesenswert?

Pascal schrieb:
> Procedure EinfacheProcedure(a,b:real;
>                                  out Ergebnis1, Ergebnis2: real);
>    begin
>       Ergebnis1:=a+b;
>       Ergebnis2:=a-b
>
>    end;

Um ein Ergebnis zu liefern, müsste es heissen
1
Function Ergebnis1 (a,b : real) : real;
2
  begin
3
  Ergebnis1 := a+b;
4
  end;

Aber mit 2 Ergebnissen bist du sowieso auf dem Holzweg, eine Function 
hat nur eines, eben den Wert der Function. Entweder du definierst 2 
Functions oder du lässt es bei der Procedure, die auf für sie globale 
Variablen Ergebnsi1, Ergebnis 2 zugreift, was nicht sehr portabel ist un 
deshalb etwas verpönt - aber korrekt.

Gruss Reinhard
#2911788
Lesenswert?

Also für Funktionsparameter in Ausgangsrichtung braucht man VAR
1
program Project1;
2

3
{$mode objfpc}{$H+}
4

5
uses
6
  {$IFDEF UNIX}{$IFDEF UseCThreads}
7
  cthreads,
8
  {$ENDIF}{$ENDIF}
9
  Classes
10
  { you can add units after this };
11

12
Procedure EinfacheProcedure(a,b:real; VAR Ergebnis1, Ergebnis2: real);
13
begin
14
  Ergebnis1:=a+b;
15
  Ergebnis2:=a-b; {Der Strichpunkt hier ist optional}
16
end;
17

18
VAR globvarA,globvarB,globvarC,globvarD:real;
19
begin 
20
  {Kommentar, hier sind die Anweisungen des Hauptprogramms}
21
  globvarA:=1; globvarB:=2;
22
  EinfacheProcedure(globvarA,globvarB,globvarC,globvarD);
23
  writeln(globvarC,' ',globvarD,' ');
24
end.
Übrigens inzwischen verwendet man lieber double oder single anstelle von 
real.
Gast #2911805
Lesenswert?

Reinhard Kern schrieb:
> Aber mit 2 Ergebnissen bist du sowieso auf dem Holzweg, eine Function
> hat nur eines, eben den Wert der Function. Entweder du definierst 2
> Functions oder du lässt es bei der Procedure, die auf für sie globale
> Variablen Ergebnsi1, Ergebnis 2 zugreift, was nicht sehr portabel ist un
> deshalb etwas verpönt - aber korrekt.

Schwachwug hoch Zehn ;-)
Ergebnisse können als var deklariert per Parameter übergeben werden.

Aber die Frage war eine andere:

BeleFischer schrieb:
> aber irgendwas mit den
> "end" stimmt noch nicht, ich dachte ich kenne die Regeln aber brauche
> jetzt eure Hilfe.
Gast #2911939
Lesenswert?

Hallo,
warum sollte mir eine Funktion nicht mehrere Ergebnisse in einem
eigenen Type (hier z.B. Array) zurückgeben können ?
(jetzt mal unabhängig davon ob guter oder schlechter Programmierstil)
1
unit Unit1;
2

3
{$mode objfpc}{$H+}
4

5
interface
6

7
uses
8
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
9

10
type
11
  pm = array [0..2] of double;
12

13
  { TForm1 }
14

15
  TForm1 = class(TForm)
16
    Button1: TButton;
17
    procedure Button1Click(Sender: TObject);
18
  private
19
    { private declarations }
20

21
    function plusminus(a,b: double): pm;
22
  public
23
    { public declarations }
24
  end;
25

26
var
27
  Form1: TForm1;
28

29
implementation
30

31
{$R *.lfm}
32

33
procedure TForm1.Button1Click(Sender: TObject);
34
begin
35
  Caption := FloatToStr(plusminus(2,3)[0])
36
             + ' / ' + FloatToStr(plusminus(2,3)[1])
37
             + ' / ' + FloatToStr(plusminus(2,3)[2]);
38
end;
39

40
function TForm1.plusminus(a,b: double): pm;
41
begin
42
     Result[0] := a+b;
43
     Result[1] := a-b;
44
     Result[2] := a*b;
45
end;
46
end.
47

48
MfG
Gast #2912134
Lesenswert?

BeleFischer schrieb:
> Ich versuche eine erste einfache Procedure in Lazarus in
> Pascal-Programmiersprache zum laufen zu bringen aber irgendwas mit den
> "end" stimmt noch nicht

Es stimmt ne Menge anderes auch bloß nicht.

Also:

program Project1;
uses
 { hier kommt die Liste der benutzten Units rein, Beispiele: }
 Windows, DOS, UNIX, SysUtils, MyKrempel, DiesUndDas;

Procedure EinfacheProcedure(a,
                            b : real;
                            var Ergebnis1 : real;
                            var Ergebnis2 : real);
 begin
    Ergebnis1:=a+b;
    Ergebnis2:=a-b
 end;

{ und hier haste den Hauptteil vergessen }

var
  Blabla : real;
  lalala : real;

begin
  EinfacheProcedure(123, 345, Blabla, lalala);
  writeln('auf meinem Miste wuchsen ',Blabla,' Früchte an ',lalala,
          ' Bäumen');

end.

Vergiß den Punkt nicht hinter dem letzten end
und schreib nicht solche scheußlichen Prozeduren. Für Rückgabewerte 
nimmt man FUNCTION.

W.S.
Gast #2912236
Lesenswert?

W.S. schrieb:
> und schreib nicht solche scheußlichen Prozeduren. Für Rückgabewerte
> nimmt man FUNCTION.

Das sieht nicht jeder so. Oft gibt der Rückgabewert einer function eine 
Aussage über Versagen oder nicht, z. Bsp. Wertebereich verlassen, 
Division durch 0, usw. Du hast selber ein schönes Bsp. geschrieben:
1
begin
2
  If EinfacheFunction(123, 345, Blabla, lalala) = OK then
3
     writeln('auf meinem Miste wuchsen ',Blabla,' Früchte an ',lalala,
4
             ' Bäumen')
5
  else
6
     writeln('Fehler: EinfacheFunction');
7

8
end.
#2916296
Lesenswert?

Hallo,

Jede IDE wie lazarus,fp ( syntaxcheck ), geany , etc pp hätte über das 
fehlende end. gemosert/es angezeigt.

Wer hat denn etwas gegen out Parameter?
Siehe  http://www.freepascal.org/docs-html/ref/refsu57.html
Wer will den für jedes blabalbal und lalala eine extra Typ anlegen.

Ein guter Prozedurname hilft doch eher weiter, ala
1
procedure DiffSumBerechnen(     a,b     : double;
2
                           out sum,diff : double);
3
begin
4
  sum  :=a+b;
5
  diff :=a-b
6
end;
Gast #2921264
Lesenswert?

Rufus Τ. Firefly schrieb:
> Ich habe so meine Zweifel daran, daß Du weißt, wovon Du da redest.

Hehe, du wolltest mal wieder ein bissel stänkern, gelle?

Aber ich bin ja ein netter und positiv eingestellter Mensch und deshalb 
erkläre ich dir das mal:

Also, "var" wurde mal eingeführt, um Programm und Stack bei umfänglichen 
Argumenten einer Funktion zu entlasten. Dabei wurde leider ein im 
Prinzip unerwünschter Seiteneffekt mit eingeführt, denn dadurch war es 
möglich, mutwillig oder versehentlich Veränderungen an einem so 
deklarierten Argument zu bewirken. Es wurde dann mit "const" 
nachgebessert, aber das greift nur dort, wo die Programmierer es auch 
tatsächlich benutzen. Die Einführung von "out" ist zwar konsequent und 
stellt zumindest eine Art 'Achtungs-Schild' dar, aber sie befördert eben 
auch dessen Verwendung und damit einen Programmierstil, wo das Ausnutzen 
des Seiteneffektes nicht die seltene Notlösung eines Problems ist, 
sondern zum generellen Stil der Programmierer sich entwickelt. Siehe 
übliche Programmierstile bei C.

Weitaus besser wäre es, die betreffenden Daten zu einem Objekt zu machen 
und die Funktion zu einer Methode dieses Objektes. Das wäre ein Schritt 
in die richtige Richtung. Pascal bietet heutzutage diese Möglichkeit, 
man kann damit Daten sinnvoll kapseln und unübersichtliche Zusammenhänge 
vermeiden, die ansonsten gar zu häufig Ursache schwer zu findender 
Laufzeitfehler sind.

W.S.
Moderator #2921484
Lesenswert?

W.S. schrieb:
> Also, "var" wurde mal eingeführt, um Programm und Stack bei umfänglichen
> Argumenten einer Funktion zu entlasten.

Das glaube ich nicht (um es genau zu wissen, müsste man allerding Herrn
Wirth fragen). Wenn es so wäre, würde das Schlüsselwort nicht "var",
sondern bspw. "ref" (wegen call by reference) heißen.

> Dabei wurde leider ein im Prinzip unerwünschter Seiteneffekt mit
> eingeführt, denn dadurch war es möglich, mutwillig oder versehentlich
> Veränderungen an einem so deklarierten Argument zu bewirken.

Und eben weil damit Änderungen des Arguments möglich und auch vorgesehen
sind, wurde als Schlüsselwort "var" (variable=veränderlich) genommen.

> Es wurde dann mit "const" nachgebessert, aber das greift nur dort, wo
> die Programmierer es auch tatsächlich benutzen.

Mit "const" sichert der Programmierer dem Compiler nur zu, dass der
Parameter innerhalb des Unterprogramms nicht verändert wird. Damit hat
der Compiler die freie Wahl, das Argument per Wert oder per Referenz zu
übergeben, da es bei korrekter Programmierung keinen semantischen Unter-
schied zwischen den beiden Alternativen gibt.

Will man Call-by-Reference aus Effizienzgründen erzwingen, ist (zumin-
dest in Free Pascal) "constref" die richtige Wahl. Da steckt dann auch
tatsächlich das "ref" für Reference drin.

Zusammengefasst:
1
Qualifier   Call by   Datenrichtung   Beschreiben
2
——————————————————————————————————————————————————
3
(keiner)     Value         in           erlaubt
4
   var     Reference     in/out         erlaubt
5
  const    impl.-abh.      in           verboten
6
constref   Reference       in           verboten
7
   out     Reference       out       vorgeschieben
8
——————————————————————————————————————————————————

Jede dieser fünf Methoden hat also ihren speziellen Einsatzzweck.

> Die Einführung von "out" ist zwar konsequent und stellt zumindest eine
> Art 'Achtungs-Schild' dar, aber sie befördert eben auch dessen
> Verwendung und damit einen Programmierstil, wo das Ausnutzen des
> Seiteneffektes nicht die seltene Notlösung eines Problems ist, sondern
> zum generellen Stil der Programmierer sich entwickelt. Siehe übliche
> Programmierstile bei C.

Solche Konstrukte sind eben vonnöten, wenn in einer Programmiersprache
Funktionen nur einen einzelnen Rückgabewert liefern können. Das ist eine
Design-Schwäche von Pascal, C und auch vielen neueren, davon abgeleite-
ten Sprachen. Als Seiteneffekt würde ich das aber nicht bezeichnen, da
dieser alternative Weg, Funktionsergebnisse zurückzugeben, klar in der
Funktionsdeklaration durch das "var" bzw. "out" dokumentiert ist.
Schlecht ist allerdings, dass man den Unterschied nicht beim Aufruf der
Funktion erkennen kann.

Man kann die Rückgabewerte allenfalls in einer Struktur zusammenfassen,
um die Out- und Var-Parameter zu vermeiden. Das ist aber in vielen
Fällen auch nicht schön, weil man bei jedem Funktionsaufruf erst die
Werte in die Struktur packen und hinterher die Struktur wieder
auseinanderfieseln muss.

> Weitaus besser wäre es, die betreffenden Daten zu einem Objekt zu
> machen und die Funktion zu einer Methode dieses Objektes. Das wäre ein
> Schritt in die richtige Richtung.

Auch das ist eine Möglichkeit, aber IMHO ebenfalls etwas von hinten
durch die Brust ins Auge ;-)

Wie dieses Problem elegant gelöst wird, zeigt bspw. Python, wo man
einfach schreibt:
1
y,z = f(x)

Eigentlich liefert auch hier die Funktion nur einen einzelnen Rückgabe-
wert, nämlich ein Tupel. Das anschließende Auseinanderfieseln desselben
geschieht aber nicht explizit, sondern impliziet durch Pattern-Matching,
so dass auf Syntaxebene die Funktion tatsächlich zwei Rückgabewerte
liefert.
Persönliche Seite #2921527
Lesenswert?

Yalu X. schrieb:
> Das anschließende Auseinanderfieseln desselben
> geschieht aber nicht explizit
Wobei das auch so eine Frage ist ob das nun unbedingt sein muss, ob ich 
jetzt schreibe:
1
var x;
2
var y;
3

4
x,y = func();
5

6
echo "x="+x+", y="+y;
oder
1
var obj = func();
2
echo "x="+obj.x+", y="+obj.y;
ist nun auch nicht die Welt... Ich habe (zumindest im OO Umfeld) auch 
gaaaaaanz selten den bedarf mal mehr als "einen" Wert zurückzugeben 
(eigentlich müsste man sagen: einen Typ, da ja der Rückgabewert durchaus 
ein Array sein kann).

Und für den Fall kann man sich wenn es einen nun wirklich wurmt auch 
einmal eine generelle Tupel/Tripel/... Klasse schreiben.
Gast #2921539
Lesenswert?

Yalu X. schrieb:
> Das glaube ich nicht (um es genau zu wissen, müsste man allerding Herrn
> Wirth fragen).

Kannst du ja: ich hatte da auch Zweifel, aber im Jensen-Wirth steht 
ausdrücklich drin, dass var eingesetzt werden kann, um die Belastung von 
Stack und Programmcode gering zu halten durch Übergabe per Referenz (von 
Pointern redet da keiner). Wirth hatte das also zumindest AUCH im Auge. 
Nicht dumm der Mann.

Wer hat's erfunden? Die Schweizer!

Gruss Reinhard
Moderator #2921621
Lesenswert?

Reinhard Kern schrieb:
> im Jensen-Wirth steht ausdrücklich drin, dass var eingesetzt werden
> kann, um die Belastung von Stack und Programmcode gering zu halten

Natürlich kann man das "var" auch zur Handoptimierung einsetzen. Die
Frage ist nur, welches welches der beiden Ziele (veränderliche Argumente
zu haben oder die Effizienzsteigerung) das primäre war. Dem Namen nach
zu urteilen sind es eher die veränderlichen Argumente. Die Effizienz-
steigerung ist ein angenehmer Nebeneffekt, den man natürlich ebenfalls
als Feature angepriesen hat.

Oder steht in dem Buch vielleicht drin, dass das "var" nur zur Effi-
zienzsteigerung eingesetzt werden soll?

Auch in meinem Studium, als ich Pascal lernen musste, wurden die beiden
Anwendungsmöglichkeiten von "var" in dieser Reihenfolge vorgestellt.
Genauer gesagt, hat der Professor nur die Anwendung für veränderliche
Argumente vorgestellt. Später, in den Übungen, hat uns dann die Tutorin
eröffnet, dass das ein cooler Trick ist, um Unterprogrammaufrufe zu
beschleunigen.

Aber eigentlich ist es ja auch egal, was die ursprüngliche Absicht war.
Das Feature wird eben mal so und mal anders genutzt, da seh ich nichts
Böses dabei.

> Wer hat's erfunden? Die Schweizer!

Genau. Es gibt aber auch bei den Bonbons bessere als Ricola ;-)
Gast #2922068
Lesenswert?

Yalu X. schrieb:
> Das Feature wird eben mal so und mal anders genutzt, da seh ich nichts
> Böses dabei.

Es ist ja auch nichte BÖSES, sondern eine Quelle für schlecht 
auffindbare Bugs, wenn man nicht wirklich höllisch aufpaßt. Sei doch mal 
realistisch: Der größte Teil von Bugs passiert aus irgendwelchen 
Schusseligkeiten oder daß man irgendwas übersehen hat - und keiner von 
uns kann von sich behaupten, da ganz erhaben drüberzustehen. Schließlich 
sind wir Menschen und keine Maschinen.

Es ist also sehr wohl die Frage nach dem eigenen Programmierstil. Ich 
bevorzuge - wo es geht - einen Stil, der von Hause aus möglichst so 
überschaubar ist, wie die Programmiersprache das zuläßt. Bei plain C hab 
ich keine Chance, mit Objekten zu arbeiten und deren Innenleben von der 
Außenwelt zu kapseln (um unbeabsichtigte Schnitzer nicht zum Zuge kommen 
zu lassen), aber bei Pascal hat man die Möglichkeit - und sie ist 
obendrein auch noch gut und angenehm leserlich. Warum also nicht so? Ich 
denk mal, im Grunde deiner Seele siehst du das ein bissel ähnlich.

W.S.
Persönliche Seite #2922229
Lesenswert?

W.S. schrieb:
> aber bei Pascal hat man die Möglichkeit

Eigentlich da auch nicht. Was Du als Pascal bezeichnest, ist "Object 
Pascal", eine Weiterentwicklung von Pascal. Pascal, das ist das, was vor 
"Delphi" war.

Mit der gleichen Logik könnte man also auch argumentieren, daß man in C 
ebenfalls Objekte nutzen könnte -- denn C++ ist ja auch nur so eine Art 
Weiterentwicklung von C.
Gast #2922383
Lesenswert?

??? schrieb:
> Was hat das mit
> der Ausgangsfrage oder variablen Parametern zu tun?

Dass Objekte das Problem der unbeabsichtigten Nebenwirkungen vermeiden 
können, das bei var besteht - und weil sowieso alles mit allem 
zusammenhängt.

Gruss Reinhard
#2922426
Lesenswert?

(interessant wie sich so eine extrem einfache frage, entwickelt...)

>und schreib nicht solche scheußlichen Prozeduren. Für Rückgabewerte
>nimmt man FUNCTION.

allein die Existenz von "out" Parameter, beweist ja schon das 
Gegenteil..

..

zum VAR, ja da kenne ich auch Leute die das zum 
geschwindigkeitsoptimieren verwenden. bei Stings z.B.
real bringt das natürlich fast nix (man spart eine Referenzzählung +/-), 
bringt aber einige gefahren...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren