Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

hi monks,
i am trying to print the lastname first and firatname last, below is my code.
#!/usr/bin/perl $input=''; %nme=(); $fn=''; $ln=''; while() { print "enter the name\n"; chomp($input=<STDIN>); if($input ne '') { ($fn,$ln)=split('',$input); print "$fn, $ln\n"; $nme{$ln}=$fn; } else { last; } foreach $lastname(sort keys %nme) { print "$lastname, $nme{$lastname}\n"; }
it only interchanging only two char of first word, could any one helpout me .

Replies are listed 'Best First'.
Re: Problem in printing lastname and firstname
by jwkrahn (Abbot) on Nov 18, 2006 at 13:32 UTC
    You are using split('',$input) which splits $input into individual characters. You should be using split(' ',$input) which will split on whitespace.

Re: Problem in printing lastname and firstname
by shmem (Chancellor) on Nov 18, 2006 at 14:29 UTC
    Addendum to the previous posts. Read perlre, read split.

    To split on any amount of whitespace, use a regular expression:

    ($fn,$ln) = split(/\s+/,$input);

    Note that you'll get only the first two words without the third argument to split - the number of fields you want to split into:

    $input = "foo bar blurf"; ($f,$s) = split /\s+/, $input; print "<$f> <$s>\n" __END__ <foo> <bar>
    $input = "foo bar blurf"; ($f,$s) = split /\s+/, $input, 2; print "<$f> <$s>\n" __END__ <foo> <bar quux>

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Problem in printing lastname and firstname
by grep (Monsignor) on Nov 18, 2006 at 14:51 UTC
    I really don't want to be a layout enforcer. Since no one has brought it up, please Clean your room before posting.

    You can use whitespace and indenting to convey helpful information. We want to help - make it easy on us.

    #!/usr/bin/perl use strict; use warnings; my $input = ''; my %nme = (); my $fn = ''; my $ln = ''; while() { print "enter the name\n"; chomp($input=<STDIN>); if($input ne '') { ($fn, $ln) = split('',$input); print "$fn, $ln\n"; $nme{$ln} = $fn; } else { last; } foreach my $lastname(sort keys %nme) { print "$lastname, $nme{$lastname}\n"; }
    This is much easier to read and, we see right there you're missing a final curly. I'm sure that's a copy-n-paste error, but wouldn't it be nice if you showed syntactically correct code to people who are helping you (at the very least it keeps us away from a red herring).

    Always use strict; and use warnings;. Even if it would not have helped you here, you need to get into the habit. You took the time to preset your vars, there is no reason not to have strict and warnings on.

    UPDATE: fixed link - Thanks Albannach and added strict and warnings for demonstration - Thanks Grandfather

    grep
    XP matters not. Look at me. Judge me by my XP, do you?

      In the same vein I'd advise the OP to constrain the scope of his variables to make it easier to see where they are used and to avoid the bogus initialisations.

      Always initialising variables seems like a good idea, but is only appropriate where the variable is being given a default value. If it is intended that the initial value will always be replaced, it is much better not to provide a bogus intial value. Perl's use warnings; "undef used" warning gives an immediate heads up that there is a path or condition in your code that you hadn't anticipated is you leave variables uninitialised until you have a sensible value for them.

      Reworking the code again with that in mind and after fixing various issues that arise during testing you might end up with:

      #!/usr/bin/perl use strict; use warnings; my @nme; # Input loop while ((print "Enter the name: "), defined (my $input = <STDIN>)) { chomp $input; last if ! length $input; # Exit loop on empty line my ($fn, $ln) = split /\s+/, $input, 2; if (! defined $fn) { print "Blank name ignored\n"; next; } $ln ||= '_missing_'; # Provide missing name print "$fn, $ln\n"; push @nme, "$ln, $fn"; } # Print loop print "$_\n" foreach sort @nme;

      Note too the use of the comma operator in teh while loop expression to get the prompt output each time through the loop. Not a highly recommended technique, but can be less ugly and more cogent than many of the alternative ways of achieving the same effect.

      Note too that the hash changed into an array. It's quite possible for two people to have the same last name. In fact it is even possible for people to have the same name. Names are tricky. ;)


      DWIM is Perl's answer to Gödel
        Note too the use of the comma operator in the while loop expression to get the prompt output each time through the loop.Not a highly recommended technique, but can be less ugly and more cogent than many of the alternative ways of achieving the same effect.

        On *nix I usually set up my prompt outside the while loop along with another string of returns and spaces to erase the prompt once I drop out of the loop. Like this

        my $prompt = q{Enter name (<Ctrl-D> to exit) : }; my $dePrompt = qq{\r} . q{ } x (length($prompt) + 2) . qq{\r}; while (1) { print $prompt; last if eof STDIN; chomp(my $response = <STDIN>); # Do something with $response here ... } print $dePrompt;

        This has the advantage of cleaning up the last prompt displayed before returning to a shell prompt or some further output from the script. It does not work so well under MS Windows as it seems you have to do <Ctrl-Z><Enter> to signal EOF and that throws a line before you can erase the prompt. Thus, you may as well dispense with the $dePrompt part of it there.

        I am not sure why you do defined (my $input = <STDIN>). Will it not always be defined, even with just hitting <Enter> as $input will always contain at least a newline? Perhaps I'm missing something but I would have thought you'd only have to worry about definedness after the chomp.

        Cheers,

        JohnGG

Re: Problem in printing lastname and firstname
by swampyankee (Parson) on Nov 18, 2006 at 19:47 UTC

    More code critique! (You should fee special)

    1) your check to see if $input has data is flawed; if the user enters a long string of whitespace, e.g., holds down the spacebar, your test will fail and you'll try to process $input = ' ' x 1_000. Better to use a regex.

    2)Your code will not properly handle a case where somebody enters "Harry S Truman".

    There have been several similar threads before; check Super Search. Also, take a look at the rather relevant discussion at Changing from full name to last, first mid.

    emc

    At that time [1909] the chief engineer was almost always the chief test pilot as well. That had the fortunate result of eliminating poor engineering early in aviation.

    —Igor Sikorsky, reported in AOPA Pilot magazine February 2003.
Re: Problem in printing lastname and firstname
by perladdict (Chaplain) on Nov 18, 2006 at 13:49 UTC
    In declaration of $input variable as well as in split function u r not using a space between the quotes,split function is spliting the input by char.so,give the space between quotes in two places,it works.
Re: Problem in printing lastname and firstname
by joaocoutinho (Novice) on Nov 18, 2006 at 23:30 UTC
    How about doing something like the code below to discard anything the user types between the first and the last names?

    #!/usr/bin/perl chomp(my $full_name = <STDIN>); my @names_list = split(/ /, $full_name); my $name_elements = scalar(@names_list); print "$names_list[$#names_list], $names_list[0]\n";
Re: Problem in printing lastname and firstname
by smokemachine (Hermit) on Nov 21, 2006 at 11:45 UTC
    perl -e 'chomp($name=<>); $,=", ";print ((split/ /,$name)[-1,0])'