Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

assistance with a better way to do this 1

Status
Not open for further replies.

Hemo

Programmer
Apr 9, 2003
190
US
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   => "[URL unfurl="true"]http://url.com",[/URL]
);

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
 
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";
}
 
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";
}

: Online engineering calculations
: Magnetic brakes for fun rides
: Air bearing pads
 
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.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top