2012-02-12 65 views
1

我一直在研究一個cgi文件,該文件將檢查用戶是否想要註冊其憑據時是否已經使用了用戶名。如果使用用戶名,它應該通知他們,如果不是,則將其憑據保存到原始平面文件。我在比較foreach語句中賦予值的變量時遇到問題。如果用戶輸入的名稱與已存儲的名稱相同,我告訴foreach將用戶名分配給變量。我有它適當地分配變量,但後話我想告訴它在foreach之外再次比較這些變量,所以操作只能進行一次。這裏是我當前的代碼比較在foreach語句中分配的變量的問題

#!/usr/bin/perl 
use warnings; 
use strict; 
use CGI qw(:standard); 
use CGI::Carp qw/fatalsToBrowser warningsToBrowser/; 
use Digest::MD5 qw(md5 md5_hex md5_base64); 

#telling what variables are still to be used as global 
our ($username, ,$user, $nametaken); 

#assigning some local variables 
my $username = param("username"); 
my $password = param("password"); 
my $hashpass = md5_hex($password); 

print header, start_html(); 

#creating an array from the flatfile that usernames and passwords are stored 
my @users = do { open my $fh, "<", "password.txt" or die $!; map { chomp; split /:/ } <$fh> }; 

#comparing the values in the array to the username entered 
foreach my $user (@users) { 
if ($user eq $username) { 
    #printing here to test if it is comparing correctly which it is 
    print p("$user\n"); 
    #assigning the $user value to $nametaken so it can be compared to later 
    my $nametaken = $user; 
    #printing here to test if the variable was correctly assigned, which it is 
    print p("$nametaken\n"); 
    } 
} 

#printing here to test if the variable was correctly assigned, which it is not printing 
#so the foreach must be causing some king of issue for this variable after it is done and I don't know what that is 
print p("$nametaken\n"); 

#Here is where I am trying to check if the username already exists and then save the user credentials if it does not 
if ($nametaken eq $username) { 
print p("Username already taken, Try again"); 
} 

#As of now the else statement is running everytime and saving new user credentials even if a username is already taken 
else { 
open my $fh, ">>", "password.txt" or die $!; 
print $fh "$username:$hashpass\n"; 
print p("Your account has been created sucessfully"); 
close $fh; 

} 
print end_html(); 
+0

啊,我們的朋友,如果反模式。 – hobbs 2012-02-12 21:21:05

+0

爲什麼使用'qw(...)'和'qw /.../',只需選擇一個。我實際上推薦使用'qw'...''或'qw「...」'來在StackOverflow上使用,因爲它更好地突出顯示。 – 2012-02-14 06:09:47

回答

4

您聲明一個新的內部你foreach循環的詞法範圍的變量$nametaken - 或者說,if {}塊內:my $nametaken = $user;

,可能與$nametaken變量共享相同的名稱你在外面,但它是一個完全不同的變量,其範圍爲if塊 - 一旦您退出if,該變量就完全被遺忘了。無論你分配給它什麼價值都會丟失。

你可以在這裏看到更多的細節有關詞法變量:

http://perldoc.perl.org/perlsub.html#Private-Variables-via-my%28%29


從戰術解決您的問題,您只需從內取出my聲明,如果:$nametaken=$user;

爲了正確地做到這一點,以Perl的方式,你應該重新思考你對問題的方法。您可以使用foreach循環來檢測列表中是否有值,但它絕對不是最好的(可讀性明智,有時甚至是性能明智的)Perl技術。更慣用的方法是使用哈希查找:

my %users = map { ($_ => 1) } @users; # Create a hash with users being keys 
if ($users{$username}) { 
    print "$username already taken!\n"; 
} 
+0

太棒了,我改變了我的代碼並實現了哈希查找。工作完美。謝謝!你能解釋一下哈希設置嗎?當你寫地圖{($ _ => 1)}時,這是什麼意思? – Jared 2012-02-12 23:02:48

+0

@Salmonerd - 我可以:)你可能想要使它成爲一個單獨的問題 - 這是一個有點獨特的主題,可能對其他用戶有用 – DVK 2012-02-12 23:10:06

+0

@ DVK-也許你可以看看我最新的問題,關於嘗試使用散列查找用於登錄驗證。我真的很想更好地理解他們,我想要對他們做的事情真的超過了我的經驗水平。感謝您的幫助。 – Jared 2012-02-13 00:59:04

2

爲什麼$nametaken不具有價值外foreach環是因爲它已被詞法範圍的原因而只內foreach定義。


總是有這樣做的方法不止一種:

my ($nametaken) = grep { /$username/ } @users; 

if ($nametaken) { ... } else { ... } 

或者乾脆:

if (grep { /$username/ } @users) { ... } else { ... } 

這是通常當你在Perl較少的臨時變量減少噪音。

+0

他已經在循環外有'我們的$ nametaken',所以這仍然會給出重複的聲明。 – cjm 2012-02-12 17:36:46

+0

@cjm:Ack。沒有注意到。刪除了不相關的示例。 – Zaid 2012-02-12 17:41:44

3
my $nametaken = $user; 

創建一個名爲$nametaken一個變量無關,與你的外循環宣佈$nametaken

+0

是的,這是問題,對於Perl和變量的範圍以及如何聲明它們仍然很新穎。感謝您指出顯而易見的事情,我想我已經把自己的腦袋纏繞起來了一點。 – Jared 2012-02-12 22:44:21