Till Startsidan
JavaScript.nu / Perl-kurs / Returvärden och argument

LÄR DIG ATT PROGRAMMERA PERL
Returvärden och argument

Eftersom subrutiner är så extremt viktiga och jag inte vill att du glömmer vad du tidigare lärt dig om subrutiner ska vi nu åter gå tillbaka till det. Vi ska dock gå ett steg längre nu. Vi ska lära oss hur man skickar med argument till subrutinen vid anropet och hur man tar tillvara dess returvärde. Låter det komplicerat? Inte alls, vårt lilla exempel nedan visar hur lätt detta är:
#!/usr/bin/perl
print "Content-type:text/html\n\n";

sub geNamn
{
$fornamn = $_[0];		#Lagrar första argumentet till funktionen
$efternamn = $_[1];	#Lagrar andra argumentet till funktionen

return "$fornamn $efternamn"; 	#Nu returneras en sträng. Värdet lagras i "$helaNamnet" nedan
print "Detta är helt onödigt!";	#Vid return (ovan) avslutas subrutinen(!!!),
				#så denna rad kommer att ignoreras av scriptet.
				#Vi skulle med andra ord ha kunnat strunta i detta helt.
}

$helaNamnet=&geNamn('Adam','Svensson');	#Här anropar vi funktionen "geNamn".
					#Som argument skickar vi "Adam" och "Svensson"
					#$helaNamnet kommer nu få värdet "Adam Svensson",
					#eftersom geNamn returnerar detta.

print "'helaNamnet' innehåller nu: $helaNamnet";	#Detta skriver vi ut bara för att se vad som hänt

Utmatning:
'helaNamnet' innehåller nu: Adam Svensson
Vad är nu nytt i scriptet?
Jo, först har vi en subrutin som vi kallar geNamn. Denna anropas en gång av scriptet vid raden $helaNamnet=&geNamn('Adam','Svensson');.
Till skillnad mot vad vi tidigare gjort så anropar vi inte subrutinen med endast &geNamn;, utan den här gången skickar vi även med två argument: Adam och Svensson
I själva subrutinen kommer vi åt dessa genom variablerna $_[0] samt $_[1]. Observera att det första argumentet är 0 och det andra är 1.
Värdena vi skickar kan ses som en array som skickas. Vi skulle med andra ord ha kunnat ändra denna rad...
$helaNamnet=&geNamn('Adam','Svensson');
...mot dessa rader...
@namnen=('Adam','Svensson');
$helaNamnet=&geNamn(@namnen);

Av detta kan vi alltså dra slutsatsen att även subrutinen hanterar argumenten som en array. Dvs, man kan använda funktioner på argumenten precis som om det vore en vanlig array. Observera att vi då istället för $_[X] måste använda @_, eftersom detta är en array. Exempel på vad man kan göra:

@_=sort(@_);		#Sorterar arrayen i teckenordning
@_=reverse(@_);		#Vänder på arrayen. Sista värdet kommer först, första kommer sist etc.
$sistaIndexet=$#_;	#Sista indexet i arrayen lagras (@_)
Utöver dessa funktioner kan man utföra alla andra operationer på @_ som man kan göra på en vanlig array man skapar på vanligt vis.

Observera att man inte nödvändigtvis behöver skicka alla argumenten som vanliga strängar. Om man vill kan man skicka argumenten genom en array eller om man så vill genom arrayer och strängar. Nedan visas ett korrekt sätt att anropa en funktion med ett flertal värden:

#!/usr/bin/perl
print "Content-type:text/html\n\n";
sub vilkaVardenSkickas
{
	foreach $ettVarde (@_)
	{
	print "$ettVarde ";
	}
}

@nagraVarden=("Gustav","sade:");
@nagraNyaVarden=("Hejsan","hoppsan");
$ettTillVarde="Sedan var han tyst.";

print "Dessa argument har skickats till funktionen (subrutinen):\n";	#Detta skriver vi ut bara för att se vad som hänt
&vilkaVardenSkickas(@nagraVarden, @nagraNyaVarden, "\n", $ettTillVarde);

Utmatning:
Dessa argument har skickats till funktionen (subrutinen):
Gustav sade: Hejsan hoppsan
 Sedan var han tyst.
Observera att jag istället för raden...
&vilkaVardenSkickas(@nagraVarden, @nagraNyaVarden, "\n", $ettTillVarde);
...Lika bra skulle ha kunnat haft denna rad...
&vilkaVardenSkickas("Gustav", "sade:", "Hejsan", "hoppsan", "\n", "Sedan var han tyst.");

