×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!
  • Students Click Here

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Jobs

assistance with a better way to do this

assistance with a better way to do this

assistance with a better way to do this

(OP)
OK folks, this is taking some courage to post this, because it lays bare my inexperience with some aspects of Perl.

I am working on a self-contained bit of code. If an outside module is used, it really needs to be part of the basic Perl installation. (RHEL 5.9, perl-5.8.8-40) )

I've read some posts on here that 'appear' they could do what I envision, but again, my lack of understanding gets in the way.

I have need of a way to loop though some data, and I get stuck thinking I have to write the same code over and over, but know that is not the case, I just don't know the proper way to do this, and possible to even explain it, so I will show you.

I am using a hash now for each 'set' of data, but this data is common, and I'd like to be able to deal with 'all' of these 'sets' in a loop, rather than dealing with each 'set' separately in it's own loop. If I can find a way to do this, then I can simply continue to add data 'sets' to this 'group', and the code that will process the 'sets' will never (sic) need to change again.

Consider this code:

CODE

#!/usr/bin/perl
use strict;

our %Barcode1 = ();
our %Barcode2 = ();
our %Barcode3 = ();

%Barcode1 = (
    enabled => 1,
    x       => 40,
    y       => 50,
    height  => 0.40,
    width   => 0.80,
    type    => "code39",
    value   => "ABC123",
);
%Barcode2 = (
    enabled => 0,
    x       => 40,
    y       => 50,
    height  => 0.40,
    width   => 0.80,
    type    => "datamatrix",
    value   => "ABC123XYZ!",
);
%Barcode3 = (
    enabled => 1,
    x       => 100,
    y       => 90,
    height  => 0.40,
    width   => 0.40,
    type    => "qrcode",
    value   => "http://url.com",
); 

I'd like a 'container' or 'group' for the BarcodeXX hashes. So I can keep adding to the group. One time I may only need a single barcode dataset, the next time I might need 10. Rather than hardocding for a fixed number, and then all the extensive code to handle that number, what would be a way to get this all into a single variable or reference that I can just loop through?

Here's what I end up doing on the output side, and it gets ugly and repetitive fast:

CODE

if ( $Barcode1{enabled} eq "1" ) {
            &print_barcode(
                {
                    x       => $Barcode1{x},
                    y       => $Barcode1{y},
                    type    => $Barcode1{type},
                    height  => $Barcode1{height},
                    width   => $Barcode1{width},
                    data    => $Barcode1{value},
                }
            );
        }

        if ( $Barcode2{enabled} eq "1" ) {
            &print_barcode(
                {
                    x       => $Barcode2{x},
                    y       => $Barcode2{y},
                    type    => $Barcode2{type},
                    height  => $Barcode2{height},
                    width   => $Barcode2{width},
                    data    => $Barcode2{value},
                }
            );
        }

        if ( $Barcode3{enabled} eq "1" ) {
            &print_barcode(
                {
                    x       => $Barcode3{x},
                    y       => $Barcode3{y},
                    type    => $Barcode3{type},
                    height  => $Barcode3{height},
                    data    => $Barcode3{value},
                }
            );
        }

sub print_barcode {

    # Pass barcode type, data to encode
    # optionals: X,Y coordinates, hscale, vscale, height, width, options
# not the real routine, but included here so code snippets will give output
    my ($args) = @_;

    my $x         = $args->{x};
    my $y         = $args->{y};
    my $symbology = $args->{type};
    my $data      = $args->{data};
    my $hscale    = $args->{hscale};
    my $vscale    = $args->{vscale};
    my $height    = $args->{height};
    my $width     = $args->{width};
    my $options   = $args->{options};

    unless ($symbology) { return; }
    unless ($data) { return; }

    unless ($hscale) { $hscale = 0.2845; }
    unless ($vscale) { $vscale = 0.2845; }
    unless ($x)      { $x      = 0; }
    unless ($y)      { $y      = 0; }

    if ($height) { $height = "height=" . $height; }
    if ($width)  { $width  = "width=" . $width; }

    print "Barcode Symbology: $symbology \n";
    print "printing data [$data] at X=$x, Y=$y \n\n";
} 

I _know_ this is ugly, and I want to learn how to make this type of looping more efficient, especially from a code maintenance standpoint. The loops where I test if the barcode is enabled and then call a routine would be nice to just have one in the program and loop through all the Barcode 'variables'. I'm pretty sure I don't want to try and assign a variable counter and use that counter as part of another variable name..

$Count=1
if $Barcode$Count eq "1" ...

That doesn't look like a good way to do things, is it? I know that $Barcode$Count doesn't work, but understand what I'm trying to do?

I envision something like this:

CODE

loop through container start (counter = X?)
    if $Barcode X is enabled
        output stuff for $Barcode X
        print $Barcode X{x} 
        print $Barcode X {data}
        etc, etc.
X++ until looped through all items in container
End of loop 

I don't care what Barcode1, Barcode2, are called as long as the data sets are grouped together.

Could some one please point me in the right direction? And if code snips are exampled, please explain them a bit to me? I've done websearches and they all leave me short on understanding...

I appreciate any time or effort one would give to help me learn and understand better. Thank you

