Re: adding to hash/writing to file errors
by GrandFather (Saint) on May 05, 2008 at 03:37 UTC
|
First: use strictures (use strict; use warnings;).
Second: named subs don't belong inside a while loop (replies to Perl scoping not logical...? may help understand why).
When you add use strict; you will find the variable $username can't be found. Because you use it in various subs you need to pass it into those subs. You've done that for greeting, but not elsewhere.
Perl is environmentally friendly - it saves trees
| [reply] [d/l] |
Re: adding to hash/writing to file errors
by apl (Monsignor) on May 05, 2008 at 11:52 UTC
|
GrandFather has already moved you in the proper direction, leaving me free to be curious.
i dunno what in the world we have done wrong.
What did you do to try to debug your program? Did you use the Perl Debugger? Did you use print statements? Did you try to determine the minimal program that caused the problem? | [reply] |
|
|
Okay, here is the revised version, now i get this error when it is compiling:
Global symbol "%logins" requires explicit package name at ./maybe.pl line 62.
Execution of ./maybe.pl aborted due to compilation errors.
# AGTS-CLI(Andrew's GTK Time System-Command Line version)
# Copyright (C) 2008 Andrew Harris
#
# This program is free software: you can redistribute it and/or mod
+ify
# it under the terms of the GNU General Public License as published
+ by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, email andrew2325@gmail.com!
# Contributors: Kelly Royal <netdaemon862@gmail.com>
#!/usr/bin/perl
use strict;
use warnings;
my $time = localtime;
sub verify {
my $username = shift;
my %logins = ("aharris" => "1234", "kroyal" => "5678");
if (exists $logins{$username}) {
login($username, %logins);
}
else {
print "$username does not exist in our database.\n";
}
}
sub login {
my %logins = shift;
my $username = shift;
print "Enter your password: ";
chomp(my $pass = <STDIN>);
if ($pass <=> $logins{$username}) {
greeting($username);
}
else {
print "Incorrect password!\n";
}
}
sub greeting {
my $username = shift;
print "Welcome $username.\n";
print "Current time is $time\n\n\n";
}
sub admin {
print "Administrative Tools\n";
print "1. Add user\n";
print "2. Remove user\n";
print "Enter selection: ";
chomp(my $selection = <STDIN>);
if ($selection == "1") {
print "Enter new user name: ";
chomp(my $newname = <STDIN>);
print "Enter password for $newname: ";
chomp(my $newpass = <STDIN>);
$logins{$newname} = $newpass;
print "User added.\n";
}
}
while (1) {
print "Welcome, Main Menu\n";
print "1. Log in\n";
print "2. Log out\n";
print "3. Administration\n";
print "Enter selection: ";
my $selection = <STDIN>;
if ($selection == "1") {
print "Enter your user name to log in: ";
chomp(my $username = <STDIN>);
verify($username);
open(MYLOGINFILE, ">>login.txt");
print MYLOGINFILE "$username:$time\n";
close(MYLOGINFILE);
}
elsif ($selection == "2") {
print "Enter your user name to log out: ";
chomp(my $username = <STDIN>);
verify($username);
open(MYLOGOUTFILE, ">>login.txt");
print MYLOGOUTFILE "$username:$time\n";
close(MYLOGOUTFILE);
}
elsif ($selection == "3") {
admin;
}
}
When I remove use strict; use warnings;, it runs, but it doesn't add the users/passwords to the hash.. | [reply] [d/l] |
|
|
use strict; requires that you declare all variables using my in all scopes. The variable $username is used in your "login" sub, but it is not declared there, nor is it declared as a global variable. Since your call to "login" is:
login($username, %logins);
I believe you might want:
sub login {
my $username = shift;
my %logins = shift;
You only declare your $time variable in your "greeting" sub, but you use it in the "while" loop.
| [reply] [d/l] [select] |
|
|
|
|
|
|
| [reply] [d/l] |
|
|
|
|
|
|
Re: adding to hash/writing to file errors
by andrew2325 (Initiate) on May 05, 2008 at 17:09 UTC
|
Here are the changes that I have made.
# AGTS-CLI(Andrew's GTK Time System-Command Line version)
# Copyright (C) 2008 Andrew Harris
#
# This program is free software: you can redistribute it and/or mod
+ify
# it under the terms of the GNU General Public License as published
+ by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, email andrew2325@gmail.com!
# Contributors: Kelly Royal <netdaemon862@gmail.com>
#!/usr/bin/perl
use strict;
use warnings;
my $time = localtime;
sub verify {
my $username = shift;
my %logins = shift;
if (exists $logins{$username}) {
login($username, %logins);
}
else {
print "$username does not exist in our database.\n";
}
}
sub login {
my %logins = shift;
my $username = shift;
print "Enter your password: ";
chomp(my $pass = <STDIN>);
if ($pass <=> $logins{$username}) {
greeting($username);
}
else {
print "Incorrect password!\n";
}
}
sub greeting {
my $username = shift;
print "Welcome $username.\n";
print "Current time is $time\n\n\n";
}
sub admin {
my %logins = shift;
print "Administrative Tools\n";
print "1. Add user\n";
print "2. Remove user\n";
print "Enter selection: ";
chomp(my $selection = <STDIN>);
if ($selection == "1") {
print "Enter new user name: ";
chomp(my $newname = <STDIN>);
print "Enter password for $newname: ";
chomp(my $newpass = <STDIN>);
$logins{$newname} = $newpass;
print "User added.\n";
}
}
while (1) {
print "Welcome, Main Menu\n";
print "1. Log in\n";
print "2. Log out\n";
print "3. Administration\n";
print "Enter selection: ";
my $selection = <STDIN>;
my %logins = ("kroyal" => "5678", "aharris" => "1234");
if ($selection == "1") {
print "Enter your user name to log in: ";
chomp(my $username = <STDIN>);
verify($username, %logins);
open(MYLOGINFILE, ">>login.txt");
print MYLOGINFILE "$username:$time\n";
close(MYLOGINFILE);
}
elsif ($selection == "2") {
print "Enter your user name to log out: ";
chomp(my $username = <STDIN>);
verify($username);
open(MYLOGOUTFILE, ">>login.txt");
print MYLOGOUTFILE "$username:$time\n";
close(MYLOGOUTFILE);
}
elsif ($selection == "3") {
admin(%logins);
}
}
Now when I run it, only one of the default users work and you can't add users. I get the following errors when logging in:
Welcome, Main Menu
1. Log in
2. Log out
3. Administration
Enter selection: 1
Enter your user name to log in: aharris
Odd number of elements in hash assignment at ./maybe.pl line 23, <STDIN> line 2.
Odd number of elements in hash assignment at ./maybe.pl line 33, <STDIN> line 2.
Enter your password: 1234
Use of uninitialized value $logins{"aharris"} in numeric comparison (<=>) at ./maybe.pl line 37, <STDIN> line 3.
Welcome aharris.
Current time is Mon May 5 11:58:30 2008
| [reply] [d/l] |
|
|
my $username = shift;
my %logins = @_;
and thisif ($pass <=> $logins{$username})
becomes
if( $pass eq $logins{$username} )
ie use a string comparison operator.
http://perldoc.perl.org/perlop.html#Equality-Operators
Numeric test:
if ($selection == "1")
becomes if ($selection == 1)
Cheers
Chris | [reply] [d/l] [select] |
Re: adding to hash/writing to file errors
by andrew2325 (Initiate) on May 07, 2008 at 04:03 UTC
|
I made the changes as you guys instructed and made some changes of my own, now I encounter an unusual error. Welcome, Main Menu
1. Log in
2. Log out
3. Administration
Enter selection: 3
Administrative Tools
1. Add user
2. Remove user
Enter selection: 1
Enter new user name: ggamber
Enter password for ggamber: 9898
User added.
Welcome, Main Menu
1. Log in
2. Log out
3. Administration
Enter selection: 1
Enter your user name to log in: ggamber
Enter your password: 9898
Use of uninitialized value $username in hash element at ./agts-cli.pl line 39, <STDIN> line 7.
Use of uninitialized value in string eq at ./agts-cli.pl line 39, <STDIN> line 7.
Incorrect password!
New code:
#!/usr/bin/perl
#
# AGTS-CLI(Andrew's GTK Time System-Command Line version)
# Copyright (C) 2008 Andrew Harris
#
# This program is free software: you can redistribute it and/or mod
+ify
# it under the terms of the GNU General Public License as published
+ by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, email andrew2325@gmail.com!
# Contributors: Kelly Royal <netdaemon862@gmail.com>
use strict;
use warnings;
my $time = localtime;
my %logins = ("aharris" => "1234", "kroyal" => "5678");
sub verify {
my $username = shift;
if (exists $logins{$username}) {
login($username, %logins);
}
else {
print "$username does not exist in our database.\n";
}
}
sub login {
my %logins;
my $username;
print "Enter your password: ";
chomp(my $pass = <STDIN>);
if ($pass eq $logins{$username}) {
greeting($username);
}
else {
print "Incorrect password!\n";
}
}
sub greeting {
my $username = shift;
print "Welcome $username.\n";
print "Current time is $time\n\n\n";
}
sub admin {
print "Administrative Tools\n";
print "1. Add user\n";
print "2. Remove user\n";
print "Enter selection: ";
chomp(my $selection = <STDIN>);
if ($selection == 1) {
print "Enter new user name: ";
chomp(my $newname = <STDIN>);
print "Enter password for $newname: ";
chomp(my $newpass = <STDIN>);
$logins{$newname} = $newpass;
print "User added.\n";
}
}
while (1) {
print "Welcome, Main Menu\n";
print "1. Log in\n";
print "2. Log out\n";
print "3. Administration\n";
print "Enter selection: ";
my $selection = <STDIN>;
if ($selection == 1) {
print "Enter your user name to log in: ";
chomp(my $username = <STDIN>);
verify($username);
open(MYLOGINFILE, ">>login.txt");
print MYLOGINFILE "$username:$time\n";
close(MYLOGINFILE);
}
elsif ($selection == 2) {
print "Enter your user name to log out: ";
chomp(my $username = <STDIN>);
verify($username);
open(MYLOGOUTFILE, ">>login.txt");
print MYLOGOUTFILE "$username:$time\n";
close(MYLOGOUTFILE);
}
elsif ($selection == 3) {
admin;
}
}
| [reply] [d/l] |