Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Record als Result einer Funktion (https://www.delphipraxis.net/203816-record-als-result-einer-funktion.html)

NoGAD 27. Mär 2020 13:44

Record als Result einer Funktion
 
Hallo,

wenn ich einen Record deklariere und diesen dann einer Funktion als Result zuordne, werden alle Werte innerhalb des Records auf True gesetzt.

Warum, weiß ich nicht.

Hier ein Beispiel:

Code:
type
  TTest_Result = record
    Test_a : Boolean;
    Test_b : Boolean;
    Test_c : Boolean;
  end;


  function test(a:integer):TTest_Result;

  function test(a:integer):TTest_Result;
  begin
    Result.Test_a := True;
  end;
Rufe ich die funktion nun auf, ist alles vom Result auch True.

Eine Zuweisung mittels Result.Test_b := False; z.B. innerhalb der function oder vorher aus dem Aufruf der function heraus, bringt auch nichts.


Warum passiert das und wie behebe ich diesen Fehler?

LG Mathias

DieDolly 27. Mär 2020 14:03

AW: Record als Result einer Funktion
 
Versuch mal so. Funktioniert bei mir wie gewünscht
Booleans sind, wenn sie vorher nicht initialisiert werden, immer auf True. Jedenfalls bei MIR unter 10.3.3.
Delphi-Quellcode:
function test: TTest_Result;
begin
 Result.Test_a := True;
 Result.Test_b := False;
 Result.Test_c := True;
end;
// was du in der Funktion test am Ende machst, bleibt dir überlassen

procedure TForm1.Button2Click(Sender: TObject);
var
 X: TTest_Result;
begin
 X := test;

 showmessage(
  BoolToStr(X.Test_a, True)+sLineBreak+
  BoolToStr(X.Test_b, True)+sLineBreak+
  BoolToStr(X.Test_c, True)
 );
end;

Dennis07 27. Mär 2020 14:06

AW: Record als Result einer Funktion
 
Kann diesen Fehler nicht reproduzieren. Das Problem muss also wo anders liegen. Bei mir Funktioniert der von dir aufgeführte Code problemlos, und es wird
Delphi-Quellcode:
(True, False, False).
zurückgegeben.

DieDolly 27. Mär 2020 14:08

AW: Record als Result einer Funktion
 
Zitat:

Das Problem muss also wo anders liegen.
Zitat:

Eine Zuweisung mittels Result.Test_b := False; z.B. innerhalb der function oder vorher aus dem Aufruf der function heraus, bringt auch nichts.
Zeig mal den Aufruf.

Dennis07 27. Mär 2020 14:11

AW: Record als Result einer Funktion
 
Zitat:

Zitat von DieDolly (Beitrag 1460627)
Booleans sind, wenn sie vorher nicht initialisiert werden, immer auf True. Jedenfalls unter 10.3.3.

WAS? Also ich habs grad mal unter 10.3.2 getestet, und da ist es immer
Delphi-Quellcode:
False
. Außerdem werden initialisierte Variablen immer mit 0 beschrieben, so ist das auch in der aktuellen OH nachzulesen.

Habe gerade kein 10.3.3 zur Hand, wäre aber definitiv ein Bug, wenn es so wie von dir beschrieben sich verhält.

Uwe Raabe 27. Mär 2020 14:12

AW: Record als Result einer Funktion
 
Da du den anderen Feldern von result keine Werte zuweist, ist deren Inhalt eher zufällig.

DieDolly 27. Mär 2020 14:13

AW: Record als Result einer Funktion
 
Zitat:

Also ich habs grad mal unter 10.3.2 getestet
Du: 10.3.2
Ich: 10.3.3.

Vielleicht gibt es da Unterschiede oder einen Bug. Ich hatte immer alle auf True, obwohl ich persönlich eher False erwartet hätte.

Dennis07 27. Mär 2020 14:14

AW: Record als Result einer Funktion
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1460633)
Da du den anderen Feldern von result keine Werte zuweist, ist deren Inhalt eher zufällig.

Kommt auf die Variable an...

DieDolly 27. Mär 2020 14:15

AW: Record als Result einer Funktion
 
Um das abzukürzen und nicht 10 Seiten an Diskussionen zu erzeugen:

einfach alles initialisieren oder setzen. Dann gibt es auch kein Problem.
Aber bevor wir hier nicht sehen wie test() aufgerufen wird, kann man eh nix sagen.

Dennis07 27. Mär 2020 14:16

AW: Record als Result einer Funktion
 
Zitat:

Zitat von DieDolly (Beitrag 1460634)
Vielleicht gibt es da Unterschiede oder einen Bug. Ich hatte immer alle auf True, obwohl ich persönlich eher False erwartet hätte.

Bei automatisch initialisierten Variablen? Denn die müssten immer False sein.
Ansonsten ist der Wert halt zufällig, und da alles außer 0 als
Delphi-Quellcode:
True
ausgewertet wird, erhältst du halt meistens das. Das wäre in dem Fall aber immer noch Zufall und nichts, auf das du dich verlassen kannst/solltest!

EDIT: (kleine Ergänzung):
Automatisch initialisierte Variablen sind Strings, dynamische Arrays, Objektfelder und globale Variablen.

DieDolly 27. Mär 2020 14:17

AW: Record als Result einer Funktion
 
Zitat:

Das wäre in dem Fall aber immer noch Zufall und nichts, auf das du dich verlassen kannst/solltest!
Deswegen sollte man auch immer alles brav selber initialisieren.

himitsu 27. Mär 2020 14:22

AW: Record als Result einer Funktion
 
Dieser Record (über 4 Byte) wird, wie auch bei Strings, DynArrays, Interfaces und alle Typen größer als 4 Byte (NativeInt/Pointer) als VAR-Para,eter durchgereicht.

Die Initialisierung hängt also vom Aufrufer ab und dort ist es meistens eine lokale Variable in einer Prozedur.
Auch in einer Schleife (For/Repeat) ist sowas selten so initialisiert, wie du es denkst.

Dennis07 27. Mär 2020 14:23

AW: Record als Result einer Funktion
 
Zitat:

Zitat von DieDolly (Beitrag 1460638)
Deswegen sollte man auch immer alles brav selber initialisieren.

Da bin ich absolut deiner Meinung. Wollte nur sagen, dass du dich halt nicht darauf verlassen kannst, da sie halt nicht zwingend
Delphi-Quellcode:
True
sein müssen, sondern es nur meistens halt durch Zufall bei dir waren.

NoGAD 27. Mär 2020 18:28

AW: Record als Result einer Funktion
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe mal mein Testprojekt angehängt.

Bitte nicht wundern, wenn hier und da noch etwas im Code technisch nicht ganz sauber ist.


Code:
procedure init_Result( var _Result : TDB_Result );
  begin

>> Hier mal ein Exit; rein machen und bitte testen.
Mit dieser Hilfsprocedure klappt es nun auch.

Als Fremdkomponenten benutze ich ABSDatabase, ABSQuery, ABSTable.

LG Mathias



Edit: Quellcode hinzugefügt

Code:
unit Unit1;

interface

