Showing posts with label PHP - Strings. Show all posts
Showing posts with label PHP - Strings. Show all posts
Saturday, November 24, 2012
PHP : Strings - [1.2] Accessing Substrings
PHP : Strings - [1.3] Replacing Substrings
1.3.1 Problem
You want to replace a substring with a different string. For example, you want to obscure all but the last four digits of a credit card number before printing it.
1.3.2 Solution
// Everything from position $start to the end of $old_string
// becomes $new_substring
$new_string = substr_replace($old_string,$new_substring,$start);
// $length characters, starting at position $start, become $new_substring
$new_string = substr_replace($old_string,$new_substring,$start,$length);
1.3.3 Discussion
Without the $length argument, substr_replace( ) replaces everything from $start to the end of the string. If $length is specified, only that many characters are replaced:
print substr_replace('My pet is a blue dog.','fish.',12);
print substr_replace('My pet is a blue dog.','green',12,4);
$credit_card = '4111 1111 1111 1111';
print substr_replace($credit_card,'xxxx ',0,strlen($credit_card)-4);
My pet is a fish.
My pet is a green dog.
xxxx 1111
If $start is negative, the new substring is placed at $start characters counting from the end of $old_string, not from the beginning:
print substr_replace('My pet is a blue dog.','fish.',-9);
print substr_replace('My pet is a blue dog.','green',-9,4);
My pet is a fish.
My pet is a green dog.
If $start and $length are 0, the new substring is inserted at the start of $old_string:
print substr_replace('My pet is a blue dog.','Title: ',0,0);
Title: My pet is a blue dog.
The function substr_replace( ) is useful when you've got text that's too big to display all at once, and you want to display some of the text with a link to the rest. For example, this displays the first 25 characters of a message with an ellipsis after it as a link to a page that displays more text:
$r = mysql_query("SELECT id,message FROM messages WHERE id = $id") or die( );
$ob = mysql_fetch_object($r);
printf('<a href="more-text.php?id=%d">%s</a>',
$ob->id, substr_replace($ob->message,' ...',25));
The more-text.php page can use the message ID passed in the query string to retrieve the full message and display it.
PHP : Strings - [1.4] Processing a String One Character at a Time
1.4.1 Problem
1.4.2 Solution
Loop through each character in the string with for.
This example counts the vowels in a string:
$string = "This weekend, I'm going shopping for a pet chicken.";
$vowels = 0;
for ($i = 0, $j = strlen($string); $i < $j; $i++) {
if (strstr('aeiouAEIOU',$string[$i])) {
$vowels++;
}
}
1.4.3 Discussion
function lookandsay($s) {
// initialize the return value to the empty string
$r = '';
// $m holds the character we're counting, initialize to the first
* character in the string
$m = $s[0];
// $n is the number of $m's we've seen, initialize to 1
$n = 1;
for ($i = 1, $j = strlen($s); $i < $j; $i++) {
// if this character is the same as the last one
if ($s[$i] == $m) {
// increment the count of this character
$n++;
} else {
// otherwise, add the count and character to the return value //
$r .= $n.$m;
// set the character we're looking for to the current one //
$m = $s[$i];
// and reset the count to 1 //
$n = 1;
}
}
// return the built up string as well as the last count and character //
return $r.$n.$m;
}
for ($i = 0, $s = 1; $i < 10; $i++) {
$s = lookandsay($s);
print "$s\n";
}
1
11
21
1211
111221
312211
13112221
1113213211
31131211131221
13211311123113112211
It's called the "Look and Say" sequence because each element is
what you get by looking at the previous element and saying what's in it. For
example, looking at the first element, 1, you say "one one." So the second
element is "11." That's two ones, so the third element is "21." Similarly,
that's one two and one one, so the fourth element is "1211," and so on.
PHP : Strings - [1.5] Reversing a String by Word or Character
1.5.1 Problem
1.5.2 Solution
print strrev('This is not a palindrome.');
.emordnilap a ton si sihT
To reverse by words, explode the string by word boundary,
reverse the words, then rejoin:
$s = "Once upon a time there was a turtle.";
// break the string up into words
$words = explode(' ',$s);
// reverse the array of words
$words = array_reverse($words);
// rebuild the string
$s = join(' ',$words);
print $s;
turtle. a was there time a upon Once
1.5.3 Discussion
Reversing a string by words can also be done all in one
line:
$reversed_s = join(' ',array_reverse(explode(' ',$s)));
PHP : Strings - [1.6] Expanding and Compressing Tabs
1.6.1 Problem
You want to change spaces to tabs (or tabs to spaces) in a string while keeping
text aligned with tab stops. For example, you want to display formatted text to
users in a standardized way.
1.6.2 Solution
$r = mysql_query("SELECT message FROM messages WHERE id = 1") or die();
$ob = mysql_fetch_object($r);
$tabbed = str_replace(' ',"\t",$ob->message);
$spaced = str_replace("\t",' ',$ob->message);
print "With Tabs: <pre>$tabbed</pre>";
print "With Spaces: <pre>$spaced</pre>";
Using str_replace( ) for conversion, however, doesn't
respect tab stops. If you want tab stops every eight characters, a line
beginning with a five-letter word and a tab should have that tab replaced with
three spaces, not one. Use the pc_tab_expand( ) function shown in Example 1-1 to turn tabs to spaces
in a way that respects tab stops.
Example 1-1. pc_tab_expand( )
function pc_tab_expand($a) {
$tab_stop = 8;
while (strstr($a,"\t")) {
$a = preg_replace('/^([^\t]*)(\t+)/e',
"'\\1'.str_repeat(' ',strlen('\\2') *
$tab_stop - strlen('\\1') % $tab_stop)",$a);
}
return $a;
}
$spaced = pc_tab_expand($ob->message);
PHP : Strings - [1.7] Controlling Case
1.7.1 Problem
You need to
capitalize, lowercase, or otherwise modify the case of letters in a string. For
example, you want to capitalize the initial letters of names but lowercase the
rest.
1.7.2 Solution
print ucfirst("how do you do today?");
print ucwords("the prince of wales");
How do you do today?
The Prince Of Wales
print strtoupper("i'm not yelling!");
// Tags must be lowercase to be XHTML compliant
print strtolower('<A HREF="one.php">one</A>');
I'M NOT YELLING!
<a href="one.php">one</a>
1.7.3 Discussion
Use ucfirst( ) to capitalize the first character in a
string:
print ucfirst('monkey face');
print ucfirst('1 monkey face');
Monkey face
1 monkey face
Note that the second line of output is not "1 Monkey face".
print ucwords('1 monkey face');
print ucwords("don't play zone defense against the philadelphia 76-ers");
1 Monkey Face
Don't Play Zone Defense Against The Philadelphia 76-ers
As expected, ucwords( ) doesn't capitalize the "t" in
"don't." But it also doesn't capitalize the "e" in "76-ers." For ucwords(
), a word is any sequence of nonwhitespace characters that follows one or
more whitespace characters. Since both ' and - aren't
whitespace characters, ucwords( ) doesn't consider the "t" in "don't"
or the "e" in "76-ers" to be word-starting characters.
Both ucfirst( ) and ucwords( ) don't change
the case of nonfirst letters:
print ucfirst('macWorld says I should get a iBook');
print ucwords('eTunaFish.com might buy itunaFish.Com!');
MacWorld says I should get a iBook
ETunaFish.com Might Buy ItunaFish.Com!
The functions strtolower( ) and strtoupper( ) work on entire strings, not just
individual characters. All alphabetic characters are changed to lowercase by
strtolower( ) and strtoupper( ) changes all alphabetic
characters to uppercase:
print strtolower("I programmed the WOPR and the TRS-80.");
print strtoupper('"since feeling is first" is a poem by e. e. cummings.');
i programmed the wopr and the trs-80.
"SINCE FEELING IS FIRST" IS A POEM BY E. E. CUMMINGS.
When determining upper- and lowercase, these functions respect
your locale settings.
PHP : Strings - [1.8] Interpolating Functions and Expressions Within Strings
1.8.1 Problem
1.8.2 Solution
Use the string concatenation operator (.) when
the value you want to include can't be inside the string:
print 'You have '.($_REQUEST['boys'] + $_REQUEST['girls']).' children.';
print "The word '$word' is ".strlen($word).' characters long.';
print 'You owe '.$amounts['payment'].' immediately';
print "My circle's diameter is ".$circle->getDiameter().' inches.';
1.8.3 Discussion
You can put variables, object properties, and array elements (if the
subscript is unquoted) directly in double-quoted strings:
print "I have $children children.";
print "You owe $amounts[payment] immediately.";
print "My circle's diameter is $circle->diameter inches.";
Direct interpolation or using string
concatenation also works with heredocs. Interpolating with
string concatenation in heredocs can look a little strange because the heredoc
delimiter and the string concatenation operator have to be on separate lines:
print <<< END
Right now, the time is
END
. strftime('%c') . <<< END
but tomorrow it will be
END
. strftime('%c',time() + 86400);
Also, if you're interpolating with heredocs, make sure to
include appropriate spacing for the whole string to appear properly. In the
previous example, "Right now the time" has to include a trailing space, and "but
tomorrow it will be" has to include leading and trailing spaces.
PHP : Strings - [1.9] Trimming Blanks from a String
1.9.1 Problem
You want to remove
whitespace from the beginning or end of a string. For example, you want to clean
up user input before validating it.
1.9.2 Solution
Use ltrim( ) , rtrim( ), or trim(
). ltrim( ) removes whitespace from the beginning of a string,
rtrim( ) from the end of a string, and trim( ) from both the
beginning and end of a string:
$zipcode = trim($_REQUEST['zipcode']);
$no_linefeed = rtrim($_REQUEST['text']);
$name = ltrim($_REQUEST['name']);
1.9.3 Discussion
For these functions, whitespace is defined as the following
characters: newline, carriage return, space, horizontal and vertical tab,
and null.
Trimming whitespace off of strings saves storage space and can
make for more precise display of formatted data or text within
<pre> tags, for example. If you are doing comparisons with user
input, you should trim the data first, so that someone who mistakenly enters
"98052 " as their Zip Code isn't forced to fix an error that really isn't.
Trimming before exact text comparisons also ensures that, for example,
"salami\n" equals "salami." It's also a good idea to normalize string data by
trimming it before storing it in a database.
The trim( ) functions can also remove user-specified
characters from strings. Pass the characters you want to remove as a second
argument. You can indicate a range of characters with two dots between the first
and last characters in the range.
// Remove numerals and space from the beginning of the line
print ltrim('10 PRINT A$',' 0..9');
// Remove semicolon from the end of the line
print rtrim('SELECT * FROM turtles;',';');
PRINT A$
SELECT * FROM turtles
PHP : Strings - [1.10] Parsing Comma-Separated Data
1.10.1 Problem
You have data in comma-separated values ( CSV) format, for example a file
exported from Excel or a database, and you want to extract the records and
fields into a format you can manipulate in PHP.
1.10.2 Solution
If the CSV data is in a file (or available via a URL), open the
file with fopen( ) and read
in the data with fgetcsv( ). This prints out the data in an HTML table:
$fp = fopen('sample2.csv','r') or die("can't open file");
print "<table>\n";
while($csv_line = fgetcsv($fp,1024)) {
print '<tr>';
for ($i = 0, $j = count($csv_line); $i < $j; $i++) {
print '<td>'.$csv_line[$i].'</td>';
}
print "</tr>\n";
}
print '</table>\n';
fclose($fp) or die("can't close file");
1.10.3 Discussion
The second argument to fgetcsv( ) must be longer than
the maximum length of a line in your CSV file. (Don't forget to count the
end-of-line whitespace.) If you read in CSV lines longer than 1K, change the
1024 used in this recipe to something that accommodates your line length.
You can pass fgetcsv( ) an optional third argument, a
delimiter to use instead of a comma (,). Using a different delimiter however,
somewhat defeats the purpose of CSV as an easy way to exchange tabular data.
PHP : Strings - [1.11] Parsing Fixed-Width Delimited Data
1.11.1 Problem
1.11.2 Solution
$fp = fopen('fixed-width-records.txt','r') or die ("can't open file");
while ($s = fgets($fp,1024)) {
$fields[1] = substr($s,0,10); // first field: first 10 characters of the line
$fields[2] = substr($s,10,5); // second field: next 5 characters of the line
$fields[3] = substr($s,15,12); // third field: next 12 characters of the line
// a function to do something with the fields
process_fields($fields);
}
fclose($fp) or die("can't close file");
$fp = fopen('fixed-width-records.txt','r') or die ("can't open file");
while ($s = fgets($fp,1024)) {
// an associative array with keys "title", "author", and "publication_year"
$fields = unpack('A25title/A14author/A4publication_year',$s);
// a function to do something with the fields
process_fields($fields);
}
fclose($fp) or die("can't close file");
1.11.3 Discussion
Data in which each field is allotted a fixed number of
characters per line may look like this list of books, titles, and publication
dates:
$booklist=<<<END
Elmer Gantry Sinclair Lewis1927
The Scarlatti InheritanceRobert Ludlum 1971
The Parsifal Mosaic Robert Ludlum 1982
Sophie's Choice William Styron1979
END;
In each line, the title occupies the first 25 characters, the
author's name the next 14 characters, and the publication year the next 4
characters. Knowing those field widths, it's straightforward to use substr(
) to parse the fields into an array:
$books = explode("\n",$booklist);
for($i = 0, $j = count($books); $i < $j; $i++) {
$book_array[$i]['title'] = substr($books[$i],0,25);
$book_array[$i]['author'] = substr($books[$i],25,14);
$book_array[$i]['publication_year'] = substr($books[$i],39,4);
}
Exploding $booklist into an array of lines makes the
looping code the same whether it's operating over a string or a series of lines
read in from a file.
PHP : Strings - [1.12] Taking Strings Apart
1.12.1 Problem
You need to break a string into
pieces. For example, you want to access each line that a user enters in a
<textarea> form field.
1.12.2 Solution
$words = explode(' ','My sentence is not very complicated');
Use split( ) or preg_split( ) if you need a POSIX or Perl regular
expression to describe the separator:
$words = split(' +','This sentence has some extra whitespace in it.');
$words = preg_split('/\d\. /','my day: 1. get up 2. get dressed 3. eat toast');
$lines = preg_split('/[\n\r]+/',$_REQUEST['textarea']);
$words = spliti(' x ','31 inches x 22 inches X 9 inches');
$words = preg_split('/ x /i','31 inches x 22 inches X 9 inches');
1.12.3 Discussion
The simplest solution of the bunch is explode( ). Pass
it your separator string, the string to be separated, and an optional limit on
how many elements should be returned:
$dwarves = 'dopey,sleepy,happy,grumpy,sneezy,bashful,doc';
$dwarf_array = explode(',',$dwarves);
Now $dwarf_array is a seven element array:
print_r($dwarf_array);
Array
(
[0] => dopey
[1] => sleepy
[2] => happy
[3] => grumpy
[4] => sneezy
[5] => bashful
[6] => doc
)
If the specified limit is less than the number of possible
chunks, the last chunk contains the remainder:
$dwarf_array = explode(',',$dwarves,5);
print_r($dwarf_array);
Array
(
[0] => dopey
[1] => sleepy
[2] => happy
[3] => grumpy
[4] => sneezy,bashful,doc
)
PHP : Strings - [1.13] Wrapping Text at a Certain Line Length
1.13.1 Problem
You need to wrap
lines in a string. For example, you want to display text in
<pre>/</pre> tags but have it stay within a
regularly sized browser window.
1.13.2 Solution
$s = "Four score and seven years ago our fathers brought forth on this continen
t a new nation, conceived in liberty and dedicated to the proposition that all
men are created equal.";
print "<pre>\n".wordwrap($s)."\n</pre>";
<pre>
Four score and seven years ago our fathers brought forth on this continent
a new nation, conceived in liberty and dedicated to the proposition that
all men are created equal.
</pre>
1.13.3 Discussion
By default, wordwrap( ) wraps text at 75 characters
per line. An optional second argument specifies different line length:
print wordwrap($s,50);
Four score and seven years ago our fathers brought
forth on this continent a new nation, conceived in
liberty and dedicated to the proposition that all
men are created equal.
print wordwrap($s,50,"\n\n");
Four score and seven years ago our fathers brought
forth on this continent a new nation, conceived in
liberty and dedicated to the proposition that all
men are created equal.
There is an optional fourth argument to wordwrap( )
that controls the treatment of words that are longer than the specified line
length. If this argument is 1, these words are wrapped. Otherwise, they span
past the specified line length:
print wordwrap('jabberwocky',5);
print wordwrap('jabberwocky',5,"\n",1);
jabberwocky
jabbe
rwock
y
PHP : Strings - [1.14] Storing Binary Data in Strings
1.14.1 Problem
You want to parse a string
that contains values encoded as a binary structure or encode values into a
string. For example, you want to store numbers in their binary representation
instead of as sequences of ASCII characters.
1.14.2 Solution
$packed = pack('S4',1974,106,28225,32725);
$nums = unpack('S4',$packed);
1.14.3 Discussion
The first argument to pack( ) is a format string that describes how
to encode the data that's passed in the rest of the arguments. The format string
S4 tells pack( ) to produce four unsigned short 16-bit numbers
in machine byte order from its input data. Given 1974, 106, 28225, and 32725 as
input, this returns eight bytes: 182, 7, 106, 0, 65, 110, 213, and 127. Each
two-byte pair corresponds to one of the input numbers: 7 * 256 + 182 is 1974; 0
* 256 + 106 is 106; 110 * 256 + 65 = 28225; 127 * 256 + 213 = 32725.
The first argument to unpack( )
is also a format string, and the second argument is the data to decode. Passing
a format string of S4, the eight-byte sequence that pack( )
produced returns a four-element array of the original numbers:
print_r($nums);
Array
(
[1] => 1974
[2] => 106
[3] => 28225
[4] => 32725
)
In unpack( ), format characters and their count can be
followed by a string to be used as an array key. For example:
$nums = unpack('S4num',$packed);
print_r($nums);
Array
(
[num1] => 1974
[num2] => 106
[num3] => 28225
[num4] => 32725
)
Subscribe to:
Posts (Atom)