Perl语言入门(12 引用 + 结构)

2016-09-22 19:57:55来源:CSDN作者:haoweilaizoule人点击

由于公司需要,本人最近在学习Perl这种脚本语言,本文是我在学习Perl的过程中总结出来的一些心得和笔记,希望能够帮助也在学习Perl的各位同僚。废话不多说直接上干货!!!

———————————————————————————干货分割线 —————————————————————————

引例:

数据拷贝:      

$a = “stone”;

$b = $a;

此时,$b是$a的一个数据拷贝,即两个变量中的数据完全一致,但是当$a修改,$b不变,仍然是stone.

数据引用:     

$a = “stone”;

$b = /$a; (引用的写法,后面会介绍)

此时,$b是$a的一个数据引用,当$a修改时,$b也会跟着被修改.

引用的好处:1>节省内存开支.2>方便修改变量(当有多个变量同时引用一个变量的时候,只要修改被指向的元数据,引用就会被修改)

引用:它是指向一组数据的指针,并不包含实际数据的本身。该引用通常存放在另一个标量变量中。

大白话解释:我(相当于$b变量)指着你(相当于$a变量),你的位置,穿衣吃饭,胳膊腿都可以看做是变量中的数据(相当于$a中的stone).无论你从T恤换成了棉袄,从北京来到了上海,还是自残剁了条胳膊(你的数据发生了改变),但我始终指着你.其实我本身并没有数据,只是起到一个桥梁的作用,将你的数据,牵引到用到你的地方.

 

创建引用的方法:

$ref = /$a;

不能简单地对$ r e f进行操作,因为它里边没有通常的标量值。如果输出$ref,就会显示类似SCALAR (0X0000)的信息。若要通过$ref获得$ a中的值,必须间接引用$ref。间接引用可以被视为上面的方块图中按箭头方向的引用。

 

通过引用输出值:

print $$ref;

 

通过引用修改原始值:

$$ref = “sticks”;

若果你使用$ r e f而不是$ $ r e f:

$ref = “Break”;

那么存放在$ r e f中的引用将被撤消并被实际值取代.

 

给引用赋值:

$name = “mountain .king”;

$nref = /$name;

$oref = $nref;

得到的结果如下:

 

给引用赋值引用:

$book = “jinpingmei”;

$bref = /$book;

$bref2 = /$bref;

得到的结果如下:


如果使用$ b r e f 2来输出书名,那么该引用将是$$$b r e f 2,如果使用$ b r e f,则该引用是$ $ b r e f。

请注意,$ $ $ b r e f 2多了一个美元符号,它需要增加一层间接引用,才能获得原始值。

 

对数组的引用:

$aref = /@arr;

形式:

 

使用引用访问数组:

$$aref[0]  #输出@arr的第一个元素

@$aref[2,3] #输出@arr的一个片

@$aref      #输出整个数组

也可以这样表示:

${$aref}[0]

${$aref}[2,3]

@{$aref}

使用引用输出数组:

foreach $element(@{$aref}){

    print $element;

}

 

Hash的引用:

$href = /%hash;

形式:

 

 

使用引用访问Hash:

$$href{key}  <===> ${$href}{key}

%$href  <===> %{$href}

迭代输出所有值:

foreach $key(keys %$href){

print $$href{$key};    #同$hash{$key}

}

 

引用作为参数:

由于整个数组或哈希结构均可被引用,并且该引用可以存放在一个标量中,因此,借助这些引用,可以调用带有多个数组或哈希结构的函数。

Exp:

#不能正常执行

@fruit = qw(apples oranges banana);

@veggies = qw(carrot cabbage turnip);

getarrays(@fruit,@veggies);

sub getarrays{

    my (@a,@b)= @_;

    ...

}

 

#可以正常执行

@fruit = qw(apples oranges banana);

@veggies = qw(carrot cabbage turnip);

getarrays(/@fruit,/@veggies);    #引用

sub getarrays{

    my ($friut_ref,$veg_ref)= @_;   #引用

    ...

}

 

数据拷贝和数据引用的对比:

数据拷贝:

#!/usr/bin/perl sub changehash{    my (%local_hash) = @_;    $local_hash{mammal} = 'bear';    return;} %hash = (fish => 'shark', bird => 'robin');changehash (%hash);foreach (keys %hash){    print "$hash{$_}/n";}
PS:在本例中,@_取得% hash中每个关键字值对的各个值。在子例程changehash( )中,现在放入@_中的哈希结构的各个元素被拷贝到%localhash中。%localhash被修改.当子例程返回后,%localhash就被撤消,而程序的主要部分中的%hash则保持不变。

数据引用:

sub changehash{    my ($href) = @_;    $$href{mammal} = 'bear';    return;} %hash = (fish => 'shark', bird => 'robin');changehash (/%hash);foreach (keys %hash){    print "$hash{$_}/n";}
PS:在本例中,对% h a s h的引用通过@_被传递到子例程c h a n g e h a s h ( )中。该引用被拷贝到$href中,它仍然指原始哈希% h a s h。在子例程中,$ h r e f指向的哈希结构被修改。c h a n g e h a s h ( )返回后,原始哈希结构% h a s h将包含新关键字b e a r.

 