uses
  Unit_ABS_DBFunctions,

  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Data.DB,
  ABSMain,
  Vcl.Grids,
  Vcl.DBGrids,
  Vcl.StdCtrls;

type
  TForm1 = class( TForm )
    DBGrid1 : TDBGrid;
    ABSDatabase1 : TABSDatabase;
    ABSTable1 : TABSTable;
    DataSource1 : TDataSource;
    Button1 : TButton;
    ABSQuery1 : TABSQuery;
    Button2 : TButton;
    Button3 : TButton;
    Memo1 : TMemo;
    Button4 : TButton;
    Button5 : TButton;
    Button6 : TButton;
    procedure Button1Click( Sender : TObject );
    procedure Button3Click( Sender : TObject );
    procedure Button4Click( Sender : TObject );
    procedure Button2Click( Sender : TObject );
    procedure FormCreate( Sender : TObject );
    procedure Button5Click( Sender : TObject );
    procedure Button6Click( Sender : TObject );
    private
      { Private-Deklarationen }
    public
      { Public-Deklarationen }
  end;

var
  Form1 : TForm1;
  a_SelfPath : string;
  { Datenbankpfad }
  a_DataBasePath : string;
  a_DatabaseFileName : string;

const

  DatabaseFileName = 'test_db';
  DatabaseExt = '.trm';
  DatabaseName = 'DB';

  { Fields Table Test }
  TableName_Test = 'test_table';
  Labels_DB : TArray< string > = [ 'nummer', 'spalte2', 'spalte3', 'spalte4', 'spalte5', 'ALF', 'eeeeeee' ];
  Labels_DB_Type_Query : TArray< string > = [ 'AUTOINC NOT NULL', 'VARCHAR(%d) NOT NULL', 'VARCHAR(%d)', 'VARCHAR(%d)', 'VARCHAR(%d)', 'VARCHAR(%d)', 'AUTOINC' ];
  Labels_DB_Size_Query : TArray< Integer > = [ 0, 2, 2, 4, 2, 2, 0 ];
  Indizes_DB_Query_n : TArray< TArray< string > > = [ [ 'pk_number', 'CREATE UNIQUE INDEX pk_number ON test_table (nummer);' ], [ 'i_spalte2', 'CREATE INDEX i_spalte2 ON test_table (spalte2,spalte3 );' ], [ 'i_spalte4', 'CREATE INDEX i_spalte4 ON test_table (spalte2,spalte3 );' ], [ 'i_spalte3', 'CREATE INDEX i_spalte3 ON test_table (spalte2,spalte3 );' ] ];

implementation

{$R *.dfm}

procedure TForm1.Button1Click( Sender : TObject );
  var
    i : Integer;
  begin

    if trim( ABSDatabase1.DatabaseFileName ) <> '' then
      if ( FileExists( ABSDatabase1.DatabaseFileName ) ) then
        if trim( ABSTable1.TableName ) <> '' then
          if ABSTable1.Database.Exists then
            try
              ABSTable1.FieldDefs.BeginUpdate;
              ABSTable1.DisableControls;
              for i := 1 to 7 do
              begin
                ABSTable1.Append;
                ABSTable1.FieldByName( Labels_DB[ 1 ] ).AsInteger := random( 300 ) + 1700;
                ABSTable1.FieldByName( Labels_DB[ 2 ] ).AsInteger := random( 300 ) + 1700;
                ABSTable1.FieldByName( Labels_DB[ 3 ] ).AsInteger := random( 300 ) + 1700;
                ABSTable1.FieldByName( Labels_DB[ 4 ] ).AsString := format( '%d,%2.2d', [ random( 50 ) + 5, random( 99 ) ] );
                ABSTable1.FieldByName( Labels_DB[ 5 ] ).AsString := '5';
                ABSTable1.Post;
              end;
              ABSTable1.EnableControls;
              ABSTable1.FieldDefs.EndUpdate;
            finally
              Memo1.Lines.Add( '' );
              Memo1.Lines.Add( '- Datensätze wurden hinzugefügt -' );
            end;

    if ( trim( ABSDatabase1.DatabaseFileName ) = '' ) or ( not FileExists( ABSDatabase1.DatabaseFileName ) ) then
    begin
      Memo1.Lines.Add( '' );
      Memo1.Lines.Add( '- Keine Datenbank vorhanden - ' );
      Memo1.Lines.Add( '(Kann keine Daten hinzufügen)' );
    end;

    if ( trim( ABSTable1.TableName ) = '' ) or ( not ABSTable1.Database.Exists ) then
    begin
      Memo1.Lines.Add( '' );
      Memo1.Lines.Add( '- Keine Tabelle vorhanden - ' );
      Memo1.Lines.Add( '(Kann keine Daten hinzufügen)' );
    end;

  end;

procedure TForm1.Button2Click( Sender : TObject );
  var
    DB_Result : TDB_Result;
  begin

    a_SelfPath := IncludeTrailingPathDelimiter( ExtractFilePath( ParamStr( 0 ) ) );
    a_DataBasePath := a_SelfPath;
    a_DatabaseFileName := a_DataBasePath + DatabaseFileName + DatabaseExt;

    init_Result( DB_Result );

    DB_Result := init_DatabaseABS( ABSDatabase1, ABSTable1, ABSQuery1, a_DatabaseFileName, DatabaseName );
    Memo1.Lines.Add( '' );
    if DB_Result.Create_Database then
      Memo1.Lines.Add( '- Datenbank wird neu erstellt -' );
    if DB_Result.Open_DataBase then
      Memo1.Lines.Add( '- Datenbank ist vorhanden, wird geöffnet -' );

    DB_Result := init_TableABS_Query( ABSDatabase1, ABSTable1, ABSQuery1, TableName_Test, Labels_DB, Labels_DB_Type_Query, Labels_DB_Size_Query, Indizes_DB_Query_n );
    Memo1.Lines.Add( '' );
    if DB_Result.Create_Table then
      Memo1.Lines.Add( '- Tabelle wurde neu erstellt -' );
    if DB_Result.Open_Table then
      Memo1.Lines.Add( '- Tabelle war vorhanden, wurde geöffnet -' );
    if DB_Result.Add_Table then
      Memo1.Lines.Add( '- Tabelle wurde hinzugefügt -' );
    if DB_Result.Create_Field then
      Memo1.Lines.Add( '- Feld(er) wurde(n) zur Tabelle hinzugefügt -' );
    if DB_Result.Change_Field then
      Memo1.Lines.Add( '- Feld(er) in der Tabelle wurde(n) aktualisiert -' );
    if DB_Result.Delete_Field then
      Memo1.Lines.Add( '- Felde(r) in der Tabelle wurde(n) gelöscht -' );
    if DB_Result.Create_Index then
      Memo1.Lines.Add( '- Index/Indizes wurde(n) neu erstellt -' );
    if DB_Result.Add_Index then
      Memo1.Lines.Add( '- Index/Indizes wurde(n) hinzugefügt -' );
    if DB_Result.Change_Index then
      Memo1.Lines.Add( '- Index/Indizes wurde(n) aktualisiert -' );
    if DB_Result.Rebuild_Index then
      Memo1.Lines.Add( '- Index/Indizes wurde(n) neu aufgebaut -' );

  end;

