CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Reference array in class

 



steadyonabix
New User

Aug 23, 2010, 2:10 PM

Post #1 of 5 (496 views)
Reference array in class Can't Post

Hi

I am trying to get to grips with oop in perl and have defined a class that is trying to read a file into an array called LINES defined in the constructor: -


Code
sub new() 
{
my $class = shift;
my $self = {
FILE_NAME => undef,
LINES => []
};
bless($self);
return $self;
}


I can't figure out how to reference the array from a method.

I have done this successfully in another flat perl script: -


Code
map { s/#.*$// | s/^\r?\n?$// } @cfglines = <INFO>;


This reads the whole file into an array and strips out unwanted lines.

Now I am trying to implement the same functionality in a class and want to read the file into the array LINES as defined in the constructor.

Can anyone tell me what the syntax would be?

Thanks in advance


1arryb
User

Aug 24, 2010, 9:00 AM

Post #2 of 5 (487 views)
Re: [steadyonabix] Reference array in class [In reply to] Can't Post

Hi steady,

You might find a perusal of the perlref perldoc to be instructive. In the meantime, assuming your class is called MyClass and that it is implemented in a file called MyClass.pm...


Code
#!/usr/bin/perl 

use MyClass;

# Get an instance of your class.
my $obj = MyClass->new();

# Add some LINES.
push (@{$obj->LINES}, "This is a new LINE.");
push (@{$obj->LINES}, "Here is another new LINE.");
push (@{$obj->LINES}, "This is the third LINE.");

# print the second LINE.
print "$obj->LINES->[1]\n";

# print them all.
map { print "$_\n" } (@{$obj->LINES});


Cheers,

Larry


(This post was edited by 1arryb on Aug 24, 2010, 11:06 AM)


steadyonabix
New User

Aug 24, 2010, 12:30 PM

Post #3 of 5 (478 views)
Re: [1arryb] Reference array in class [In reply to] Can't Post

Thanks Larry

Know where you are coming from with the perl docs and I promise I have been reading all week, still at the stage where it's pretty confusing I'm afraid.

I have managed to come up with this working version of the object and I am using it to parse a config and resource file. Its seems to work well but I am mindful of the many admonitions about unexpected results if you don't really understand references, (like me).

Can you take a look at this and see if I am doing anything that is bad practice? Even better explain why it is in as plain english as possible Wink


Code
#! /usr/bin/perl -w 
package Reader;
use strict;

sub new()
{
my $class = shift;
my @_lines; ## Array to hold the lines
my $self = {
FILE_NAME => undef, ## Name of the file
LINES => \@_lines, ## Ref to array holding the lines
STRIP_EMPTY => 1, ## Default to on
STRIP_COMMENTS => 1 ## Default to on
};
bless($self);
return $self;
}

sub set_comments()
{
my $self = shift;
my $tmp;
if( @_ ){
$tmp =shift;
if( ($tmp == 0) || ($tmp == 1) ){
$self->{STRIP_COMMENTS} = $tmp;
return 1;
}
}
return 0;
}

sub get_comments()
{
my $self = shift;
return $self->{STRIP_COMMENTS};
}

sub set_empty()
{
my $self = shift;
my $tmp;
if( @_ ){
$tmp =shift;
if( ($tmp == 0) || ($tmp == 1) ){
$self->{STRIP_EMPTY} = $tmp;
return 1;
}
}
return 0;
}

sub get_empty()
{
my $self = shift;
return $self->{STRIP_EMPTY};
}

sub refresh()
{
my $self = shift;
if(! defined $self->{FILE_NAME}){return 0} ## File name not set yet

## Open the file
open(INFO, $self->{FILE_NAME}) or die ("Unable to open file " . $self->{FILE_NAME});

if( $self->{STRIP_COMMENTS}){
map { s/#.*$// | s/^\r?\n?$// } @{ $self->{'LINES'} } = <INFO>;
} else {
@{ $self->{'LINES'} } = <INFO>;
}
if( $self->{STRIP_EMPTY} ) {
@{ $self->{'LINES'} } = grep /\S/, @{ $self->{'LINES'} }
}
close(INFO);
}

sub set_filename()
{
my $tmp;
my $self = shift;
if(@_) {
$tmp = shift;
if ( (! -e $tmp) || (! -r $tmp)){ return 0 } ## Not existing readable file so don't set
$self->{FILE_NAME} = $tmp;
}
return 1;
}

sub get_filename()
{
my $self = shift;
return $self->{FILE_NAME};
}

1;


Usage: -


Code
my $cf_reader = Reader->new();			## Config file reader 

##-----------------------------------------------
## Create the path to the config file
##-----------------------------------------------
if ($#ARGV == 0){
$install_dir = shift() . '/';
}
else{
$install_dir = './';
}
$tmpstr = $install_dir . 'pmon_conxn_mgr.cfg';

##-----------------------------------------------
## Read in the cfg file
##-----------------------------------------------
if(! $cf_reader->set_filename($tmpstr)){
$msg = "Config file not found / readable (" . $tmpstr . ")";
&tidyupexit(1, $msg);
}
$cf_reader->refresh();


Many thanks

Brad


1arryb
User

Aug 24, 2010, 1:39 PM

Post #4 of 5 (475 views)
Re: [steadyonabix] Reference array in class [In reply to] Can't Post

Brad,

It looks basically correct. A couple of things.

1. In several places, you declare $tmp outside of the block where it is used several times.
2. The 3-arg version of open is preferred (see: http://stackoverflow.com/questions/1479741/why-is-three-argument-open-calls-with-lexical-filehandles-a-perl-best-practice.
3. Precompile static regex's using /o.
4. I'd write the refresh() method as:

Code
sub refresh()  
{
my $self = shift;

return 0 unless defined $self->{FILE_NAME};

## Open the file.
open(my $infoFH, '<', $self->{FILE_NAME})
or die "Unable to open file $self->{FILE_NAME}";

# This loop iterates through the file's lines just once, no matter which flags are set.
while ( my $line = <$infoFH> ) {
chomp($line);
if ( $self->{STRIP_COMMENTS} ) {
next if $line =~ /^\s*#/o;
}
if( $self->{STRIP_EMPTY} ) {
next unless $line =~ /\S/o;
}
push(@{$self->{LINES}}, $line);
}
close($infoFH);
}


Cheers,

Larry


steadyonabix
New User

Aug 25, 2010, 5:34 AM

Post #5 of 5 (469 views)
Re: [1arryb] Reference array in class [In reply to] Can't Post

Thanks Larry, that's very helpfull: -

1. In several places, you declare $tmp outside of the block where it is used several times.

That makes sense as this is a compliled language, I have been working with korn shell the last couple of years and am used to defining vars at the top of the function. Need to change my mindset.


2. The 3-arg version of open is preferred (see: http://stackoverflow.com/questions/1479741/why-is-three-argument-open-calls-with-lexical-filehandles-a-perl-best-practice.

That's very enlightening, thanks I didn't realise I could use open that way. (I am still at the stage were I am cribbing stuff of the net to get things done)


3. Precompile static regex's using /o.

I don't understand the benefit, I'll have to look it up in the book tonight when I get home.


4. I'd write the refresh() method as:

That's nice. I don't understand your comment about looping only once, I suspect because I don't know what flags you are refering to. I like it though so will substitute your code for mine as it is more readable.

Thanks for the help :)

Actually looking at this a little deeper, would the command stripping the comments delete the whole line? I think in my version it deletes comments half way along the line but gives you the first half. I'll play with it later when I get home..

I just played with this at home and have decided to adopt your refresh with one change: -


Code
        if ( $self->{STRIP_COMMENTS} ) {  
next if $line =~ s/#.*//o;
}


Now it strips all comments to the end of the line.

I will make the other changes you suggested.

Once again many thanks Smile


(This post was edited by steadyonabix on Aug 25, 2010, 9:45 AM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives