2012-02-12 2 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

+0

Почему вы используете 'qw (...)' и 'qw /.../', просто выберите один. Я бы рекомендовал 'qw '...'', или 'qw" ... "' для использования в StackOverflow, так как он лучше подчеркивает. –

ответ

4

Вы объявляете новую лексическую область видимости переменной $nametaken внутри вашего foreach цикла - или, вернее, внутри if {} блока: my $nametaken = $user;

Это может делить такое же имя с $nametaken переменной, был снаружи, но это совершенно другая переменная, с объемом этого блока if - как только вы выходите из if, эта переменная полностью забыта. Независимо от того, какое значение вы назначили ему, теряется.

Вы можете посмотреть более подробную информацию о лексически контекстные переменные здесь:

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


Чтобы решить вашу проблему тактически, вам нужно просто удалить my декларацию изнутри, если: $nametaken=$user;

Чтобы сделать это правильно, на Perl-пути вы должны пересмотреть свой подход к проблеме alltogether. Вы можете использовать цикл 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

+0

@Salmonerd - я могу :) Вы можете задать отдельный вопрос - это несколько отличная тема, которая может быть полезна для других пользователей. – DVK

+0

@ DVK- Может быть, вы можете взглянуть на мой новый вопрос о попытке использовать хеш-поиск для подтверждения входа. Я бы очень хотел их лучше понять, и то, что я пытаюсь сделать с ними, действительно выше моего уровня опыта. Спасибо за вашу помощь. – Jared

2

Причина, почему $nametaken не имеет значения вне цикла foreach потому, что она была лексический ограниченным, чтобы быть определена только внутри foreach.


Существует всегда больше, чем один способ сделать это:

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

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

или просто:

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

Это обычно менее шумными, когда вы меньше временных переменных в Perl.

+0

У него уже был 'наш $ nametaken' вне цикла, так что это все равно даст повторяющиеся объявления. – cjm

+0

@cjm: Ack. Не заметил этого. Исключительный пример удален. – Zaid

3
my $nametaken = $user; 

создает переменную новый с именем $nametaken, который не имеет ничего общего с $nametaken вы объявленной вне цикла.

+0

Да, это была проблема, все еще довольно новая для Perl, а также объем переменных и способы их объявления. Спасибо за то, что я указал на очевидное, я думаю, что моя голова обернута вокруг этого немного лучше. – Jared