procedure TForm1.Button3Click( Sender : TObject );
  begin

    ABSTable1.Close;
    ABSQuery1.Close;
    ABSDatabase1.Close;
    ABSTable1.IndexDefs.Clear;
    ABSQuery1.IndexDefs.Clear;

    ABSDatabase1.DeleteDatabase;
    Memo1.Lines.Add( '' );
    Memo1.Lines.Add( '- Datenbank wurde gelöscht -' );

  end;

procedure TForm1.Button4Click( Sender : TObject );
  var
    x : Integer;
  begin

    if trim( ABSDatabase1.DatabaseFileName ) <> '' then
      if ( FileExists( ABSDatabase1.DatabaseFileName ) ) then
        if trim( ABSTable1.TableName ) <> '' then
          if ABSTable1.Database.Exists then
            try
              ABSTable1.IndexDefs.Update;
            finally
              Memo1.Lines.Add( '' );
              Memo1.Lines.Add( 'Indexfields:' );
              for x := 0 to pred( ABSTable1.IndexDefs.Count ) do
                Memo1.Lines.Add( format( '%s[%d] (%d): %s', [ 'Indexname', x, Succ( x ), ABSTable1.IndexDefs[ x ].Name ] ) );
            end;

    if ( trim( ABSDatabase1.DatabaseFileName ) = '' ) or ( not FileExists( ABSDatabase1.DatabaseFileName ) ) then
    begin
      Memo1.Lines.Add( '' );
      Memo1.Lines.Add( '- Keine Datenbank vorhanden - ' );
      Memo1.Lines.Add( '(Kann keine Idexfelder abrufen)' );
    end;

    if ( trim( ABSTable1.TableName ) = '' ) or ( not ABSTable1.Database.Exists ) then
    begin
      Memo1.Lines.Add( '' );
      Memo1.Lines.Add( '- Keine Tabelle vorhanden - ' );
      Memo1.Lines.Add( '(Kann keine Idexfelder abrufen)' );
    end;

  end;

procedure TForm1.Button5Click( Sender : TObject );
  begin

    Memo1.Lines.Clear;

  end;

procedure TForm1.Button6Click( Sender : TObject );
  var
    x : Integer;
  begin
    if trim( ABSDatabase1.DatabaseFileName ) <> '' then
      if ( FileExists( ABSDatabase1.DatabaseFileName ) ) then
        if trim( ABSTable1.TableName ) <> '' then
          if ABSTable1.Database.Exists then
            try
              ABSTable1.IndexDefs.Update;
            finally
              Memo1.Lines.Add( '' );
              Memo1.Lines.Add( 'FieldTypes:' );
              for x := 0 to pred( ABSTable1.FieldDefs.Count ) do
                Memo1.Lines.Add( format( '%s[%d]: %s | %s: %s(%d)', [ 'FieldName', x, ABSTable1.FieldDefs[ x ].Name, 'FieldType:', FieldTyp2String( ABSTable1.Fields[ x ].DataType ), ABSTable1.Fields[ x ].Size ] ) );
            end;

    if ( trim( ABSDatabase1.DatabaseFileName ) = '' ) or ( not FileExists( ABSDatabase1.DatabaseFileName ) ) then
    begin
      Memo1.Lines.Add( '' );
      Memo1.Lines.Add( '- Keine Datenbank vorhanden - ' );
      Memo1.Lines.Add( '(Kann keine FeldTypen abrufen)' );
    end;

    if ( trim( ABSTable1.TableName ) = '' ) or ( not ABSTable1.Database.Exists ) then
    begin
      Memo1.Lines.Add( '' );
      Memo1.Lines.Add( '- Keine Tabelle vorhanden - ' );
      Memo1.Lines.Add( '(Kann keine FeldTypen abrufen)' );
    end;

  end;

procedure TForm1.FormCreate( Sender : TObject );
  begin

    Button5Click( nil );
    // Button2Click( nil );
    // Button4Click( nil );

  end;

end.

Code:
unit Unit_ABS_DBFunctions;

interface

uses

  ABSSecurity,
  ABSMain,
  Data.DB,
  System.Classes,
  System.StrUtils,
  System.Sysutils,
  System.TypInfo,
  System.UITypes,
  Vcl.Controls,
  Vcl.Dialogs;

{ Datenbank-Rückgabe Ergebnisse von Funktionen }
type
  TDB_Result = record
    Open_DataBase : Boolean;
    Create_Database : Boolean;

    Open_Table : Boolean;
    Create_Table : Boolean;
    Add_Table : Boolean;

    Create_Field : Boolean;
    Add_Field : Boolean;
    Change_Field : Boolean;
    Delete_Field : Boolean;

    Create_Index : Boolean;
    Add_Index : Boolean;
    Change_Index : Boolean;
    Rebuild_Index : Boolean;

    RestructureResult : Boolean;
  end;

type
  TDB_Settings = record
    Show_Errors : Boolean;
    Show_Questions : Boolean;
    Delete_Fields : Boolean;
  end;

var
  DB_Settings : TDB_Settings;

const
  BR = #10#13;
  DBR = BR + BR;

  Question_Restructure_Table1 = 'Ein Programmupdate wurde kürzlich installiert. Die Datenbank ''%s'' muss aktualisiert werden. Dieser Vorgang kann länger dauern.';
  Question_Restructure_Table2 = '!! Befolgen Sie diesen Hinweis unbedingt !!' + DBR + 'Bitte beenden Sie das Programm nicht, auch wenn es aussieht, als würde es festhängen. Bitte melden Sie keinen weiteren Benutzer im Netzwerk an.' + DBR + 'Die Datenbank kann sonst beschädigt werden.';

  Error_C_DB_Create = 'Fehler: Datenbank [%s] konnte nicht erstellt werden!';
  Error_C_Table_Open = 'Die Tabelle [%s] konnte nicht geöffnet werden.';
  Error_C_Table_Create = 'Die Tabelle [%s] konnte nicht erstellt werden!';
  Error_C_Index_Rebuild = 'Indexfehler beim Neuaufbeu in Tabelle [%s]!';
  Error_C_Table_Restructure_AddField = 'Fehler bei der Restrukturierung. Das Tabellenfeld [%s] konnte nicht zur Tabelle [%s] hinzugefügt werden.';
  Error_C_Table_DropField = 'Fehler beim Löschen von Tabellenfeld [%s] in Tabelle [%s]!';
  Error_C_Table_Change_TypeSize = 'Fehler beim Ändern eines FeldTypes oder Feldgröße im Feld [%s]. Betrifft Tabelle [%s]!';

  Question_C_Table_FieldSize = 'Ein bestehendes Feld [%s] soll verkleinert werden. Dadurch kann es zu Datenverlust kommen. Soll der Vorgang fortgesetzt werden?';

