perlunity.de - PERL | JAVASCRIPT | PHP | MySQL | APACHE



#!/COMMUNITY

Members: 5374
davon online: 1
weitere User: 31
Click for quality!




10.02.2012 / 10:22

Community-Member werden   |   Paßwort vergessen   |   OnlineMonitor (1) Wer ist online ... OnlineMonitor starten !
     

 

Home


PERLscripts


PHPscripts


JAVAscripts


Hilfreiches


Links2www


Newscenter


Community


Interna




Community  »  Perl: Allgemeines Forum zur Themenübersicht Themensuche Themenansicht in Thread-Modus


BeitragHash an Subfunktion übergeben
Seitenanfang
Hi miteinander!

Ich knoble seit ein paar Stunden an einem ganz speziellen Problem:

Folgendes:

Ich habe einen Hash mit 361 Elementen. Ich übergebe diesen an eine Subfunktion:

my %hash2 = funktion(%hash);

sub funktion(\%){

my %hash = %{(shift)};

###der hash wird bearbeitet###

return %hash;
}

Ist das korrekt so?
Kann ich dann mit %hash2 weiterspielen?
Mit keys kann ich die Schlüssel einwandfrei im Hauptprogramm ausgeben. Aber weder im Subprogramm noch im Hauptprogramm funktioniert ein print %hash;

Ist mein Programm soweit korrekt und mache ich bei der Verarbeitung ein Fehler?

Danke für eure Hilfe!

Datum: 08.12.2005-17:32

Beitragre: Hash an Subfunktion übergeben
Seitenanfang
Hi bionic,

fast! So wie ich Deinen Code lese, hast Du richtig erkannt, dass Du den Hash als Referenz übergeben musst. Allerdings ist die Syntax falsch. Es muss so heissen:


my %hash2 = funktion(\%hash); # HIER die Referenz
sub funktion { # hier keine Parameter, ist unnoetig
my %hash = %{(shift)};
###der hash wird bearbeitet###
return %hash;
}

Du musst die Referenz beim Aufruf der Funktion übergeben, nicht bei der Deklaration der Variablen. Ausserdem deklariert man in Perl Sub's eigentlich fast nie, was man übergeben möchte, es sei denn man hat einen guten Grund (ich hatte bisher nie einen).

Mögliche Verbesserungen: Innerhalb der sub mit "ref"prüfen, ob die Referenz wirklich auf einen Hash zeigt.

Nach dem Aufruf von Sub hast Du dann zwei hashes: hash und hash2, beide sind gleich. Bei 360 Elementen ist das kein grosses Problem, aber bei 30000 oder so schon (Memory etc.). Um das zu verhindern hast Du mehrere Möglichkeiten:

1) Nach dem Funktionsaufruf "undef %hash" aufrufen, damit wird der Hash geleert.

2) Die Funktion gleich nur für den Hash aufrufen:
"%hash = funktion(\%hash);",
das geht nämlich, oder noch besser
"funktion(\%hash);" (Dann aber ohne "return")

Da Du nämlich eine Referenz übergibst, wird der Original-Hash verändert.

Gruss,
svenXY

Datum: 09.12.2005-09:21

Beitragre: Hash an Subfunktion übergeben
Seitenanfang
Hi sven,

Danke für deine Antwort!

Ich habe mein Skript angepasst und das Übergeben der Werte hat gut funktioniert. Das Problem ist allerdings ein anderes:

Fehlermeldung vom Server:
[09/Dec/2005:04:55:47] failure (20566): for host x trying to POST /cgi-bin/test.pl, cgi_scan_headers reports: the CGI program did not produce a valid header (too many headers from CGI script (max 200))

### Hauptprogramm

my %hash = spider_table($dbh,$table,"VALUE",$datacache{'VALUE'});
print %hash;

### Subprogramm

sub spider_table {
my $dbh = shift;
my $table = shift;
my $row = shift;
my $searchby = shift;

my $sql="SELECT * FROM $table WHERE $row='$searchby'";

my $sth = $dbh->prepare($sql) or die $dbh->errstr();
$sth->execute or die $dbh->errstr();

my @result = $sth->fetchrow();

$sth->finish ();

my %hash;

my $string = "";

my $er_counter = 61;
my $intcount = 1;
while ($er_counter < @result){
$string .= "\$hash{'COP".$intcount."'} = \$result[".$er_counter."];";
$er_counter++;
$string .= "\$hash{'CAT".$intcount."'} = \$result[".$er_counter."];";
$er_counter++;
$string .= "\$hash{'TUS".$intcount."'} = \$result[".$er_counter."];";
$er_counter++;
$intcount++;
}

eval $string;

return %hash;
}

Das führt zu einem Crash...

Datum: 09.12.2005-11:05

Beitragre: Hash an Subfunktion übergeben
Seitenanfang
So... Das Subprogramm war ehrlich gesagt nicht so der Bringer...

Hier ist meine neue Version. Gleiches Problem (too many headers):

sub spider_table {
my $dbh = shift;
my $table = shift;
my $row = shift;
my $searchby = shift;

my $sql="SELECT * FROM $table WHERE $row='$searchby'";

my $sth = $dbh->prepare($sql) or die $dbh->errstr();
$sth->execute or die $dbh->errstr();

my @result = $sth->fetchrow();

$sth->finish ();

my %hash;

my @names = "";

my $ingcount = 1;
while ($ingcount <= 100){
push(@names,"COP$ingcount");
push(@names,"CAT$ingcount");
push(@names,"TUS$ingcount");
$ingcount++;
}

my $gencount = 0;
foreach (@names){
%hash = ($_ => "$result[$gencount]");
$gencount++;
}

return %hash;
}

