in reply to How to open sub FH when filename is passed to sub?

You must be the same person who posted create subroutine. You really should show us what your requirements are, and most importantly, what you data looks like. Let's make some up. Save this in a text file named in_file.txt:
D:Aspartic Acid
E:Glutamic Acid
F:Phenylalanine
G:Glycine
H:Histidine
I:Isoleucine
K:Lysine
L:Leucine
M:Methionine
N:Asparagine
Our requirements will be simple:
  1. pass a file name ('in_file.txt') to a subroutine that
    1. opens the file in read mode
    2. reads one line at a time
    3. remove trailing newline
    4. splits the line on a token (':') into two elements
      1. the first element is a key
      2. the second element will be the value
    5. stores the key-value pair in a hash
    6. returns the hash
  2. store the returned hash in a new hash
  3. loop through the hash and print the key-val pairs
Here goes:
#!/usr/bin/perl -w # always use strict and warnings (-w from above) use strict; # 1 and 2 my %new_hash = create_hash('in_file.txt'); # 3 while(my($key,$val) = each %new_hash) { print "$key => $val\n"; } sub create_hash { my $filename = shift; my %hash; # 1.1 open(FILE,'<',$filename) or die "can't read $filename: $!"; # 1.2 - you get the point ;) while (my $line = <FILE>) { chomp $line; my($key,$val) = split (':',$line,2); $hash{$key} = $val; } return %hash; }
Now, at thist point i recommend you go buy and read Learning Perl. After you get some basics under your belt, you can then check out BioPerl and their lengthy Tutorial.

Good luck!

jeffa

L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
(the triplet paradiddle with high-hat)

Replies are listed 'Best First'.
Re: (jeffa) Re: How to open sub FH when filename is passed to sub?
by Anonymous Monk on May 05, 2002 at 16:14 UTC

    Thank you for your help jeffa!


    I am a beginner for perl. My new hash keys I can read in
    from a file, but my values I have to get them from my main
    hash.Why you use shift? Does it mean it can change
    different filename everytime you call sub? if it is so,
    that is what I want.
    Please help

      You are most welcome. Yes, that is exactly why i use shift. shift returns the first value from an array, in this case it is the implied array @_ which is used by Perl to store the arguments passed to a given subroutine. I could have used this instead:
      my $filename = shift @_; # or even my ($filename) = @_; # multiple arguments are best caught this way: my ($first,$second,$third) = @_; # but some folks prefer my $first = shift; my $second = shift; my $third = shift;
      Most (if not all...) other languages use an argument list to specify what a subroutine can be 'passed', as well as a return type (together these form the 'signature'). For example, in Java, these:
Re: (jeffa) Re: How to open sub FH when filename is passed to sub?
by Anonymous Monk on May 08, 2002 at 01:32 UTC

    Thank you so much jeffa!


    I do make my sub hash, it gave me all the result, but it still tell me :
    Use of uninitialized value at ./lx line 97.
    Use of uninitialized value at ./lx line 97.
    total 10 times Use of above context.
    my sub like:


    sub create_hash {
    my $myhashname=shift;
    my %myhashname=%_;
    my @keys=@_;


       unless(open(FH, ">$myhashname") ) {
           print STDERR "Cannot open file\"$myhashname\"\n\n";
            exit;}


       @myhashname{@keys}=@mydnahash{@keys};
        while (($k, $v)=each %myhashname){
        print FH "$k=>$v, "};


        close FH;
        return %myhashname;
    }


    and I call sub like:

    my %myeditedhash= create_hash('myeditedhash',@editedsites, @mydnahash{@editedsites});


    print FH "$k=>$v, "}; is line 97.what is wrong? please help.

      You are welcome, but i am not getting through to you. You need to sit down and learn some basics first. Please read this book: Learning Perl. Repeat. Please read this book: Learning Perl.

      The reason for the warnings is because your hash probably has keys, but no values. Now, your problem is two fold:

      1. the way you are passing arguments to the sub
      2. the way you are receiving the arguments in the sub
      You refuse to show me what your input is and what your desired output should be, so i really can't help you any further with THIS problem. I can show you some examples of how to call functions in Perl, though. Run this code first to see the output, then study the code itself.
      use strict; my @array1 = (1,2,3,4); my @array2 = (5,6,7,8); my %hash = ( key => 'val', foo => 'bar', ); print '=' x 20, "\nwrong way:\n"; wrong1(@array1,@array2); sub wrong1 { my (@a1,@a2) = @_; print "array 1: @a1\n"; print "array 2: @a2\n"; # notice that @a2 is empty } print '=' x 20, "\nright way:\n"; right1(\@array1,\@array2); sub right1 { my @a1 = @{ shift @_ }; my @a2 = @{ shift @_ }; print "array 1: @a1\n"; print "array 2: @a2\n"; # multiple arrays must be passed in as references } print '=' x 20, "\nwrong way:\n"; wrong2(%hash); sub wrong2 { my %hash = %_; while (my($k,$v) = each %hash) { print "$k => $v\n"; } # %_ is not special, use @_ instead - always! } print '=' x 20, "\nright way:\n"; right2(%hash); sub right2 { my %hash = @_; while (my($k,$v) = each %hash) { print "$k => $v\n"; } # a hash is really just a special kind of array # and yes, multiple hashes must be passed as references too } # last - a hash slice my %slice; @slice{@array1} = @array2; print '=' x 20, "\nhash slice:\n"; while (my($k,$v) = each %slice) { print "$k => $v\n"; } # and don't creat hash slices inside an subroutine's # argument list - that is bad bad bad ;)
      Good luck, and please read this book: Learning Perl.

      jeffa

      Cargo Cult Programming - Just say 'NO!'