[LA.pm] String handling like C array
Benjamin J. Tilly
ben_tilly at operamail.com
Mon Feb 6 23:20:48 PST 2006
Use the right tool for the job.
unpack is not the right tool for your swap. Regular expressions are. Here is your swap in native Perl:
$string =~ s/(x|y)/$1 eq "x" ? "y" : "x"/eg;
This is not just less code than you had in C, the idea is also far more flexible. For instance suppose we want to swap Bill and Charles:
$string =~ s/(Bill|Charles)/$1 eq "Bill" ? "Charles" : "Bill"/eg;
Try writing that in C! (Be sure and be careful to take care of buffer overflows!)
Or suppose that we want to swap x and y only when they are not part of a word:
$string =~ s/\b(x|y)\b/$1 eq "x" ? "y" : "x"/eg;
And the technique can be generalized to handle more complex sets of translations. Here is the generalization with the original example:
my %trans = (
"x" => "y",
"y" => "x",
);
my $pat = join "|", map quotemeta($_), keys %trans;
$string =~ s/($pat)/$trans{$1}/g;
Now the translation to do has been extracted and placed in a hash. Which means that your code stays the same while the translation gets more complex. For instance you could do something like this:
my %trans = (
"x" => "y",
"y" => "z",
"z" => "x",
);
my $pat = join "|", map quotemeta($_), keys %trans;
$string =~ s/($pat)/$trans{$1}/g;
or you could load the translation from a file somewhere, etc.
The long and short of it is that while you can pretend that Perl is as bad as C for manipulating text, it is a *lot* better when you learn to use Perl as it was designed to be used.
Cheers,
Ben
PS If pack/unpack is wrong for this job, what is it good for? The answer is producing or parsing fixed width data structures.
> ----- Original Message -----
> From: "Robin Rowe" <rower at movieeditor.com>
> To: Losangeles-pm at pm.org
> Subject: Re: [LA.pm] String handling like C array
> Date: Sat, 04 Feb 2006 01:15:23 -0800
>
>
> Jeff,
>
> Interesting. I've never used unpack. Can you show me what that could
> look like if used in the idiom of my SwapXY example?
>
> Robin
>
> Jeff wrote:
> > The "array level" needs better definition.
> >
> > Depends on what you want exactly, in general, I guess unpack()
> > also traverse the string nicely.
> >
> > Not sure if this answers your question.
> >
> > - J
> > On Feb 3, 2006, at 2:31 PM, Robin Rowe wrote:
> >
> >> I often walk through strings as arrays in C, an idiom something like
> >> this contrived example:
> >>
> >> void SwapXY(char* string)
> >> { char* ptr=string;
> >> while(*ptr)
> >> { const char c=*ptr;
> >> if('x'==c)
> >> { *ptr='y';
> >> }
> >> else if('y'==c)
> >> { *ptr='x';
> >> }
> >> ptr++;
> >> }
> >> }
> >>
> >> In Perl would I walk the string using substr and length or is there a
> >> better way to do array-level string manipulation?
> >>
> >> Robin
> >> _______________________________________________
> >> Losangeles-pm mailing list
> >> Losangeles-pm at pm.org
> >> http://mail.pm.org/mailman/listinfo/losangeles-pm
> >
> >
> >
> >
> _______________________________________________
> Losangeles-pm mailing list
> Losangeles-pm at pm.org
> http://mail.pm.org/mailman/listinfo/losangeles-pm
>
More information about the Losangeles-pm
mailing list