Datum: 09.12.2005-12:46

Beitragre: Hash an Subfunktion übergeben
Seitenanfang
Hi,
ich denke, Du musst erst einen gültigen HTTP Header schicken (print), bevor Du den Hash ausgeben kannst.

Wenn Du das CGI Modul benutzt (sehr empfehlenswert), dann sowas wie


use CGI qw/:standard/;
print header, #HIER!!!
start_html('A Simple Example'),
h1('A Simple Example'); ...

und danach erst "print %hash", wobei "print %hash " sicherlich nicht ausgeben wird, was Du Dir vorstellst:

$ perl -e '%h=(a=>'ggg',b=>'zzz');print %h'
agggbzzz

Datum: 09.12.2005-14:31

Beitragre: Hash an Subfunktion übergeben
Seitenanfang
Hmm... Ja, den Header habe ich nicht vergessen auszugeben.

Ich kann auch auf einzelne Elemente des Hash zugreifen und diese ausgeben; das funktioniert alles.

Nur: Ich kann den Hash eifach nicht als ganzes verwenden! Er sagt immer: "too many headers".

Das mit print %hash; ist nur ein Test. Eigentlich möchte ich den Hash an eine weiter Subfunktion übergeben und dort weiterverarbeiten, nur weigert er sich das zu tun.

Ich vermute, es liegt ein Problem mit der Datenbank vor, aus der die Daten ausgelesen werden.

Ich melde mich, wenn es was neues gibt.

Vielen Dank für deine Hilfe!

Datum: 09.12.2005-15:58

Beitragre: Hash an Subfunktion übergeben
Seitenanfang
Hi bionic,

Funktioniert denn Dein Ansatz ohne CGI, als normale Subroutine? Dann weißt Du eher, wo Du gucken mußt.

Datum: 11.12.2005-18:56

Beitragre: Hash an Subfunktion übergeben
Seitenanfang
Hi,
ich würde auch - wenn schon testen ;-) - mal einen Dump von %hash ausgeben, so a la

use Data::Dumper;
print '<pre>', Dumper(\%hash), '</pre>'

Das sollte kla machen, wo es hängt.

Gruss,
svenXY

Datum: 12.12.2005-09:41

Beitragre: Hash an Subfunktion übergeben
Seitenanfang
Hi Sven,
der Tipp mit Dumper war super. Die Ausgabe ist einwandfrei; alle Keys haben einen Wert oder sind undef. Sobald ich aber eine Zeile weiter ein print %hash; hinzufüge, gibt er nun dieses auch aus und bricht nicht mehr ab. Er schmeisst aber auch viele Male die Fehlermeldung: Use of uninitialized value in print at /pfad/test.pl line 35.

Wieso sucht er hier nach nicht initialisierten Werten? Line 35 ist mein print %hash;...

Hat jemand eine Idee?

Gruss
bionic

Datum: 12.12.2005-10:50

Beitragre: Hash an Subfunktion übergeben
Seitenanfang
Naja, ein undef ist eben ein undef (oder uninitialized)

Datum: 12.12.2005-11:36

Beitragre: Hash an Subfunktion übergeben
Seitenanfang
Ah... ok.

Wie kann ich denn den undef mit einer if schleife eliminieren?

so ähnlich wie:

if ($string eq undef){
$string = "";
}

Datum: 12.12.2005-13:34

Beitragre: Hash an Subfunktion übergeben
Seitenanfang
ja, so würde es gehen (wahrscheinlich nicht "eq" weil das ein Stringvergleich ist, sondern "=="), beeser noch:

$string = "" unless defined $string;

Du hast das Problem doch aber praktisch nur bei Deinem Test "print %hash", der ohnehin nicht so gut geeignet ist bei hashes (Dumper ist da viel besser).

Wenn Du den ganzen Hash reparieren willst, geht das gut mit der einen Zeile


%hash = map { $_, ($hash{$_}) ? $hash{$_} : '' } keys %hash;

Gruss,
svenXY

Datum: 12.12.2005-14:19

Beitragre: Hash an Subfunktion übergeben
Seitenanfang
%hash = map { $_, ($hash{$_}) ? $hash{$_} : '' } keys %hash;

Hammer! Das hat mein Problem gelöst!!!

Vielen Dank! Auf einmal funktioniert alles, wie es sollte... Ich habe gedacht, dass automatisch "" zugeordnet wird, wenn in der DB das Feld empty ist...

Manchmal ist man zu blind vor lauter Fehlersuche, dass man das einfachste Problem übersieht.

Danke svenXY, du kannst ja wirklich jedes Problem lösen. ;-)

Gruss
bionic

Datum: 12.12.2005-15:04

Beitragre: Hash an Subfunktion übergeben
Seitenanfang
Danke für die Blumen :-), schön wäre es, wenn's wirklich so wäre (mit dem jedes Problem lösen)...

undef und "" ist eben ein Unterschied, genauso übrigens, wie "" und NULL in MySQL ein Unterschied ist.

Gruss,
svenXY

Datum: 12.12.2005-15:18

-






-
-