FHEM Forum

FHEM => Automatisierung => Perl für FHEM-User => Thema gestartet von: TomLee am 23 Dezember 2021, 12:04:46

Titel: [geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: TomLee am 23 Dezember 2021, 12:04:46
Hallo,

kann mich noch weitere zwei Tage mit beschäftigen, ich zweifle mittlerweile daran irgendwann selbst drauf zu kommen warum es zu der Meldung kommt ?

Mach ich wirklich noch was falsch ?
Kann es vlt. am Ende von der verwendeten Perl Version abhängig sein ?

{
  my @d = qw(bli bla blub);;
  my %c;;
  for my $i (1..@d) {
  $c{$i}="$d[$i]";;
  }
  print join(" ",sort keys %c),"\n";;
}

{
  my @d = qw(bli bla blub);;
  my %c;;
  for (my $i = 1;;$i <= @d;;$i++ ) {
  $c{$i}="$d[$i]";;
  }
  print join(" ",sort keys %c),"\n";;
}


2021.12.23 11:57:46 1: PERL WARNING: Use of uninitialized value within @d in string at (eval 33059) line 1.
2021.12.23 11:57:46 3: eval: {   my @d = qw(bli bal blub);   my %c;   for my $i (1..@d) {   $c{$i}="$d[$i]";   }   print join(" ",sort keys %c),"\n"; }
1 2 3
2021.12.23 11:58:00 1: PERL WARNING: Use of uninitialized value within @d in string at (eval 33086) line 1.
2021.12.23 11:58:00 3: eval: {   my @d = qw(bli bal blub);   my %c;   for (my $i = 1;$i <= @d;$i++ ) {   $c{$i}="$d[$i]";   }   print join(" ",sort keys %c),"\n"; }
1 2 3


Gruß

Thomas
Titel: Antw:PERL WARNING: Use of uninitialized value within @d in string at (eval 33059)
Beitrag von: Beta-User am 23 Dezember 2021, 12:19:35
Vermutlich liegt es daran, dass die Zählweise innerhalb eines Array etwas anders ist als man das vermutet: Das erste Element ist "0", nicht "1"...
Statt
for my $i (1..@d) {

sollte es m.E. heißen:
for my $i (0..@d-1) {
Das mit "@d-1" ist eigentlich auch eine etwas "schmutzige" Schreibweise, ganz korrekt sollte sein:
for my $i (0..$#arr) {
https://stackoverflow.com/questions/7406807/find-size-of-an-array-in-perl#comment92844211_7406807
Titel: Antw:PERL WARNING: Use of uninitialized value within @d in string at (eval 33059)
Beitrag von: TomLee am 23 Dezember 2021, 12:23:11
Zitatfor my $i (0..$#arr) {

Das mag ich aber nicht, ich möchte das der key bei 1 beginnt und 0..$#arr zählt wie du sagst von 0 bis 9.

Ergebnis wäre also 0 1 2, ich will wie gezeigt 1 2 3.
Titel: Antw:PERL WARNING: Use of uninitialized value within @d in string at (eval 33059)
Beitrag von: Christoph Morrison am 23 Dezember 2021, 12:24:09
Dein Code produziert folgendes:


# @d
$VAR1 = [
          'bli',
          'bla',
          'blub'
        ];

# %c
$VAR1 = {
          '1' => 'bla',
          '2' => 'blub',
          '3' => ''
        };



Warum?
$d[0] = bli
$d[1] = bla
$d[2] = blubb
$d[3] = ''


Du fängst bei der Iteration in for mit 1, nicht mit 0 an. Ergo: Du greifst auf einen nicht definierten Schlüssel $d[3] zu.

Beispiellösung:

use Data::Dumper;
use feature 'say';

my @d = qw(bli bla blub);

my ($i, %c);
for my $v (@d) {
    $i++;
    $c{$i} = $v;
}

say Dumper(\%c);


Ergibt:

$VAR1 = {
          '1' => 'bli',
          '3' => 'blub',
          '2' => 'bla'
        };
Titel: Antw:PERL WARNING: Use of uninitialized value within @d in string at (eval 33059)
Beitrag von: TomLee am 23 Dezember 2021, 12:28:08
Christoph hat mich verstanden, Danke für das Beispiel/erklären.
Titel: Antw:PERL WARNING: Use of uninitialized value within @d in string at (eval 33059)
Beitrag von: Beta-User am 23 Dezember 2021, 12:29:58
Zitat von: TomLee am 23 Dezember 2021, 12:23:11
Das mag ich aber nicht, ich möchte das der key bei 1 beginnt und 0..$#arr zählt wie du sagst von 0 bis 9.

Ergebnis wäre also 0 1 2, ich will wie gezeigt 1 2 3.
Na ja, um das vollständig zu machen:
Eine weitere Variante wäre, dann den Array-Pointer einfach entsprechend zu reduzieren:
  for my $i (1..@d) {
  $c{$i}="$d[$i-1]";;
  }

Oder den Hash-Pointer zu manipulieren:
  for my $i (0..$#d) {
  $c{$i+1}="$d[$i-1]";;
  }
Titel: Antw:PERL WARNING: Use of uninitialized value within @d in string at (eval 33059)
Beitrag von: Christoph Morrison am 23 Dezember 2021, 12:37:03
Zitat von: TomLee am 23 Dezember 2021, 12:28:08
Christoph hat mich verstanden, Danke für das Beispiel/erklären.

Die Antwort von Beta-User ist ja auch nicht falsch, kommt halt darauf an, wo du zu zählen anfängst / anfangen willst.
Dein Fehler ist übrigens ein echter Klassiker (https://de.wikipedia.org/wiki/Off-by-one-Error).
Titel: Antw:[geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: TomLee am 23 Dezember 2021, 12:47:55
ZitatNa ja, um das vollständig zu machen:
Eine weitere Variante wäre, dann den Array-Pointer einfach entsprechend zu reduzieren:

Super  ::), erst hab ich goar nix und jetzt muss man sich für eine von drei Varianten entschliessen  ;D. Danke.
Titel: Antw:[geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: Christoph Morrison am 23 Dezember 2021, 13:51:52
Zitat von: TomLee am 23 Dezember 2021, 12:47:55
Super  ::), erst hab ich goar nix und jetzt muss man sich für eine von drei Varianten entschliessen  ;D. Danke.

Und zwei davon kann man kaum lesen ;-)

Willkommen in der Perl-Welt.
Titel: Antw:[geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: Beta-User am 23 Dezember 2021, 14:06:16
Zitat von: Christoph Morrison am 23 Dezember 2021, 13:51:52
Und zwei davon kann man kaum lesen ;-)

Willkommen in der Perl-Welt.
...wir könnten noch $i durch $_ ersetzen und versuchen ein map zu basteln...

Ansonsten wäre es vermutlich sinnvoll einige Quotes wegzulassen und sauberer einzurücken.

*duckundweg*
Titel: Antw:[geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: TomLee am 23 Dezember 2021, 15:12:46
Nochmal.

Hab mein Ziel jetzt erreicht, wie würdet ihr das machen ?

{
    my @d = qw(bli bla blub);;
    my @e = qw(Honk Monk Zonk);;
    my ($i, %c);;
    for my $v (@d) {
    $i++;;
    $c{$i} = $v;;
    }
    $i= keys %c;;
    for my $w (@e) {
    $i++;;
    $c{$i} = 'du '.$w;;
    }   
    print join(" ",sort values %c),"\n";;
}

bla bli blub du Honk du Monk du Zonk

Titel: Antw:[geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: TomLee am 23 Dezember 2021, 15:21:52
Und eine Frage hätte ich noch bezüglich der Rückgabe der Anzahl mit keys %irgendwas und @irgendwas, wenn man damit rechnen wollte klappt das problemlos, aber wäre es nicht korrekter das ganze dann in scalar() zu stecken, auch in dem Code jetzt ?
Titel: Antw:[geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: Christoph Morrison am 23 Dezember 2021, 15:55:51
print join(" ",sort values %c),"\n";;

Warum baust du dir erst einen numerischen Index (1..x), sortierst aber dann nach den Values im Hash?
Titel: Antw:[geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: TomLee am 23 Dezember 2021, 16:20:16
Das ist nur für mich gewesen zum nachvollziehen.

Ich will nur den Hash, sieh dir hier (https://forum.fhem.de/index.php/topic,124843.msg1194238.html#msg1194238) in setList den pct slider an, den vorderen Teil hab ich schon dynamisch und den hinteren Teil, iVm. mit diesem setter (https://forum.fhem.de/index.php/topic,124843.msg1194313.html#msg1194313) jetzt.

Ich hab das bis jetzt aber noch nicht eingebaut in setList und getestet, mach später erst.
Titel: Antw:[geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: TomLee am 24 Dezember 2021, 12:08:53
Mit map hab ich mich eben kurz beschäftigt, sieht bei mir, nach zwei-drei Tests, so aussehen:

{
my @d = qw(bli bla blub);;
my @e = qw(Honk Monk Zonk);;
my ($i, %c);;map {$i++;;$c{$i} = $_;;} (@d) ;;
$i= keys %c;;
map {$i++;;$c{$i} = 'du '.$_;;} (@e);;
}


Und auch hier (mit map) die Frage, wie ihr es machen würdet ?
Titel: Antw:[geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: Beta-User am 24 Dezember 2021, 12:40:05
...eher gar nicht mit map. Ging da nur um die Frage, wie man es noch unleserlicher notieren könnte...
Titel: Antw:[geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: TomLee am 24 Dezember 2021, 13:31:54
Kann ich mangels Erfahrung ja nicht beurteilen, wenn ich mir den fertigen Code anschaue empfinde ich die map-Variante als angenehm und man spart sich noch die Definition einer Variable.


{
my @d = split(/,/,ReadingsVal($NAME,'speech_cmnd','none'));
my @e = split(/,/,ReadingsVal($NAME,'zones','none'));
my ($i, %pct2cmd);
    for my $v (@d) {$i++;$pct2cmd{$i} = $v;}
$i= keys %pct2cmd;
    for my $w (@e) {$i++;$pct2cmd{$i} = 'zone '.$w;};
my $cmd = $pct2cmd{$EVTPART1};
    return if !$cmd;
    return fhem("set $NAME !$cmd;setreading $NAME pct $EVTPART1");}

{
my @d = split(/,/,ReadingsVal($NAME,'speech_cmnd','none'));
my @e = split(/,/,ReadingsVal($NAME,'zones','none'));
my ($i,%pct2cmd);
    map {$i++;$pct2cmd{$i} = $_;} (@d);
$i= keys %pct2cmd;
    map {$i++;$pct2cmd{$i} = 'zone '.$_;} (@e);
my $cmd = $pct2cmd{$EVTPART1};
    return if !$cmd;
    return fhem("set $NAME $cmd;setreading $NAME pct $EVTPART1");
}
Titel: Antw:[geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: Christoph Morrison am 27 Dezember 2021, 00:28:31
Wie sieht denn $EVTPART1 typischerweise aus?
Titel: Antw:[geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: TomLee am 27 Dezember 2021, 00:32:21
Das sind die Rückgabewerte des pct-slider, hab ich in #13 verlinkt.
Titel: Antw:[geklärt] PERL WARNING: Use of uninitialized value within @d in string at ...
Beitrag von: TomLee am 27 Dezember 2021, 00:36:50
Hier (https://forum.fhem.de/index.php/topic,121017.msg1195353.html#msg1195353) meine fertige Lösung des pct-setter die bisher nach mehrerem testen problemlos klappt.