RE: assistance with a better way to do this

(OP)
I can't see a way to delete my OP. After spending much time reading and trial and error, I came up with a hash of hashes to solve my situation. I am able to grow the number of barcodes dynamically and have a single loop to process all of them, whether there are 1 or 100.

CODE

#!/usr/bin/perl

use strict;
use warnings;

my %BARCODE = (
    Barcode1 => {
        enabled => 1,
        type    => 'code39',
        data    => '12345ABC',
        options => 'includetext',
        width   => '',
        height  => '0.4',
        hscale  => '',
        vscale  => '',
        x       => '35.0',
        y       => '45.0',
    },
    Barcode2 => {
        enabled => 1,
        type    => 'interleaved22of5',
        data    => '1234567812',
        options => 'includetext',
        width   => '',
        height  => '0.4',
        hscale  => '',
        vscale  => '',
        x       => '35.0',
        y       => '65.0',
    },
    Barcode3 => {
        enabled => 0,
        type    => 'qrcode',
        data    => 'http:web.url',
        options => '',
        width   => '',
        height  => '0.4',
        hscale  => '',
        vscale  => '',
        x       => '65.0',
        y       => '95.0',
    },
);

# Create a bunch of barcodes and data
for ( my $i = 4 ; $i <= 15 ; $i++ ) {
    my $tmpstr = "Barcode$i";
    $BARCODE{$tmpstr}{enabled} = 1;
    $BARCODE{$tmpstr}{type}    = 'qrcode';
    $BARCODE{$tmpstr}{data}    = "http:web$i.url";
    $BARCODE{$tmpstr}{options} = '';
    $BARCODE{$tmpstr}{width}   = "0.$i";
    $BARCODE{$tmpstr}{height}  = '0.4';
    $BARCODE{$tmpstr}{hscale}  = '0.5';
    $BARCODE{$tmpstr}{vscale}  = '1.0';
    $BARCODE{$tmpstr}{x}       = 65.0 + $i;
    $BARCODE{$tmpstr}{y}       = '95.0';
}

# test if barcode is enabled, print if it is
foreach my $barcode ( sort keys %BARCODE ) {
    if ( $BARCODE{$barcode}{enabled} eq "1" ) {
        print "Will print $barcode\n";
        &print_barcode(
            {
                x      => $BARCODE{$barcode}{x},
                y      => $BARCODE{$barcode}{y},
                type   => $BARCODE{$barcode}{type},
                height => $BARCODE{$barcode}{height},
                width  => $BARCODE{$barcode}{width},
                data   => $BARCODE{$barcode}{data},
            }
        );
    }
}

sub print_barcode {

    # Pass barcode type, data to encode
    # optionals: X,Y coordinates, hscale, vscale, height, width, options
    # not the real routine, but included here so code snippets will give output
    my ($args) = @_;

    my $x         = $args->{x};
    my $y         = $args->{y};
    my $symbology = $args->{type};
    my $data      = $args->{data};
    my $hscale    = $args->{hscale};
    my $vscale    = $args->{vscale};
    my $height    = $args->{height};
    my $width     = $args->{width};
    my $options   = $args->{options};

    unless ($symbology) { return; }
    unless ($data)      { return; }

    unless ($hscale) { $hscale = 0.2845; }
    unless ($vscale) { $vscale = 0.2845; }
    unless ($x)      { $x      = 0; }
    unless ($y)      { $y      = 0; }

    if ($height) { $height = "height=" . $height; }
    if ($width)  { $width  = "width=" . $width; }

    print "Barcode Symbology: $symbology \n";
    print "printing data [$data] at X=$x, Y=$y \n\n";
} 

RE: assistance with a better way to do this

I would use an array of hashes instead of a hash of hashes.
In short, creation and printing become (untested):

CODE -->

for ( my $i = 4 ; $i <= 15 ; $i++ ) {
    push @BARCODE, {'enabled',1,'type','qrcode','data',"http:web$i.url",'options','',
    'width',"0.$i",'height',0.4,'hscale',0.5,'vscale',1,'x',65 + $i,'y',95};
}
for (my $i=0;$i<@BARCODE;$i++) {
    if (exists $BARCODE[$i]{enabled} && $BARCODE[$i]{enabled}) {
          #with the double test you don't create new records that were non existent
        print "Will print barcode #$i\n";
        &print_barcode($BARCODE[$i]);
    }
}
sub print_barcode {
   my ($refbarc) = @_;
    return unless $$refbarc{type};
    return unless $$refbarc{data};
      #...
    print "Barcode Symbology: $$refbarc{type}\n";
    print "printing data [$$refbarc{data}] at X=$$refbarc{x}, Y=$$refbarc{y}\n\n";
} 

http://www.xcalcs.com : Online engineering calculations
http://www.megamag.it : Magnetic brakes for fun rides
http://www.levitans.com : Air bearing pads

RE: assistance with a better way to do this

(OP)
Thanks prex1. I had run across references to 'an array of hashes' but never found an example that really showed how to push the hash into the array. I also found interesting what you altered in the print_barcode sub. I tend to write code very much like a full language and I miss out on the efficiency of other methods.

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close