2014-10-16 121 views
3

我需要修改例程中的變量,以便在離開例程後保留更改。這裏有一個例子:Perl:將作爲參數傳遞給變量的變量修改爲子例程

$text = "hello"; 
&convert_to_uppercase($text); 
print $text; 

我想在屏幕上看到「你好」,而不是「你好」。

的常規是:

sub convert_to_uppercase($text){ 
    <something like $text = uc($text);> 
} 

我知道如何做到這一點在PHP,但似乎未更改參數的方法相同。而且,我一直在尋找,我找不到具體的答案。

我會很感激任何幫助。謝謝!

+0

這個問題可能會有所幫助:http://stackoverflow.com/questions/24063638/if-perl-is-call-by-reference-why-does-this-發生 – AntonH 2014-10-16 22:21:29

+0

非常感謝!我的新問題是:爲什麼($ x1,$ y1)= @_;?如果我這樣做,它會是相同的:** $ x1 = $ _ [0]; $ y1 = $ _ [1]; **?請考慮我對Perl真的很陌生,並感謝您的耐心等待! – gonfer 2014-10-16 23:14:37

+0

是的。 '($ x1,$ y1)= @_;'是一個快捷方式。 – AntonH 2014-10-16 23:27:12

回答

5

真的調用Perl子程序時不應該使用&符號&。僅在將代碼視爲數據項時纔有必要,例如在參考時,如\&convert_to_uppercase。在Perl 5的版本4中,在調用中使用它並不是必需的,它會執行一些你可能不想要的東西。

子程序修改它們的參數是不常見的,但@_的元素是實際參數的別名,因此您可以通過修改該數組來做到這一點。

如果你寫你的子程序這樣

sub convert_to_uppercase { 
    $_[0] = uc $_[0]; 
} 

然後它會做什麼你問。但通常最好是返回修改後的值,以便決定是否覆蓋原始值可以由調用代碼進行。舉例來說,如果我有

sub upper_case { 
    uc shift; 
} 

那麼它可以被稱爲要麼作爲

my $text = "hello"; 
$text = upper_case($text); 
print $text; 

它確實如你需要,並修改$text;或作爲

my $text = "hello"; 
print upper_case($text); 

其中$text保持不變,但返回更改的值。

+1

太棒了!還有一件事:是否有必要聲明例程簽名?我看到你做** sub convert_to_uppercase {} **而不是** sub convert_to_uppercase($ text){} **,但是當你調用它時,你會執行** convert_to_uppercase($ text)**。 另一件事,我用**&**,因爲我不知道我不應該,我對Perl真的很陌生。我正在做的是用戶輸入的驗證,所以我想大寫用戶的輸入(我會稍後再檢查它),並返回1或0,如果有效或不是,那就是爲什麼我不這樣做使用返回來做到這一點。 你真的很有幫助,非常感謝! – gonfer 2014-10-16 23:22:11

+0

@gonfer,no。自從Perl 5.20(幾個月前發佈)以來,子簽名才被添加爲核心Perl特性,並且僅在實驗中使用。 (雖然簽名的幾種實現方式可用作不同級別穩定性的擴展模塊。) – tobyink 2014-10-17 09:37:57

3

傳遞一個參考和修改子程序內的原始變量將這樣來完成:

$text = 'hello'; 
convert_to_uppercase(\$text); #notice the \ before $text 
print $text; 

sub convert_to_uppercase {  #perl doesn't specify arguments here 

    ### arguments will be in @_, so @_ is now a list like ('hello') 
    my $ref = shift;    #$ref is NOT 'hello'. it's '$text' 

    ### add some output so you can see what's going on: 
    print 'Variable $ref is: ', $ref, " \n"; #will print some hex number like SCALAR(0xad1d2) 
    print 'Variable ${$ref} is: ', ${$ref}, " \n"; #will print 'hello' 

    # Now do what this function is supposed to do: 
    ${$ref} = uc ${$ref}; #it's modifying the original variable, not a copy of it 
} 

另一種方法是給子程序外部創建的子程序內的返回值並修改變量:

$text = 'hello'; 
$text = convert_to_uppercase($text); #there's no \ this time 
print $text; 

sub convert_to_uppercase { 
    # @_ contains 'hello' 
    my $input = shift; #$input is 'hello' 
    return uc $input; #returns 'HELLO' 
} 

但是convert_to_uppercase例程似乎是多餘的,因爲這就是uc所做的。跳過這一切,只是這樣做:

$text = 'hello'; 
$text = uc $text; 
+0

你好,你清除了我所有的疑惑!當我回復其他人時,我正在驗證用戶輸入的密鑰。我想將它大寫並驗證它,並將其保留爲大寫字母以備將來檢查。如果它是有效的,我會返回1,否則返回0.一個簡單的** uc **會更容易,但我想在一個例程中完成所有這些。非常感謝你。我很高興在這裏回覆的質量和速度。 – gonfer 2014-10-16 23:28:09

+0

現在我再讀一遍:再次修改@_,變量在例程外被修改,但是在調用子程序時是否需要傳遞變量?這樣,$ ref就是對變量的實際引用,並且您可以用{}去引用它。僅當您使用\來傳遞參數時,纔會使用{}。謝謝! – gonfer 2014-10-16 23:33:15

+0

值得一提的是,你可以使用'convert_to_uppercase($ text);'(在子例程參數前面沒有「\」)而不是'convert_to_uppercase(\ $ text);''shift'前加'\':'my $ ref = \ shift;' – Omar 2017-01-25 14:35:25

相關問題