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: Need a Custom or Prewritten Perl Program?: I need a program that...: Re: [gopsi1234] Generate a C file from CSV file using perl: Edit Log



Zhris
Enthusiast

Jul 1, 2014, 8:32 AM


Views: 51455
Re: [gopsi1234] Generate a C file from CSV file using perl

Hi gopsi,

Firstly, it looks as though you are making good progress, so well done for that!

Rather than give you a working version right away lets see if we can address some of your issues and perhaps you can fix your code yourself.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

At the top of every script you write you should always use strict and warnings:


Code
use strict; 
use warnings;


These will report on various issues during compilation and run time. You'll notice the following:


Code
Global symbol "@name" requires explicit package name at line 13. 
Global symbol "@name" requires explicit package name at line 17.
Execution aborted due to compilation errors.


You declare the variable @names at the top, but actually use @name.

Upon rerunning the following error is reported:


Code
Can't use an undefined value as an ARRAY reference at line 26, <DATA> chunk 4.


This is because you have tried to use a non existent hash entry 'memid' as an array reference. When you split the line, you didn't incorporate the space after each comma and the key is actually ' memid'.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

When you enter the while loop, the first thing you will need to do is remove the newline character on the end of each line. You would usually use the chomp function to do this. However you have additional whitespace, therefore I suggest using a regexp. You also mentioned you have removed blank lines, but alternatively you can just skip them using another regexp:


Code
while (<DATA>) 
{
next if m/^\s*$/; # skip blank lines.
s/\s+$//; # remove any whitespace from the end of the line.
...


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

You can then go ahead and split the line as you have done, however incorporate the space after the comma, and just to be on the safe side consider incorporating potential space before the comma:


Code
my @list = split(/\s*,\s*/);


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Now remember, you already have the row as a list in @list. When you need to store the header, just copy this list:


Code
@names = @list;


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

You have decided upon storing your data into a hash of arrays, then iterating through it at the end to actually print out the data. Its perfectly possible to use a hash of arrays, but doesn't make as much sense as using an array of hashes, since each row is unique/individual. I would use the hash slice technique I showed you in the previous post, and push the hash onto the array:


Code
my %hash;   
@hash{@names} = @list;
push @data, \%hash;


This will ensure if a new column is added, you don't have to make adjustments to the code. An alternative is to use an array of arrays, then worry about matching up each value to its column name later on:


Code
push @data, \@list; 

...

my @head_b = qw(memid vendorid);
my @indexes;

for my $key (@head_b)
{
my ($index) = grep { $key eq $head[$_] } 0 .. $#head;
push @indexes, $index;
}

for (@data)
{
printf "%s, %s\n", @{$_}[@indexes];
}


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Before attempting to print out the data, another useful module is Data::Dumper. You can dump your data structure to stdout and inspect it to check its how you expected:


Code
use strict; 
use warnings;
use Data::Dumper;

my @data;

while (<DATA>)
{
...
}

print Dumper \@data;


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Use the technique I showed you in the previous post in a loop to print the data:


Code
for (@data) 
{
printf "%s, %s\n", @{$_}{qw/vendorid memid/};
}


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

I've actually used some bad practices, its better to use named variables whenever possible, it is easier to understand code like this, and you won't have problems if $_ is reassigned i.e. a loop within a loop:


Code
... 
while (my $row = <DATA>) {
...
for my $row (@data) {
...


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

I hope you find these pointers useful.

Regards,

Chris


(This post was edited by Zhris on Jul 2, 2014, 7:44 AM)


Edit Log:
Post edited by Zhris (Enthusiast) on Jul 1, 2014, 8:33 AM
Post edited by Zhris (Enthusiast) on Jul 1, 2014, 8:34 AM
Post edited by Zhris (Enthusiast) on Jul 1, 2014, 8:39 AM
Post edited by Zhris (Enthusiast) on Jul 1, 2014, 8:42 AM
Post edited by Zhris (Enthusiast) on Jul 1, 2014, 8:49 AM
Post edited by Zhris (Enthusiast) on Jul 1, 2014, 8:52 AM
Post edited by Zhris (Enthusiast) on Jul 1, 2014, 8:57 AM
Post edited by Zhris (Enthusiast) on Jul 1, 2014, 9:47 AM
Post edited by Zhris (Enthusiast) on Jul 1, 2014, 9:51 AM
Post edited by Zhris (Enthusiast) on Jul 1, 2014, 10:00 AM
Post edited by Zhris (Enthusiast) on Jul 2, 2014, 7:44 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