Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

General Purpose String Padding

by thedoe (Monk)
on Feb 01, 2006 at 20:37 UTC ( #527163=perlquestion: print w/replies, xml ) Need Help??
thedoe has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to create an all purpose string padding function. This function takes a string and the max length, then optionally the padding direction and pad character.

After looking around Q&A, Tutorials, and using the Super Search, I still haven't found any nodes addressing this.

My first thought was to use sprintf. The problem with this is that, as far as my research has shown, there is no way to specify the pad character with sprintf for strings (besides 0 instead of the default space). This of course solves most of my cases, but not entirely as generic as I would like.

My next solution is to simply append the desired characters to the string in the desired place, such as (basic idea, not a polished sub):

# this assumes that $s will never be longer than $max_length sub my_pad { my ($s, $max_length, $dir, $pad_char) = @_; $pad_char ||= ' '; $dir ||= 'L'; my $pad_string = $pad_char x ($max_length - length $s); return $s . $pad_string if $dir eq 'R'; return $pad_string . $s; }

My question is, does anyone know a more simple way of doing this? It feels like there is something very basic I'm missing, but I can't put my finger on it. Thanks in advance!

Replies are listed 'Best First'.
Re: General Purpose String Padding
by ikegami (Pope) on Feb 01, 2006 at 21:12 UTC

    Your function won't ever work if the pad character is a zero. Replace
    $pad_char ||= ' ';
    $pad_char = ' ' if not defined $pad_char;
    to fix the problem.

    Also, you could make your code a bit cleaner by replacing the last three lines with the following two:

    my $pad = $pad_char x ($max_length - length $s); return $dir eq 'R' ? "$s$pad" : "$pad$s";

    Finally, you documented one of your assumptions ($s will never be longer than $max_length), but you didn't document your assumption that $pad_char will never be longer than one character.

Re: General Purpose String Padding
by saintmike (Vicar) on Feb 01, 2006 at 20:48 UTC

      In particular look for the section "Field filling".

      DWIM is Perl's answer to Gödel

      Perl6::Form does not seem to be a solution to a simpler form of this.

      I would still need to create the template by using something like:

      my $template = $dir eq 'R' ? '<' x $max_length : '>' x $max_length;
      Also, I do not see anything about padding with a specific character. It seems Perl6::Form only pads with spaces.
      See this portion now, thanks Grandfather.

      Still quite a nice module though, I will have to remember it for general formatting in the future.

        The idea would be to discard $max_length entirely. Whatever is providing the value stored in $max_length would now provide a form/template. Of course, this is not necessarily possible in your case.
Re: General Purpose String Padding
by Fletch (Chancellor) on Feb 01, 2006 at 20:59 UTC

      Or Text::Format
      Or not.

      We're building the house of the future together.
Re: General Purpose String Padding
by diotalevi (Canon) on Feb 01, 2006 at 21:47 UTC

    I'd write that more concisely but essentially the same way. defined($pad_char) is preferred because the pad string might '0'.

    sub my_pad { my ($s, $max_length, $dir, $pad_char) = @_; my $pad_string = (defined $pad_char ? $pad_char : ' ' ) x ($max_leng +th - length $s); return $dir eq 'R' ? $s . $pad_string : $pad_string . $s; }

    In perl 5.10, it's shorter because of the new err operator. That's an import from perl 6.

      my $pad_string = ( $pad_char err ' ' ) x ( $max_length - length $s );

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: General Purpose String Padding
by holli (Monsignor) on Feb 01, 2006 at 21:55 UTC
    use strict; use warnings; for ( ["test", "l", 10, "*"], ["test", "r", 10, "*"], ["test", "l", 4, "*"], ["test", "r", 4, "*"], ["test", "l", 2, "*"], ["test", "r", 2, "*"], ["test", "l", 10], ["test", "r", 10], ["test", "l", 4], ["test", "r", 4], ["test", "l", 2], ["test", "r", 2], ) { my $padded = pad (@{$_}); print "=$padded=\n"; } sub pad { my $string = shift || die "no string"; my $direction = shift || die "no direction"; my $length = shift || die "no lenght"; my $char = shift || " "; my $pad_length = $length - length($string); return $string if $pad_length <= 0; my $pad_string = $char x $pad_length; if ( $direction =~ /^l/i ) { return $pad_string.$string; } elsif ( $direction =~ /^r/i ) { return $string.$pad_string; } else { die "unknown direction"; } }

    holli, /regexed monk/

      Just wanted to give you credit the pad sub. Works like it should. Easy to implement. Thanks.

Re: General Purpose String Padding
by superfrink (Curate) on Feb 01, 2006 at 23:20 UTC
    Have you looked at the format keyword yet? It is in the perlform man page.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://527163]
Approved by GrandFather
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (4)
As of 2018-05-27 20:24 GMT
Find Nodes?
    Voting Booth?