![]() |
array als var-Parameter
Ich möchte eine Procedure, die soll mehreren Integer-Variablen den Wert 0 zuweisen.
Ich dachte ich könnte folgendes realisieren.
Delphi-Quellcode:
Und so soll die Funktion verwendet werden:
procedure SetToZero(aValues: array of Integer);
var a: Integer; begin for a := low(aValues) to High(aValues) do aValues[a] := 0; end;
Delphi-Quellcode:
Die Werte der Mengen ändern sich aber nicht. Sind immer noch 10 und 20.
lMenge1:=10;
lMenge2:=20; SetToZero([lMenge1,lMenge2]); Nun dachte ich, klar, fehlt der Var-Parameter. Also Funktion umgeschrieben und "var" vor avalues gesetzt.
Delphi-Quellcode:
Dann lässt sich folgende Zeile nicht mehr kompilieren.
procedure SetToZero(var aValues: array of Integer);
var a: Integer; begin for a := low(aValues) to High(aValues) do aValues[a] := 0; end;
Delphi-Quellcode:
SetToZero([lMenge1,lMenge2]);
Folgende Fehlermeldung:
Code:
Welchen Gedankenfehler mache ich?
[DCC Fehler] blubunit.pas(124): E2197 Konstantenobjekt kann nicht als Var-Parameter weitergegeben werden
|
AW: array als var-Parameter
Bei dieser Art der Übergabe handelt es sich um ein Open Array, das ist immer konstant. Versuch es doch einmal mit einer Typdeklaration, und diesen Typ übergibst Du dann.
|
AW: array als var-Parameter
Das Array nimmt nur die Werte auf und nicht die Referenzen/Zeiger zu den Variablen.
So kannst du nur die Werte im Array ändern, aber nicht die Variablen, wo diese Werte drin standen als du das Array erstellt hast ;) |
AW: array als var-Parameter
|
AW: array als var-Parameter
Die Übergabe in
Delphi-Quellcode:
ist mMn ein
SetToZero([lMenge1,lMenge2]);
Delphi-Quellcode:
!
array of const
Du müsstest es wie folgt deklarieren:
Delphi-Quellcode:
Ist jetzt schnell aus der Hüfte geschossen ...
type TArrayIntegers : TArray<integer>;
procedure SetToZero(var paInts : TArrayIntegers); begin ... end; procedure Irgendwas; var aIntegers : TArrayIntegers; begin aIntegers := TArrayIntegers.Create(10,20); SetToZero(aIntegers); end; Gruß Thomas |
AW: array als var-Parameter
Für alle, die es noch nicht verstanden haben ;)
Delphi-Quellcode:
procedure SetToZero( { ? } );
begin { ? } end; procedure Test; var Val1, Val2 : Integer; begin Val1 := 42; Val2 := 84; SetToZero([Val1,Val2]); Assert( ( Val1 = 0 ) and ( Val2 = 0 ), 'Mist, hat nicht hingehauen' ); end; |
AW: array als var-Parameter
Das geht wie Sir Rufo schon gesagt/angedeutet hat nur mit einem Array of PInteger.
Delphi-Quellcode:
Wenn dich das @ nicht stört, gehts so. Ansonsten fällt mir jetzt nichts ein.
procedure SetToZero(Werte: Array of PInteger);
var i: Integer; begin for i:= 0 to High(Werte) do Werte[i]^ := 0; end; procedure Test; var Val1, Val2 : Integer; begin Val1 := 42; Val2 := 84; SetToZero([@Val1,@Val2]); Assert( ( Val1 = 0 ) and ( Val2 = 0 ), 'Mist, hat nicht hingehauen' ); end; |
AW: array als var-Parameter
Danke für die Antworten. Ich habe es mir schon gedacht.
Habe nur gehofft, daß es etwas gibt, was ich noch nicht weis. Schade. Dann halt wieder:
Delphi-Quellcode:
Statt
lMenge1 = 0;
lMenge2 = 0; lMenge3 = 0; lMenge4 = 0;
Delphi-Quellcode:
SetToZero([lMenge1,lMenge2,lMenge3,lMenge4]);
|
AW: array als var-Parameter
Zitat:
Oder kommt das nicht in Frage für dich? |
AW: array als var-Parameter
Zitat:
Ich denke ich bleibe beim Alten. Das "@" tut mir irgendwie im Auge weh ;-) |
AW: array als var-Parameter
Das geht hier aber auch schnell mit den Antworten.:-D
|
AW: array als var-Parameter
Okay, mir war aus deinem Post nicht ganz klar, dass Du "nur" die Variablen auf 0 setzen wolltest. Ich bin von einem Array ausgegangen ...
|
AW: array als var-Parameter
Dann bau dir halt einen Wrapper
Delphi-Quellcode:
type
TPIntArray = array of PInteger; TIntValueSetter = record private FValues: TPIntArray; public function AddVar( var Value: Integer ): TIntValueSetter; procedure SetValue( Value: Integer ); end; TValueSetter = record class function Int: TIntValueSetter; static; end; { TValueSetter } class function TValueSetter.Int: TIntValueSetter; begin SetLength( Result.FValues, 0 ); end; { TIntValueSetter } function TIntValueSetter.AddVar( var Value: Integer ): TIntValueSetter; var LValues: TPIntArray; LIdx: Integer; begin SetLength( LValues, Length( FValues ) + 1 ); for LIdx := low( FValues ) to high( FValues ) do LValues[ LIdx ] := FValues[ LIdx ]; LValues[ high( LValues ) ] := @Value; Result.FValues := LValues; end; procedure TIntValueSetter.SetValue( Value: Integer ); var LIdx: Integer; begin for LIdx := low( FValues ) to high( FValues ) do FValues[ LIdx ]^ := Value; end; procedure SetValue( Values: array of Integer; Value: Integer = 0 ); var LIdx: Integer; begin for LIdx := low( Values ) to high( Values ) do Values[ LIdx ] := Value; end; procedure Test; var Val1, Val2, Val3: Integer; TargetValue: Integer; Set1, Set2, Set3: TIntValueSetter; begin Val1 := 42; Val2 := 84; Val3 := 34; TargetValue := 0; TValueSetter.Int.AddVar( Val1 ).AddVar( Val2 ).AddVar( Val3 ).SetValue( TargetValue ); Assert( ( Val1 = TargetValue ) and ( Val2 = TargetValue ), 'Mist, hat nicht funktioniert' ); Set1 := TValueSetter.Int.AddVar( Val1 ).AddVar( Val2 ); Set2 := TValueSetter.Int.AddVar( Val2 ).AddVar( Val3 ); Set3 := TValueSetter.Int.AddVar( Val1 ).AddVar( Val2 ).AddVar( Val3 ); WriteLn( 'Set1.SetValue( 1 )' ); Set1.SetValue( 1 ); WriteLn( 'Val1: ', Val1, ' Val2: ', Val2, ' Val3: ', Val3 ); WriteLn; WriteLn( 'Set2.SetValue( 2 )' ); Set2.SetValue( 2 ); WriteLn( 'Val1: ', Val1, ' Val2: ', Val2, ' Val3: ', Val3 ); WriteLn; WriteLn( 'Set3.SetValue( 3 )' ); Set3.SetValue( 3 ); WriteLn( 'Val1: ', Val1, ' Val2: ', Val2, ' Val3: ', Val3 ); end; |
AW: array als var-Parameter
Zitat:
Ich wollte eigendlich nur ein paar Variablen auf 0 setzen. :o Bei deinen Antworten bin ich immer wieder erstaunt. |
AW: array als var-Parameter
Zitat:
Und wenn ich an mehr als einer Stelle die Werte setzen muss, dann ist so ein Wrapper doch etwas Feines und wandert in die hauseigene Bibliothek. Dann brauchst man nur noch die Unit einbinden und benutzt es. Das ist allemal besser als in jedem Programm immer wieder das Gleiche zu schreiben ;) |
AW: array als var-Parameter
Also ich mache das seit Jahren so (siehe unten). Entweder ich mache es falsch oder ich habe hier einige Posts nicht verstanden.
Delphi-Quellcode:
Oder so:
type
TTest = array of Integer; procedure Abc(var ATest: TTest); begin ATest[0] := 10; ATest[1] := 20; end; procedure TForm1.Button1Click(Sender: TObject); var Test: TTest; begin SetLength(Test, 2); Test[0] := 1; Test[1] := 2; Abc(Test); ShowMessage(IntToStr(Test[0] + Test[1])); end;
Delphi-Quellcode:
type
TTest = array[0..1] of Integer; procedure Abc(var ATest: TTest); begin ATest[0] := 10; ATest[1] := 20; end; procedure TForm1.Button1Click(Sender: TObject); var Test: TTest; begin Test[0] := 1; Test[1] := 2; Abc(Test); ShowMessage(IntToStr(Test[0] + Test[1])); end; |
AW: array als var-Parameter
Zitat:
Du hast es falsch verstanden (siehe ![]() Nicht die Werte im Array sollen auf 0 gesetzt werden sondern die Variablen über die die Werte an das Array übergeben werden sollen auf 0 gesetzt werden. |
AW: array als var-Parameter
Achso, ok.
|
AW: array als var-Parameter
Nur mal so zum neidisch sein :stupid:
Code:
inline void zeroVars() {}
template<class Arg, class... Args> inline void zeroVars(Arg& arg, Args&... args) { arg = 0; zeroVars(args...); } ![]() |
AW: array als var-Parameter
Zitat:
Du hast vollkommen recht. War auch nicht negativ gemeint. Dennoch musste ich erst zwei mal schauen. Bei näherem hinsehen allergings ne tolle Lösung. :thumb: |
AW: array als var-Parameter
OT:
Zitat:
Delphi-Quellcode:
Das ist nicht aufwendiger als
var1=var2=var3=var4=var5=0;
Delphi-Quellcode:
und man sieht unmittelbar, was gemacht wird.
zeroVars(var1,var2,var3,var4,var5);
|
AW: array als var-Parameter
Zitat:
Allerdings wieder einmal ein schönes Beispiel dafür, wie man eingentlich unnötig Speicher und Rechenleistung verschwenden kann, wenn man den Code wirklich näher betrachtet. Und wirklich besser aussehen, oder lesbarer ist die Aufrufzeile auch nicht.
Delphi-Quellcode:
TValueSetter.Int.AddVar( Val1 ).AddVar( Val2 ).AddVar( Val3 ).SetValue( TargetValue );
Delphi-Quellcode:
Und intern machen die Funktionen dann auch nichts anderes als einen Zeiger übergeben, welcher dann dereferenziert wird um den neuen Wert zu setzen.
SetToZero([@Val1,@Val2]);
Es ist eben auch Geschmacksache, ob man lieber 1 Klasse + 2 Records + 4 Funktionen deklariert und schreibt, als 1 Funktion, welche 5 Zeilen umfasst und das gleiche ohne unnötige Zwischenschritte macht. |
AW: array als var-Parameter
Zitat:
![]() |
AW: array als var-Parameter
Zitat:
![]() |
AW: array als var-Parameter
|
AW: array als var-Parameter
Overengineering 500 bitte... :shock:
Zur Eingangsfrage: warum hast du einzelne Variablen, die offensichtlich zusammen gehören (sonst würdest du sie ja nicht gemeinsam auf 0 setzen wollen). Wenn sie zusammen gehören, dann pack sie in ein Array oder einen Record und wuppdi, kannst die auch mit einem beherzten Einzeiler nullen. |
AW: array als var-Parameter
Zitat:
|
AW: array als var-Parameter
Zitat:
Delphi-Quellcode:
Vorteil wäre auch, dass Du Dir die eckigen Klammern beim Aufruf der Procedure sparen kannst.
procedure ToZ (var i1, i2:Integer); overload;
procedure ToZ (var i1, i2, i3: Integer); overload; procedure ToZ (var i1, i2, i3, i4: Integer); overload; implementation procedure ToZ (var i1, i2:Integer); overload; begin i1 := 0; i2 := 0; end; procedure ToZ (var i1, i2, i3: Integer); overload; begin i1 := 0; i2 := 0; i3 := 0; end; procedure ToZ (var i1, i2, i3, i4: Integer); overload; begin i1 := 0; i2 := 0; i3 := 0; i4:= 0; end; // ... Programmablauf var itest1, itest2, itest3, itest4: Integer; begin iTest1 := 10; iTest2 := 20; iTest3 := 30; iTest4 := 40; ToZ (iTest1,iTest2); // gültiger Aufruf mit 2 Parametern ToZ (iTest1,iTest2,iTest3,iTest4); // gültiger Aufruf mit 4 Parametern |
AW: array als var-Parameter
Hallo,
ich werfe mal in dein Raum, dass die Variablen vielleicht schon mit 0 initialisiert sind. Übrigens funktionieren die Generics-Beispiele in D2007 noch nicht. Heiko |
AW: array als var-Parameter
Der Thread ist geil: Wir diskutieren, wie man Variablen initialisiert und schreiben sogar eine Klasse dafür.
Mir geht es in der Programmierung darum, eine Lösung einfach darzustellen. Einfach, klar und verständlich. Wenn ich einmal 20 Variablen auf 0 setzen muss (private property backing stores z.B.), dann schreibe ich mir eine private Methode 'InitializeValues' und dann besteht diese Methode eben aus 20 Zeilen 'Foo := 0'. Wo ist das Problem? Das ist die einfachste, klarste und direkteste Form, Variablen auf 0 zu setzen. Als nächstes kommt jemand noch auf die Idee und will eine For-Schleife in eine Klasse packen, um diese dann per fluent-Interface ineinander zu schachteln. Kann man ja wiederverwenden. Na ja. Nette Übung jedenfalls. |
AW: array als var-Parameter
Zitat:
|
AW: array als var-Parameter
Zitat:
Etwas zum Hintergrund: Ich räume so nach und nach den Code von einem gewachsenen Programm auf.(Projekte und Units sind teilweise >15 Jahre alt). Man glaubt gar nicht, welche Mist man so mit der Zeit programmiert hat. Früher war ich stolz darauf, wenn ich sagen konnte "Mein Projekt hat mehrere 100.000 Zeilen". Mittlerweile bin ich stolz darauf, wenn ich sagen kann, "Ich habe die Anzahl der Codezeilen geschrumpft". Um zum Thema zurück zu kommen: Es fällt auf, daß es immer mal wieder solche Konstrukte gibt, in denen 2-4 lokale lokale Variablen auf einen vorgegebenen Wert gesetzt werden. Diese vier Zeilen möchte ich auf eine Zeile schrumpfen. Die Variablen haben natürlich immer mal wieder andere Namen, daher ist die Idee mit dem Record für mich nicht anwendbar. |
AW: array als var-Parameter
Zitat:
|
AW: array als var-Parameter
Zitat:
Ja. Hätte ich mir auch nie vorstellen können, so eine Frage zu stellen. Aber manchmal sind die einfachsten Sachen do nicht so trivial, wie man denkt. Es geht ja auch nicht darum, wie und warum man Variablen initialisiert, sondern wie macht man es am effektivsten. Und es ist sehr interessant, welche unterschiedlichsten Ansätze es gibt. Deshalb finde ich solche Threads besonders lesenswert. |
AW: array als var-Parameter
Zitat:
Das macht das Ganze recht flexibel. |
AW: array als var-Parameter
Zitat:
SirRufos Ansatz ist auch gut. Zumal man ein Set von Variablen vordefinieren kann. Aber irgendwie auch nicht so gut zu lesen. Aber das ist Geschmacksache. So. Danke für euere Antworten! |
AW: array als var-Parameter
So ist es noch etwas flexibler:
Delphi-Quellcode:
Als Standard wird 0 gesetzt, ansonsten der übergebene Wert im optionalen Parameter 2
procedure SetVariableToValue(APointers: Array of PInteger; AValue: Integer = 0);
var liZ1: Integer; begin for liZ1 := 0 to High(APointers) do begin APointers[liZ1]^ := AValue; end; end; |
AW: array als var-Parameter
Zitat:
Jeder hier hat in seinem Projekt Code bei dem er die Variablen hin und wieder mal löschen muss. In dem Fall wird entweder in der Prozedur jede Variable wieder auf Null gesetzt oder, falls es öfters im Code vorkommt, wird die Routine ausgelagert. Aber nach 15 Jahre Erfahrung sich nun eine Zauberprozedur wünschend in die man alle Variablen als Parameter übergibt und die genullt zurück kommen, also da stellt sich die Frage ob man mit Pascal sich für die richtige Programmiersprache entschieden hat. Auf der anderen Seite, nichts ist unmöglich und alles läßt sich programmieren. Nur ich weiß nicht, wie oft hat man ein Programm wo man in Massen Variablen nullen muss? Also wenn ich mar alle meine Programme zurück denke, dann kommen mal gelegentlich zwei Variablen vor die ich nullen muss. Das wars dann aber auch. Ich meine, schließlich gibt es sowas wie Prozeduren und Funktionen. Da gibt es immer paar Variablen. Die löscht man so nebenbei oder die werden bei Parameterübergabe genullt. |
AW: array als var-Parameter
Zitat:
Es geht hier nicht um Massen oder fest festgelegte Variablen nur auf 0 zu stellen. Mit dieser Funktion hast Du zum Beispiel die Möglichekeit beliebige (und nicht immer die gleichen) Variablen, welche von Dir, oder auch vom Programm selbst ausgewählte Variablen in einer einzigen Funktion mit einem variablen Wert zu belegen. Und dies in einer absolut flexiblen Gestaltung, durch zum Beispiel die Verwendung von Zeigern. |
AW: array als var-Parameter
Zitat:
Geld- oder Wertpaierbuchungs unterschiedlicher Datenlieferanten kommen mit den verschiedensten Vorzeichenregelungen. - Alle Beträge vorzeichenlos. Das Vorzeichen ergibt sich dann aus der Buchungsart: Einzahlung, Auszahlung, Kauf, Verkauf... sowie die jeweiligen Stornierungen. - Vorzeichen wird durch Buchungsrichtung bestimmt - Vorzeichen wird durch Buchungsrichtung und Storno bestimmt. ...und in den chaotischeren Schnittstellen ist die Vorzeichenregelung innerhalb der Schnittstelle nicht konsistent. Ganz großartig. :stupid: Jedenfalls müssen die gelieferten Vorzeichen auf unsere interne Vorzeichenregelung gebracht werden. Dafür habe ich testweise eine Funktion ChangeSign gebaut, die ein offenes Array aufnimmt. Sieht im Prinzip genau so aus wie bei Neutral General, nur daß mein Array nicht typisiert ist und ich auf Move zurückgreifen mußte, weil ich es nicht anders hinbekam. :cry:
Delphi-Quellcode:
procedure ChangeSign(Args: array of pointer);
var i: integer; d: double; begin for i := low(Args) to high(Args) do begin d := -1 * double(Args[i]^); Move(d, Args[i]^, sizeof(d)); end; end; Zitat:
Siehe Barry Kellys Antwort zu ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:22 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz