Forum: PC-Programmierung Pascal einfache Procedure


von BeleFischer (Gast)


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

von asdfghjkl (Gast)


Lesenswert?

Das was Du sucht heisst: "Function"

von Pascal (Gast)


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.

von g457 (Gast)


Lesenswert?

> irgendwas mit den "end" stimmt noch nicht,
[..]
> end

War bei Pascal nicht irgendwas(tm) mit '.' beim letzten 'end' oder 
sowas?

von begin end (Gast)


Lesenswert?

g457 schrieb:
> War bei Pascal nicht irgendwas(tm) mit '.' beim letzten 'end' oder
> sowas?

und jedes end braucht ein begin, ausser bei uint Initialisierung.

von Reinhard Kern (Gast)


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

von Christian B. (casandro)


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.

von Der, der die Frage liest (Gast)


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.

von Mitleser (Gast)


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

von Christian B. (casandro)


Lesenswert?

Wenn Du das so machst, kann es sein, dass plusminus mehrmals aufgerufen 
wird. Da gibts irgendwie "const" oder so um das zu vermeiden.

von W.S. (Gast)


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.

von Der, der die Frage liest (Gast)


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.

von W.S. (Gast)


Lesenswert?

Der, der die Frage liest schrieb:
> Du hast selber ein schönes Bsp. geschrieben:

Nee, mein Lieber, das war nur des Zitates willen. Ich hab nur das 
ominöse 'out' entfernt. Schau:

BeleFischer schrieb:
> Procedure EinfacheProcedure(a,b:real;
>                             out Ergebnis1, Ergebnis2: real);

W.S.

von Horst H. (horha)


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;

von W.S. (Gast)


Lesenswert?

Horst Hahn schrieb:
> Wer hat denn etwas gegen out Parameter?

Ich.

Ist ne nette Spielerei, aber bei gründlicher Betrachtung nur etwas, das 
schlechten Programmierstil befördert.

W.S.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

W.S. schrieb:
> Ist ne nette Spielerei, aber bei gründlicher Betrachtung nur etwas, das
> schlechten Programmierstil befördert.

Ich habe so meine Zweifel daran, daß Du weißt, wovon Du da redest.

von W.S. (Gast)


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.

von Yalu X. (yalu) (Moderator)


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.

von Läubi .. (laeubi) Benutzerseite


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.

von Reinhard Kern (Gast)


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

von Yalu X. (yalu) (Moderator)


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 ;-)

von W.S. (Gast)


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.

von Rufus Τ. F. (rufus) Benutzerseite


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.

von ??? (Gast)


Lesenswert?

Plötzlich geht es um strukturiert vs. objektorientiert. Was hat das mit 
der Ausgangsfrage oder variablen Parametern zu tun?

von Reinhard Kern (Gast)


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

von gizmo (Gast)


Lesenswert?

hinter das letzte end einen punkt

von Robert L. (lrlr)


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...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.