procedure init_Result( var _Result : TDB_Result );
function FieldTyp2String( _ft : TFieldType ) : string;
function init_DatabaseABS( _DataBase : TABSDatabase; _Table : TABSTable; _Query : TABSQuery; _DatabaseFileName : string; _DatabaseName : string; _MultiUser : Boolean = True; _Encrypted : Boolean = False; _CryptoAlgorithm : TABSCryptoAlgorithm = craRijndael_256; _CryptoPassword : string = ''; _PageSize : Integer = 128; _PageCountInExtent : Integer = 8; _MaxConnections : Integer = 483 ) : TDB_Result;
function init_TableABS_Query( _DataBase : TABSDatabase; _Table : TABSTable; _Query : TABSQuery; _Table_Name : string; _Labels_DB : TArray< string >; _Labels_DB_Type_Query : TArray< string >; _Labels_DB_Size_Query : TArray< Integer >; _Indizes_DB_Query : TArray< TArray< string > > ) : TDB_Result;
function Restructure_Table_Query( _DataBase : TABSDatabase; _Query : TABSQuery; _Table_Name : string; _Labels_DB : TArray< string >; _Labels_DB_Type_Query : TArray< string >; _Labels_DB_Size_Query : TArray< Integer >; _Indizes_DB_Query : TArray< TArray< string > > ) : TDB_Result;
function Create_Table_Query( _Table : TABSTable; _Query : TABSQuery; _Table_Name : string; _Labels_DB : TArray< string >; _Labels_DB_Type_Query : TArray< string >; _Labels_DB_Size_Query : TArray< Integer > ) : TDB_Result;
function Index_Exists( _Table : TABSTable; const _IndexName : string ) : Boolean;
function Rebuild_Index_Query( _Table : TABSTable; _Query : TABSQuery; _Labels_DB : TArray< string >; _Labels_DB_Type_Query : TArray< string >; _Indizes_DB_Query : TArray< TArray< string > > ) : TDB_Result;

implementation

procedure init_Result( var _Result : TDB_Result );
  begin

>> Hier mal ein Exit; rein machen und bitte testen.

    _Result.Open_DataBase := False;
    _Result.Create_Database := False;

    _Result.Open_Table := False;
    _Result.Create_Table := False;
    _Result.Add_Table := False;

    _Result.Create_Field := False;
    _Result.Add_Field := False;
    _Result.Change_Field := False;
    _Result.Delete_Field := False;

    _Result.Create_Index := False;
    _Result.Add_Index := False;
    _Result.Change_Index := False;
    _Result.Rebuild_Index := False;

    _Result.RestructureResult := False;

  end;

function FieldTyp2String( _ft : TFieldType ) : string;
  begin

    case _ft of
      ftAutoinc : Result := 'AUTOINC';
      ftBlob : Result := 'BLOB';
      ftBytes : Result := 'BYTES';
      ftCurrency : Result := 'CURRENCY';
      ftDate : Result := 'DATE';
      ftDateTime : Result := 'DATETIME';
      ftFloat : Result := 'FLOAT';
      ftFmtMemo : Result := 'FORMATTEDMEMO';
      ftGraphic : Result := 'GRAPHIC';
      ftGUID : Result := 'GUID';
      ftInteger : Result := 'INTEGER';
      ftLargeInt : Result := 'LARGEINT';
      ftBoolean : Result := 'BOOLEAN';
      ftMemo : Result := 'MEMO';
      ftSmallint : Result := 'SMALLINT';
      ftString : Result := 'VARCHAR';
      ftFixedChar : Result := 'FIXEDCHAR';
      ftTime : Result := 'TIME';
      ftTimeStamp : Result := 'TIMESTAMP';
      ftVarBytes : Result := 'VARBYTES';
      ftWideString : Result := 'WIDESTRING';
      ftWord : Result := 'WORD'
      else Result := 'unbekannt';
    end;

  end;

function init_DatabaseABS( _DataBase : TABSDatabase; _Table : TABSTable; _Query : TABSQuery; _DatabaseFileName : string; _DatabaseName : string; _MultiUser : Boolean = True; _Encrypted : Boolean = False; _CryptoAlgorithm : TABSCryptoAlgorithm = craRijndael_256; _CryptoPassword : string = ''; _PageSize : Integer = 128; _PageCountInExtent : Integer = 8; _MaxConnections : Integer = 483 ) : TDB_Result;

  begin

    _DataBase.DatabaseName := _DatabaseName;
    _Table.DatabaseName := _DatabaseName;
    _Query.DatabaseName := _DatabaseName;

    _Table.Close;
    _Query.Close;
    _DataBase.Close;

    _DataBase.DatabaseFileName := _DatabaseFileName;
    try
      if ( not _DataBase.Exists ) or ( not Fileexists( _DataBase.DatabaseFileName ) ) then
      begin
        if _Encrypted and ( Length( Trim( _CryptoPassword ) ) > 0 ) then
        begin
          _DataBase.CryptoAlgorithm := _CryptoAlgorithm;
          _DataBase.Password := _CryptoPassword;
        end;
        _DataBase.CreateDatabase;
        Result.Create_Database := True;
      end;

      if _MultiUser then
        _DataBase.MultiUser := True;
      _DataBase.Open;
      Result.Open_DataBase := True;
    except
      if DB_Settings.Show_Errors then
        ShowMessage( Format( Error_C_DB_Create, [ _DatabaseName ] ) );
    end;

  end;

function init_TableABS_Query( _DataBase : TABSDatabase; _Table : TABSTable; _Query : TABSQuery; _Table_Name : string; _Labels_DB : TArray< string >; _Labels_DB_Type_Query : TArray< string >; _Labels_DB_Size_Query : TArray< Integer >; _Indizes_DB_Query : TArray< TArray< string > > ) : TDB_Result;
  begin

    _Table.Close;
    _Query.Close;

    _Table.TableName := _Table_Name;

    _Table.DatabaseName := _DataBase.DatabaseName;
    _Query.DatabaseName := _DataBase.DatabaseName;

    { Wenn schon vorhanden - öffnen und Feldprüfung }
    if _Table.Exists then
      try
        _Table.Close;
        Result := Restructure_Table_Query( _DataBase, _Query, _Table_Name, _Labels_DB, _Labels_DB_Type_Query, _Labels_DB_Size_Query, _Indizes_DB_Query );
        _Table.Open;
        _Table.Refresh;
        Result.Open_Table := True;
        if not Result.RestructureResult then
          Exit;
      except
        if DB_Settings.Show_Errors then
          ShowMessage( Format( Error_C_Table_Open, [ _Table_Name ] ) );
      end;

    { Wenn noch nicht vorhanden - erstellen }
    if not _Table.Exists then
      try
        Create_Table_Query( _Table, _Query, _Table_Name, _Labels_DB, _Labels_DB_Type_Query, _Labels_DB_Size_Query );
        _Table.Refresh;
        Result.Create_Table := True;
      except
        if DB_Settings.Show_Errors then
          ShowMessage( Format( Error_C_Table_Create, [ _Table_Name ] ) );
      end;

    { Alle Indizes (Index) - Suchfelder initialisieren }
    try
      Rebuild_Index_Query( _Table, _Query, _Labels_DB, _Labels_DB_Type_Query, _Indizes_DB_Query );
      Result.Rebuild_Index := True;
    except
      if DB_Settings.Show_Errors then
        ShowMessage( Format( Error_C_Index_Rebuild, [ _Table_Name ] ) );
    end;

  end;