创建各种结构:

在下面的代码段中,代码块中创建了一个哈希结构% h a s h,并且这个哈希结构是该代码块的专用结构:

my $href;

{

    My %hash = (phone => ‘bell’,light => ‘Edision’);

    $href = /%hash;

}

print $$href{light}; #输出Edision.

在这个代码块中,标量$ h r e f被赋予对% h a s h的引用。当该代码块存在时,即使% h a s h已经消失,$ h r e f中的引用仍然有效(因为% h a s h是代码块的专用结构)。当结构本身已经超出作用域之后,对该结构的引用仍然可以存在,$ h r e f引用的哈希结构仍然可以修改。

 

P e r l提供了一个机制,可以用来创建引用,而不必使用中间的哈希结构% h a s h。这个机制称为匿名存储。下面这个例子创建了一个对匿名哈希结构的引用,并把它存储在$ a h r e f中:

$ahref = {phone => ‘Bell’,light => ‘Edison’};

花括号{}将哈希结构括起来,返回对它的引用,实际上并没有创建新的变量。

也可以使用方括号( [ ])创建匿名数组:

$aaref = [qw(crosby stills nash  young)];

 

P e r l并不支持真正的二维数组。P e r l允许你使用数组引用的数组,模仿建立二维数组.

创建数组的数组:

@list_of_lists = (

[qw(Mustang Bronco Ranger)],

[qw(Cavalier Suburban Buick)],

[qw(Lebaron Ram)]

);

要访问最里层的列表的各个元素(即二维数组中的单元格),可以使用下面这个代码:

$list_of_lists[0][1]; #访问Bronco

$list_of_lists[1][2]; #访问Buick

 

最外层的列表中的元素数目:

$#list_of_lists; #最外层元素的索引:2

scalar(@list_of_lists); #列表的行数:3

 

里层列表中的某个列表的元素数目:

scalar(@{$list_of_lists[2]}); #列表索引为2的元素个数为:2

$#{$list_of_lists[1]}; #列表索引为2的行元素的最后索引为:2(第三个元素)

 

遍历列表的列表中每个元素:

foreach my $outer(@list_of_lists){

    foreach my $inner(@{$outer}){

        print “$inner”;

    }

    print “/n”;

}

 

向列表中添加元素:

push(@list_of_lists,[qw(Mercedes BMW Lexus)]);

push(@{$list_of_lists[0]},qw(Taurus));

Exp:

#!/usr/bin/perl -wuse strict;  use warnings; my @list_of_lists = (    [qw(Mustang Bronco Ranger)],    [qw(Cavalier Suburban Buick)],    [qw(Lebaron Ram)]); #向列表中添加元素push(@list_of_lists,[qw(Mercedes BMW Lexus)]);push(@{$list_of_lists[0]},qw(Taurus)); #遍历元素foreach my $outer(@list_of_lists){    foreach my $inner(@{$outer}){        print "$inner ";    }    print "/n";}
输出:

 

 

迷宫游戏:

该游戏结合本节的知识点.迷宫蓝图为:

 

Exp:

#!/usr/bin/perl -wuse strict;  use warnings; ##########################################################@maze定义迷宫的布局#数组中的元素e,w,s,n分别表示方向东,西,南,北#如第0行第1个元素swe:表示该位置可以向南,西,东三个方向移动#-:表示此位置不可进入#########################################################my @maze = (    [qw(e swe we ws)],    [qw(ne new sw ns)],    [qw(ns -   ns wn)],    [qw(ne w   ne w)]); #定义移动方向my %direction = (    n => [-1,0],    s => [1,0],    e => [0,1],    w => [0,-1]);  my %full = (    e => 'East',    n => 'North',    w => 'West',    s => 'South'); #$curr_x,$curr_y:当前位置,设置为(0,0)坐标点#$x,$y:目标位置,设置为(3,3)坐标点my ($curr_x,$curr_y,$x,$y) = (0,0,3,3);my $move; sub disp_location{    my ($cx,$cy) = @_;    print "You may move ";    #若元素能匹配则根据简称输出全称    while($maze[$cx][$cy] =~ /([nsew])/g){        print "$full{$1}";    }    #输出简称    print "($maze[$cx][$cy])/n";} sub move_to{    #该函数取出一个方向(存入$new中),和当前位置的引用    my ($new,$xref,$yref) = @_;    #lc函数将变量改为小写字母,substr函数取出变量的第一个字母:East->e    $new = substr(lc($new),0,1);    #搜索当前房间方向索引,若不匹配则输出非法值    if($maze[$$xref][$$yref] !~ /$new/){        print "Invalid direction,$new./n";        return;    }    #坐标被修改    $$xref += $direction{$new}[0];    $$yref += $direction{$new}[1];} until ($curr_x == $x and $curr_y == $y){    disp_location($curr_x,$curr_y);    print "Which way?";    #读入方向变量,若为q则退出    $move =<STDIN>;	chomp $move;    exit if($move =~ /^q/);    move_to($move,/$curr_x,/$curr_y);} print "You made it through the maze!/n";

游戏步骤的可能输出:

 


最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台