Om du undrar varför den sista raden blivit inskjuten med ett mellanslag så beror detta helt logiskt på att funktionen vilkaVardenSkickas skriver ut alla argumenten ett och ett, följt av ett mellanslag mellan varje utmatning. När då argumentet "\n" ska skrivas ut skriver funktionen ut "\n ", dvs. ett radbyte följt av ett mellanslag, vilket alltså gör så att den sista raden ("Sedan var han tyst.") blir inskjuten.

Vill du så kan du givetvis ha långa strängar eller stora arrayer direkt som returvärden. Här är ett exempel på hur man kan använda sig av funktioner på ett smart sätt:

#!/usr/bin/perl
print "Content-type:text/html\n\n";
@medlemmar=("Nisse;man\@power.se","Sven;sven\@svensson.se","Bert;bert\@bertilsson.com");

sub fixaTabell
{
return "<TR><TD>$_[0]</TD><TD>$_[1]</TD></TR>\n";
}

print "<TABLE>\n";
foreach $par (@medlemmar)
{
print &fixaTabell(split(/;/,$par));		#split gör strängen "a;b" till en array innehållande 2 värden: a och b
}
print "</TABLE>";

Utmatning:
<TABLE>
<TR><TD>Nisse</TD><TD>man@power.se</TD></TR>
<TR><TD>Sven</TD><TD>sven@svensson.se</TD></TR>
<TR><TD>Bert</TD><TD>bert@bertilsson.com</TD></TR>
</TABLE>
Det här scriptet kan vara svårt att förstå sig på till en början, fast kollar du närmare så är allt saker vi redan lärt oss under denna kurs.
För att du helt och hållet ska förstå vad som hänt beskriver jag nedan vad som sker steg för steg:
Det första scriptet gör är att det skriver ut <TABLE> och en radbrytning. Så väl allt lugnt. Efter detta kommer foreach $par (@medlemmar), som är en loop som för oss kör tre gånger (eftersom arrayen @medlemmar har tre värden). Under varje körning får $par värdet som finns i varje index i @medlemmar.
Första gången loopen körs blir värdet alltså Nisse;man@power.se
Raden print &fixaTabell(split(/;/,$par)); kan kanske vara svår att förstå sig på. Det den gör är exakt samma sak som dessa rader:
@tempArray=split(/;/,$par);		#@tempArray innehåller nu två fält, det ena med namnet på personen och det andra med hans/hennes email
$tempStrang=&fixaTabell(@tempArray);	#Namnet och emailen skickas som argument till funktionen fixaTabell. Returvärdet från fixaTabell lagras i $tempStrang
print "$tempStrang";		#$tempStrang skrivs ut
Som du säkert förstår är det mycket lättare att skriva allt på en rad, fast å andra sidan, tycker du det är lättare att förstå vad som händer om du använder dig av tre rader kanske det är att föredra.
Låt oss nu gå vidare i scriptet:
fixaTabell får alltså två argument (@tempArray innehåller två värden), dessa läses av i funktionen med denna rad:
return "<TR><TD>$_[0]</TD><TD>$_[1]</TD></TR>\n";

Lägg märke till att raden börjar med return. Detta betyder att hela strängen som kommer efter return kommer att skickas tillbaka som returvärde och lagras i $tempStrang (eller som det var i originalexemplet, det skrivs ut på direkten).

En sak som kan vara bra att känna till är att man kan returnera mer än bara en rad. Hade jag velat hade jag kunnat ändra denna rad...
return "<TR><TD>$_[0]</TD><TD>$_[1]</TD></TR>\n";
...mot dessa rader...

return <<"STOPHTML";
 <TR>
  <TD>$_[0]</TD>
  <TD>$_[1]</TD>
 </TR>
STOPHTML
Observera dock att utmatning då också innehåller radbrytningarna som finns i det sistvisade exemplet.
Bra att veta:
När du vill skriva ut flera rader direkt till skärmen, använd då:
print <<STOPHTML;
Hejsan hej.
Hej igen
STOPHTML
När du vill returnera flera rader, använd då:
return <<"STOPHTML";
Hejsan hej.
Hej igen
STOPHTML
Om du gör fel och använder citationstecken där du inte ska det eller inte använder dem där du egentligen ska använda dem så får du fel. Var noga med detta.
(texten STOPHTML kan givetvis bytas ut mot vad helst du önskar)

[Perl guiden] - [Till kapitel 10]






Copyright © Omid Rouhani 1997-2022; Alla rättigheter reserverade.
Guider: [ HTML guide ] - [ JavaScript guide ] - [ DHTML guide ] - [ Perl guide ] - [ Sitemap ]