function Restructure_Table_Query( _DataBase : TABSDatabase; _Query : TABSQuery; _Table_Name : string; _Labels_DB : TArray< string >; _Labels_DB_Type_Query : TArray< string >; _Labels_DB_Size_Query : TArray< Integer >; _Indizes_DB_Query : TArray< TArray< string > > ) : TDB_Result;
  var
    x : Integer;
    Dummy_Bool : Boolean;
    field_old_type, field_new_type : string;
    field_old_size, field_new_size : Integer;
  begin

    { Tabellenfelder prüfen, gegebenenfalls anlegen }
    for x := low( _Labels_DB ) to high( _Labels_DB ) do
    begin
      { Tabellenfeld hinzufügen, wenn es nicht existiert }
      try
        _Query.SQL.Text := 'ALTER TABLE ' + _Table_Name + ' ADD (IF NOT EXISTS ' + _Labels_DB[ x ] + ' ' + Format( _Labels_DB_Type_Query[ x ], [ _Labels_DB_Size_Query[ x ] ] ) + ');';
        _Query.ExecSQL;
        Result.Add_Field := True;
      except
        if DB_Settings.Show_Errors then
          ShowMessage( Format( Error_C_Table_Restructure_AddField, [ _Labels_DB[ x ], _Table_Name ] ) );
        Exit;
      end;
      { Tabellenfeld hinzufügen, wenn es nicht existiert }

      { Wenn Tabellenfeld falsches Format oder Größe hat }
      _Query.RequestLive := True;
      _Query.SQL.Text := 'SELECT * From ' + _Table_Name + ' WHERE 1 = 0';
      _Query.Open;
      field_old_type := FieldTyp2String( _Query.Fields[ x ].DataType );
      field_old_size := _Query.Fields[ x ].Size;

      if pos( #32, _Labels_DB_Type_Query[ x ] ) = 0 then
        field_new_type := _Labels_DB_Type_Query[ x ];
      if pos( #32, _Labels_DB_Type_Query[ x ] ) <> 0 then
        field_new_type := LeftStr( _Labels_DB_Type_Query[ x ], pos( #32, _Labels_DB_Type_Query[ x ] ) );

      field_new_size := _Labels_DB_Size_Query[ x ];
      Dummy_Bool := not ( ( field_new_size = field_old_size ) or ( field_new_size > field_old_size ) );
      if field_new_size < field_old_size then
        if DB_Settings.Show_Questions then
          Dummy_Bool := MessageDLG( Question_C_Table_FieldSize, mtConfirmation, mbYesNo, 0 ) = mrYes;
      if field_new_size < field_old_size then
        if not DB_Settings.Show_Questions then
          Dummy_Bool := True;

      if ( ( field_old_type <> field_new_type ) or ( field_old_size <> field_new_size ) ) and Dummy_Bool then
        try
          _Query.SQL.Text := 'ALTER TABLE ' + _Table_Name + ' MODIFY (' + _Labels_DB[ x ] + ' ' + Format( _Labels_DB_Type_Query[ x ], [ _Labels_DB_Size_Query[ x ] ] ) + ');';
          _Query.ExecSQL;
          Result.Change_Field := True;
        except
          if DB_Settings.Show_Errors then
            ShowMessage( Format( Error_C_Table_Change_TypeSize, [ _Labels_DB[ x ], _Table_Name ] ) );
          Exit;
        end;
      { Wenn Tabellenfeld falsches Format hat }
    end;

    { Felder löschen, die in der Deklaration nicht mehr existieren }
    if DB_Settings.Delete_Fields then
      for x := _Query.FieldDefs.Count - 1 downto 0 do
        if not MatchStr( _Query.FieldDefs.Items[ x ].Name, _Labels_DB ) then
          try
            _Query.SQL.Text := 'ALTER TABLE ' + _Table_Name + ' DROP COLUMN ' + _Query.FieldDefs.Items[ x ].Name + ';';
            _Query.ExecSQL;
            Result.Delete_Field := True;
          except
            if DB_Settings.Show_Errors then
              ShowMessage( Format( Error_C_Table_DropField, [ _Query.FieldDefs.Items[ x ].Name, _Table_Name ] ) );
          end;

  end;

function Create_Table_Query( _Table : TABSTable; _Query : TABSQuery; _Table_Name : string; _Labels_DB : TArray< string >; _Labels_DB_Type_Query : TArray< string >; _Labels_DB_Size_Query : TArray< Integer > ) : TDB_Result;
  var
    x : Integer;
    Dummy_SQL : string;
  begin

    if _Table.Exists then
    begin
      _Table.Open;
      _Table.Active := True;
      Result.Open_Table := True;
    end;

    if not _Table.Exists then
      try
        _Query.SQL.Clear;
        Dummy_SQL := '';

        for x := low( _Labels_DB ) to high( _Labels_DB ) do
        begin
          if x <> low( _Labels_DB ) then
            Dummy_SQL := Dummy_SQL + ',' + DBR;
          Dummy_SQL := Dummy_SQL + Format( '%s %s', [ _Labels_DB[ x ], Format( _Labels_DB_Type_Query[ x ], [ _Labels_DB_Size_Query[ x ] ] ) ] );
        end;

        _Query.SQL.Text := 'DROP TABLE IF EXISTS ' + _Table_Name + '; ' + DBR + 'CREATE TABLE ' + _Table_Name + ' (' + Dummy_SQL + ');';
        _Query.ExecSQL;
        _Table.Open;
        _Table.Active := True;
        Result.Create_Table := True;
      except
        if DB_Settings.Show_Errors then
          ShowMessage( Format( Error_C_Table_Create, [ _Table_Name ] ) );
      end;

  end;

function Index_Exists( _Table : TABSTable; const _IndexName : string ) : Boolean;
  var
    IndexDef : TIndexDef;
    i : Integer;
  begin

    Result := False;
    for i := 0 to pred( _Table.IndexDefs.Count ) do
    begin
      IndexDef := _Table.IndexDefs[ i ];
      if CompareText( IndexDef.Name, _IndexName ) = 0 then
      begin
        Result := True;
        break;
      end;
    end;

  end;

function Rebuild_Index_Query( _Table : TABSTable; _Query : TABSQuery; _Labels_DB : TArray< string >; _Labels_DB_Type_Query : TArray< string >; _Indizes_DB_Query : TArray< TArray< string > > ) : TDB_Result;
  var
    Dummy_Int : Integer;
    Dummy_SQL : string;
  begin

    _Table.Open;
    _Table.IndexDefs.Update;

    { Alle Indexfelder durchgehen, SQL erzeugen }
    for Dummy_Int := low( _Indizes_DB_Query ) to high( _Indizes_DB_Query ) do
      if not Index_Exists( _Table, _Indizes_DB_Query[ Dummy_Int ][ 0 ] ) then
        Dummy_SQL := Dummy_SQL + _Indizes_DB_Query[ Dummy_Int ][ 1 ];

    if Dummy_SQL <> '' then
      try
        _Query.SQL.Text := Dummy_SQL;
        _Query.ExecSQL;
        _Query.SQL.Clear;
        Result.Rebuild_Index := True;
      except
        if DB_Settings.Show_Errors then
          ShowMessage( Format( Error_C_Index_Rebuild, [ _Table.TableName ] ) );
      end;

    _Query.IndexDefs.Update;
    _Table.IndexDefs.Update;
    _Table.Close;
    _Table.Open;

  end;

end.

bernau 27. Mär 2020 19:27

AW: Record als Result einer Funktion
 
In deinem Code benutzt du die Werte von DB_Settings nur zum lesen. Die drei Werte werden zu keinem Zeitpunkt initialisiert. Ist das so gewollt?

himitsu 27. Mär 2020 22:18

AW: Record als Result einer Funktion
 
Zitat:

Zitat von bernau (Beitrag 1460660)
Die drei Werte werden zu keinem Zeitpunkt initialisiert. Ist das so gewollt?

Da es eine böse globale Variable ist, ist es auch initialisiert. (alles False)

Zitat:

Delphi-Quellcode:
BR = #10#13;

Falsch, denn es ist #13#10.

Der Witz:
BR sind sind so 2 Zeilenumbrüche,
aber wer denkt, dass 2 * 2 nun 4 ist, der wird enttäuscht, denn DBR sind so 3 Zeilenumbrüche. :stupid: :angle2:

Wer es nicht kann, der sollte Delphi-Referenz durchsuchensLineBreak verwenden.

NoGAD 28. Mär 2020 10:21

AW: Record als Result einer Funktion
 
Zitat:

Zitat von bernau (Beitrag 1460660)
In deinem Code benutzt du die Werte von DB_Settings nur zum lesen. Die drei Werte werden zu keinem Zeitpunkt initialisiert. Ist das so gewollt?

Danke. Habe ich übersehen.

[QUOTE=himitsu;1460666]
Zitat:

Zitat von bernau (Beitrag 1460660)

Zitat:

Delphi-Quellcode:
BR = #10#13;

Falsch, denn es ist #13#10.

Der Witz:
BR sind sind so 2 Zeilenumbrüche,
aber wer denkt, dass 2 * 2 nun 4 ist, der wird enttäuscht, denn DBR sind so 3 Zeilenumbrüche. :stupid: :angle2:

Wer es nicht kann, der sollte Delphi-Referenz durchsuchensLineBreak verwenden.

Oje. Danke für den Hinweis. Das habe ich seit Jahren so gemacht. Irgenwie bin ich von Linux aus das inzwischen anders gewohnt und verwechsle das dann immer gerne.



Die von euch angesprochenen Probleme betreffen aber leider nicht das Hauptthema, um welches es mir geht.

LG Mathias

Uwe Raabe 28. Mär 2020 10:42

AW: Record als Result einer Funktion
 
Zitat:

Zitat von NoGAD (Beitrag 1460680)
Die von euch angesprochenen Probleme betreffen aber leider nicht das Hauptthema, um welches es mir geht.

Und was ist das jetzt genau, was nicht schon durch den Hinweis auf nicht-initialisierte Variablen abgedeckt ist?

NoGAD 28. Mär 2020 11:33

AW: Record als Result einer Funktion
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1460681)
Und was ist das jetzt genau, was nicht schon durch den Hinweis auf nicht-initialisierte Variablen abgedeckt ist?



Warum sind Boolean von Haus aus True?

Uwe Raabe 28. Mär 2020 12:35

AW: Record als Result einer Funktion
 
Zitat:

Zitat von NoGAD (Beitrag 1460685)
Warum sind Boolean von Haus aus True?

Sind sie nicht. Ein Boolean hat die Speichergröße eines Bytes und es ist halt so, daß alles was in dem Byte steht außer 0 als True interpretiert wird. Daher ist die Wahrscheinlichkeit recht hoch, daß ein nicht-initialisierter Boolean eben als True gemeldet wird.

In der Realität ist der Speicher ja nicht wirklich zufällig belegt, sondern enthält das was vorher über eine andere Variable dort abgelegt wurde. Daher hat der vorherige Programmablauf entscheidenden Einfluss auf den Inhalt des Records.

DieDolly 28. Mär 2020 13:01

AW: Record als Result einer Funktion
 
Zitat:

Sind sie nicht. Ein Boolean hat die Speichergröße eines Bytes und es ist halt so, daß alles was in dem Byte steht außer 0 als True interpretiert wird. Daher ist die Wahrscheinlichkeit recht hoch, daß ein nicht-initialisierter Boolean eben als True gemeldet wird.
Bei mir ist Boolean False nach dem Erzeugen des Hauptformulars. Das ist ein größeres Projekt. Ist sowas Zufall?

Andreas13 28. Mär 2020 13:32

AW: Record als Result einer Funktion
 
Hallo NoGAD,
Du könntest Deinen eigenen Boolean-Typ deklarieren, bei dem dieses Problem nicht auftritt:
Delphi-Quellcode:
Type
  MyBoolean = (boUndef, boFalse, boTrue);
Und schon sind Deine Variablen beim Anlegen & Löschen "automatisch" auf boUndef gesetzt.
Gruß, Andreas

himitsu 28. Mär 2020 16:22

AW: Record als Result einer Funktion
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1460695)
Sind sie nicht.

Jupp, 255 zu 1 ist die Chance auf True, beim Boolean und ByteBool ... beim LongBool sind es da schon 4 Milliarden zu 1. :thumb:

Zitat:

Zitat von Andreas13 (Beitrag 1460705)
Du könntest Deinen eigenen Boolean-Typ deklarieren, bei dem dieses Problem nicht auftritt.
Und schon sind Deine Variablen beim Anlegen & Löschen "automatisch" auf boUndef gesetzt.

Eben nicht.
Also im Prinzip ist es ach deiner Definition ein Variant, der von Haus aus erstmal NULL ist und anschließens True oder False (WordBool) aufnehmen kann.

Mit dem Unterschied dass der Variant immer initialisiert ist und dein ENUM nicht.
siehe auch https://www.delphipraxis.net/203800-...string%3B.html

NoGAD 28. Mär 2020 17:19

AW: Record als Result einer Funktion
 
Lieben Dank an euch alle.


Da ich nur als Hobby programmiere, fehlen mir sicherlich wichtige Voraussetzungen, welche man durch eine entsprechende Ausbildung erhält. Lernen hingegen möchte ich immer. Daher freue ich mich, dass ich auch bei solchen Kleinigkeiten eines Besseren belehrt werde. :thumb:

Bisher war ich auch immer der falschen Annahme erlegen, dass Boolean immer automatisch als False initialisiert werden.

Falls noch jemand im Code eklatante Fehler, außer den bereits angesprochenen, findet, wäre ich über Rückmeldungen sehr erfreut.


LG Mathias

Luckie 28. Mär 2020 18:03

AW: Record als Result einer Funktion
 
Einfach angewöhnen alles zu initialisieren und das Standardverhalten kann einem egal sein. So mache ich es schon seit Ewigkeiten und bin bisher gut damit gefahren.

venice2 28. Mär 2020 18:15

AW: Record als Result einer Funktion
 
Zitat:

Zitat von Luckie (Beitrag 1460721)
Einfach angewöhnen alles zu initialisieren und das Standardverhalten kann einem egal sein. So mache ich es schon seit Ewigkeiten und bin bisher gut damit gefahren.

Solange wie Delphi es zulässt.

Delphi 2010 = OK
Delphi-Quellcode:
var
  x, i: Integer;
begin
 
  x := 0;
  for i := 0 to 10 do
    if i mod 2 then
      x := i;
end;
lässt man die Initialisierung 'x := 0;' weg kommt diese Meldung Variable: 'x' wurde nicht initialisiert.


Delphi 10.3 = Warnung: Auf 'x' zugewiesener Wert wird niemals benutzt.

Eine Faustregel gibt es nicht.

Andreas13 29. Mär 2020 12:14

AW: Record als Result einer Funktion
 
Zitat:

Zitat von himitsu (Beitrag 1460715)
Zitat:

Zitat von Andreas13 (Beitrag 1460705)
Du könntest Deinen eigenen Boolean-Typ deklarieren, bei dem dieses Problem nicht auftritt.
Und schon sind Deine Variablen beim Anlegen & Löschen "automatisch" auf boUndef gesetzt.

Eben nicht.
Also im Prinzip ist es ach deiner Definition ein Variant, der von Haus aus erstmal NULL ist und anschließens True oder False (WordBool) aufnehmen kann.

Mit dem Unterschied dass der Variant immer initialisiert ist und dein ENUM nicht.
siehe auch https://www.delphipraxis.net/203800-...string%3B.html

Bei allem Respekt, aber folgendes kleines Demoprogramm widerlegt Deine Thesen:
Delphi-Quellcode:
program Aufzaehlungstyp_Initialisierung_Test_1;
{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

Type
  MyBoolean = (boUndef, boFalse, boTrue);

CONST
  MyBooleanStr: Array[MyBoolean] of String = ('Undefiniert', 'Nein', 'Ja');
  n_Daten = 150;
 
VAR
  MB: MyBoolean;
  MB_Array: Array[1..n_Daten] of MyBoolean;
  i      : Integer;
   
Begin
  Try
    // OHNE eigene Initialisierung:

    WriteLn('MB: MyBooleanStr[MB] = ', MyBooleanStr[MB]);
    WriteLn;

    For i:= 1 To n_Daten Do
    Begin
      WriteLn('MyBooleanStr[MB_Array[', i.ToString.PadLeft(3), ']] = ', MyBooleanStr[MB_Array[i]]);
    End;
   
    ReadLn;

  Except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  End;
End.
Bitte selber überprüfen.
Gruß, Andreas

Andreas13 29. Mär 2020 12:38

AW: Record als Result einer Funktion
 
Und - damit wir beim Thema bleiben (Record als Result einer Funktion) - fügen wir noch folgenden Code zusätzlich ins obige Programm ein:
Delphi-Quellcode:
Type
  MB_Record = Record
    MB1: MyBoolean;
    MB2: MyBoolean;
    MB3: MyBoolean;
    MB4: MyBoolean;
    MB5: MyBoolean;
    MB6: MyBoolean;
    MB7: MyBoolean;
  End;
...

VAR
  MB_Rec: MB_Record;
...
    WriteLn('MB_Rec.MB1 = ', MyBooleanStr[MB_Rec.MB1]);
    WriteLn('MB_Rec.MB2 = ', MyBooleanStr[MB_Rec.MB2]);
    WriteLn('MB_Rec.MB3 = ', MyBooleanStr[MB_Rec.MB3]);
    WriteLn('MB_Rec.MB4 = ', MyBooleanStr[MB_Rec.MB4]);
    WriteLn('MB_Rec.MB5 = ', MyBooleanStr[MB_Rec.MB5]);
    WriteLn('MB_Rec.MB6 = ', MyBooleanStr[MB_Rec.MB6]);
    WriteLn('MB_Rec.MB7 = ', MyBooleanStr[MB_Rec.MB7]);
    WriteLn;
Auch dann funktioniert es.
Gruß, Andreas

Uwe Raabe 29. Mär 2020 12:50

AW: Record als Result einer Funktion
 
Zitat:

Zitat von Andreas13 (Beitrag 1460742)
Bitte selber überprüfen.

Das ist doch kein Beweis, sondern zeigt nur, daß nach einem Programmstart eine bestimmte Speicherbelegung wahrscheinlich ist. Probier mal dieses Testprogramm:
Delphi-Quellcode:
program Project652;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

Type
  MyBoolean = (boUndef, boFalse, boTrue);

CONST
  MyBooleanStr: Array[MyBoolean] of String = ('Undefiniert', 'Nein', 'Ja');

procedure Test;
var
  MB: MyBoolean;
begin
  if (MB < boUndef) or (MB > boTrue) then
    Writeln('Range Error!')
  else
    WriteLn('MB: MyBooleanStr[MB] = ', MyBooleanStr[MB]);
end;

procedure Dummy;
var
  B: Byte;
begin
  B := Random(256);
end;

procedure RandomTest;
var
  I: Integer;
begin
  for I := 1 to 1000 do begin
    Dummy;
    Test;
  end;
end;

begin
  try
    RandomTest;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

Andreas13 29. Mär 2020 12:54

AW: Record als Result einer Funktion
 
Inzwischen bin auch ich etwas klüger geworden... :oops:
Delphi-Quellcode:
Function Get_Record: MB_Record;
VAR
  MB_Rec_Neu: MB_Record;
 
Begin
  // OHNE eigene Initialisierung:
  Result:= MB_Rec_Neu;
End;
...
    MB_Rec:= Get_Record;
    // Himitsu hat recht: Das funktioniert NICHT mehr...
    // Das Funktions-Ergebnis kommt uninitialisiert vom Stack zurück
   
    WriteLn('MB_Rec.MB1 = ', MyBooleanStr[MB_Rec.MB1]);
    WriteLn('MB_Rec.MB2 = ', MyBooleanStr[MB_Rec.MB2]);
    WriteLn('MB_Rec.MB3 = ', MyBooleanStr[MB_Rec.MB3]);
    WriteLn('MB_Rec.MB4 = ', MyBooleanStr[MB_Rec.MB4]);
    WriteLn('MB_Rec.MB5 = ', MyBooleanStr[MB_Rec.MB5]);
    WriteLn('MB_Rec.MB6 = ', MyBooleanStr[MB_Rec.MB6]);
    WriteLn('MB_Rec.MB7 = ', MyBooleanStr[MB_Rec.MB7]);
    WriteLn;
Andreas

NoGAD 29. Mär 2020 12:55

AW: Record als Result einer Funktion
 
Zitat:

Zitat von Andreas13 (Beitrag 1460742)
Bitte selber überprüfen.
Gruß, Andreas



Bei mir werden alle Werte nicht initialisiert, also undefiniert. Delphi 10.3.3 (VirtualBox unter Linux)

himitsu 29. Mär 2020 13:06

AW: Record als Result einer Funktion
 
Zitat:

Zitat von venice2 (Beitrag 1460723)
Solange wie Delphi es zulässt.

Ja wozu auch diese Variable initialisieren und zuweisen, wenn sie danach dann eh nicht verwendet wird.

Der Fehler sitzt ein paar Zentimmer vor deinem Bildschirm,
und wenn es in 2010 ging, dann auch drinnen.

venice2 29. Mär 2020 14:21

AW: Record als Result einer Funktion
 
Zitat:

Ja wozu auch diese Variable initialisieren und zuweisen, wenn sie danach dann eh nicht verwendet wird.
Du hast schon gelesen was ich geschrieben habe?

Zentimmer
Ich schreibe es mal richtig.
Zitat:

Der Fehler sitzt ein paar Zentimeter vor deinem Bildschirm,
Richtig! Wenn man nicht liest was jemand schreibt.

Zitat:

lässt man die Initialisierung 'x := 0;' weg kommt diese Meldung Variable: 'x' wurde nicht initialisiert.
Also solltest du den Fehler bei Embarcadero (D2010) suchen nicht bei mir.
Denn unter Delphi 10.3 und Up funktioniert es ja so wie es soll.

Die Logik hinter dieser Aussage erschließt sich mir nicht.
Zitat:

und wenn es in 2010 ging, dann auch drinnen.

dummzeuch 29. Mär 2020 16:12

AW: Record als Result einer Funktion
 
Es ist nun mal so, dass verschiedene Delphi-Version für denselben Code unterschiedliche Hints und Warnings ausspucken. Ich habe schon häufig eine Variable initialisiert, obwohl das gar nicht notwendig war, damit der Compiler endlich Ruhe gibt, nur um dann bei einer neueren Delphi Version vom Compiler gesagt zu bekommen, dass die Zusweisung unnötig ist. Immerhin sind die Hints und Warnings der neueren Version häufiger korrekt als die der älteren.

venice2 29. Mär 2020 19:35

AW: Record als Result einer Funktion
 
Zitat:

Ich habe schon häufig eine Variable initialisiert, obwohl das gar nicht notwendig war
Deshalb schrieb ich ja "Solange wie Delphi es zulässt."

Ich schreibe meine Anwendungen Hints und Warnings frei.
Und ja es ist mir bewusst das das x nicht initialisiert werden muss aber sage das mal dem alten Compiler von Delphi nochmals siehe "Solange wie Delphi es zulässt."

Und Delphi lässt es nun mal nicht zu das man "Immer" alle Variablen initialisiert.
De facto gibt es auch keine Faustregel dafür (unter Delphi)
https://www.delphipraxis.net/1460721-post25.html

@dummzeuch
Zitat:

Immerhin sind die Hints und Warnings der neueren Version häufiger korrekt als die der älteren.
Du hast es auf den Kopf getroffen.

Ja Herr himitsu es sind immer die Leute vor dem Bildschirm. :stupid: ohne geht es nun mal nicht.

himitsu 29. Mär 2020 22:12

AW: Record als Result einer Funktion
 
Joar, irgendwer sitzt auch grade fett auf der Leitung, so langsam wie das hier ist.


Nja, dein Code lässt sich bei mir nichtmal kompiliere. :zwinker:
Auf die schnell sah der Code daher auch bissl anders aus.

Zitat:

Delphi-Quellcode:
if i mod 2 then    // [dcc32 Fehler] E2012 Ausdruckstyp muss BOOLEAN sein

In Pascal nimmt IF-THEN nur Boolean-Typen entgegen,
falls FreePascal das im nicht-delphi-kompatiblen Modus das macht, dann naja. (dann da halt wie im C/C++)

Aufgrund der länge hatte ich irgendwie etwas wie
Delphi-Quellcode:
x := x + 1;
oder
Delphi-Quellcode:
+ i
gesehn.



Dort kommt dann ohne das erste
Delphi-Quellcode:
x := 0;
natürlich zuerst der Fehler vonwegen nicht initialisiert.
So kommt in vielen Delphis bei Beidem
Delphi-Quellcode:
[dcc32 Hinweis] H2077 Auf 'x' zugewiesener Wert wird niemals benutzt
.

Bei Schleifen und IFs wird nicht beprüft ob und wieoft etwas ausgeführt wird.
Nur da wo untypisierte Konstanten im IF vorkommen, und sich das durch die Codeoprimierung auf einen einzelnen Boolean kürzen lässt, da weiß dann der Compiler ob der nachfolgende Code im IF niemals ausgeführt wird und ignoriert ihn dann. (wegoptimiert diesen Codeteil)

Also weiß der Compiler nicht, dass das
Delphi-Quellcode:
X:=
in der Schleife ausgeführt wird und somit auch nicht ob das vorherrige
Delphi-Quellcode:
X:=
überhaupt nicht nötig ist.
Delphi-Quellcode:
var
  x, i: Integer;
begin
  x := 0;                // [dcc32 Hinweis] H2077 Auf 'x' zugewiesener Wert wird niemals benutzt
  for i := 0 to 10 do
    //if i mod 2 then    // [dcc32 Fehler] E2012 Ausdruckstyp muss BOOLEAN sein
    if i mod 2 <> 0 then
      x := i;            // [dcc32 Hinweis] H2077 Auf 'x' zugewiesener Wert wird niemals benutzt
  //if x = 0 then ;
end;
Aber sicher ist hier, dass die Zuweisungen definitiv niemals verwendet werden und seit Delphi 4 hat mich Delphi immer darauf hingewiesen, kann mich jedenfalls nicht erinnern, dass es mir mal nichts gesagt hätte.

venice2 29. Mär 2020 23:01

AW: Record als Result einer Funktion
 
Zitat:

if i mod 2 then
Ja habe es hier getippt und <> 0 vergessen.
Zitat:

Aber sicher ist hier, dass die Zuweisungen definitiv niemals verwendet werden
Richtig wird ja so auch in Delphi 10.3 angeprangert.

Desto-trotz.
Unter Delphi 2010 meldet der Compiler das X nicht initialisiert wird.
Darauf wollte ich hinaus.

Für mich ist das Thema erledigt da es nun nicht mehr um das eigentliche Problem des TE geht.

himitsu 29. Mär 2020 23:44

AW: Record als Result einer Funktion
 
Joar, vor allem da dort soein Bug eh nicht mehr behoben wird.

Manchmal ist auch einfach der Wurm drin.
Im XE hatte ich letztens einen meiner geliebten Fatal Error mit zwei Leerzeichnen gebugfixt. (in 10.x wird er dann weg sein und ich kann die Leerzeichen dann wieder entfernen, falls ich's nicht vergesse :stupid:)

NoGAD 30. Mär 2020 08:01

AW: Record als Result einer Funktion
 
Zitat:

Zitat von himitsu (Beitrag 1460666)
Da es eine böse globale Variable ist, ist es auch initialisiert. (alles False)

Gibt es in meinem Beispiel eine günstigere Lösung als diese globale Variable?
Ich würde ungern noch drei weitere Parameter über den Funktionsaufruf übergeben wollen.


Generell habe ich eine Frage dazu:

Automatisch erstellte Forms sind auch globale Variablen.
Was ist der Unterschied zu einer in einer Unit gekapselten globalen Variable?




LG Mathias

Uwe Raabe 30. Mär 2020 08:51

AW: Record als Result einer Funktion
 
Zitat:

Zitat von NoGAD (Beitrag 1460787)
Automatisch erstellte Forms sind auch globale Variablen.

Ja, und die gelten vielen auch als böse.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:46 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz