...

View Full Version : String Handling (strstr'ing)



samuurai
11-20-2007, 03:36 PM
Hi Guys,

I've got a whole bunch of text in an array, called $lines, for example. Each array element represents a line.

I use foreach($lines as $line), I then use strstr($line, "TEXTTOSEARCH")

It all works absolutely fine, except when "TEXTTOSEARCH" appears twice in the array.

How can I make it so that instead of the second occurence overwriting the previous occurences stuff, it just gets appended?

I don't know how to seperate them out. Perhaps some way of counting the array elements would be good, because identical text only ever occurs in sequential lines. ie if($lines[arraycounter + 1] == "TEXTTOSEARCH") somehow append.

Forgive me, i'm still learning concepts, being very new to programming.

aedrin
11-20-2007, 04:00 PM
I think you're going to have to give some more detail on this one.

What is your intent of using strstr()? Are you just trying to do a search and replace?

What do you mean by:


How can I make it so that instead of the second occurence overwriting the previous occurences stuff, it just gets appended?

Perhaps post what you have currently.

samuurai
11-20-2007, 04:20 PM
Perhaps post what you have currently.

Ok!

Here's what I have so far...


<?php

$dir = "/var/www/blues/";

$dtitle = 'DTITLE=';
$dgenre = 'DGENRE=';
$dyear = 'DYEAR=';
$ttitle = 'TTITLE';


$tstring = "Track frame offsets:";

$record = FALSE;
//$duration = array();

function trimAndCase($input)
{
$input = trim($input);
$input = ucwords(strtolower($input));
return $input;
}
$dir = opendir($dir);
while (($file = readdir($dir)) !== false)
{
if(!is_dir($file))
{
$lines = file("/var/www/blues/".$file); //the readdir function changes the variable to "Resource Handle 3, so I had to specify the path manually again.
foreach($lines as $line)
{
trim($line);
if(strstr($line, $dtitle))
{
$line = substr($line, strlen($dtitle));
$line = trim($line);
// if line ends with a /, remove the /.
if(substr($line, -1) == "/")
{
echo "ends with a slash ";
$line = substr($line, 0, -1);
$line = trim($line);
}
// if the string contains a clash, use this to explode it.
if(strstr($line, "/"))
{
$elements = explode("/", $line);
//$artist is the first element before the /
$artist = trimAndCase($elements[0]);
if(count($elements) > 2)
{
$release = trimAndCase($elements[1] . "/" . $elements[2]);
echo "More than two \"/\" " . $release ;
}
else
{
$release = trimAndCase($elements[1]);
}

}
else {
echo "Only one DTITLE element";
$artist = $line;
$release = $line;
}
if(($artist == "V/A") || ($artist == "Various Artists")) {
$artist = "Various";
}
}

}
echo '<a href="' . "/blues/" . $file . '">' . $file . '</a> ' . "Artist: " . $artist . " Release: " . $release . "<br>";
}
}

closedir($dir);
?>


You can see the results at http://87.74.42.101/test.php

Thanks for your help.

aedrin
11-20-2007, 04:39 PM
Now you just have to indicate which specific parts are troubling you. ;) Or what exactly you're trying to accomplish.

I can see you're parsing a directory to produce a playlist. But the playlist looks fine to me.

samuurai
11-20-2007, 04:44 PM
Apologies... i'll be more specific in future.. :)

Ok,

go to http://87.74.42.101/test.php and search for 2212b614


Clicking on it will show the file has two DTITLE entries, which is the cause of the problem.

Thanks...

P.S. I edited it just now with correct details.

aedrin
11-20-2007, 05:24 PM
Without looking at your code, the following comes to mind:



function startsWith($subject, $startsWith) {
return substr($subject, 0, strlen($startsWith)) == $startsWith;
}

$titleKeyword = 'DTITLE';
$artist = '';

foreach ($lines as $line) {
if (startsWith($line, $titleKeyword)) {
$artist .= substr($line, strlen($titleKeyword));
}
// check for other information
}

echo 'Artist = ' . $artist;

samuurai
11-20-2007, 05:33 PM
Wow, I didn't expect the actual code.. your approach is genius.

I can use this approach to make the rest of my script neater now that I know it... thanks very much!

Beren

aedrin
11-20-2007, 05:45 PM
No problem.

Sometimes it is easier to take a different road after hitting a roadblock.

samuurai
11-20-2007, 05:49 PM
Nice metaphor :p

marek_mar
11-20-2007, 11:24 PM
Without looking at your code, the following comes to mind:



function startsWith($subject, $startsWith) {
return substr($subject, 0, strlen($startsWith)) == $startsWith;
}

$titleKeyword = 'DTITLE';
$artist = '';

foreach ($lines as $line) {
if (startsWith($line, $titleKeyword)) {
$artist .= substr($line, strlen($titleKeyword));
}
// check for other information
}

echo 'Artist = ' . $artist;

You can simplify this:


$titleKeyword = 'DTITLE';
$artist = '';

foreach ($lines as $line) {
if (strpos($line, $titleKeyword) === 0) {
$artist .= substr($line, strlen($titleKeyword));
}
// check for other information
}

echo 'Artist = ' . $artist;

aedrin
11-20-2007, 11:31 PM
Not sure if it's really simplified.

Using a function makes it easier to read, and reusable. Not to mention that comparing 2 short strings is in most cases more efficient/faster than searching through the entire string.

samuurai
11-21-2007, 12:40 PM
return substr($subject, 0, strlen($startsWith)) == $startsWith;


I'm having trouble understanding this line...

I understand that you're removing the part of the line that contains $startsWith by counting the characters in it and lopping it off the start, but I don't get the == $startsWith; at the end. - Is that a shorthand way of making a calculation, then setting it to a variable and returning it, all in one line?

samuurai
11-21-2007, 12:42 PM
You can simplify this:

Thanks a lot.. it's good to know more than one way of doing it. - I was about to say "both ways", but I'm gathering with programming that there are usually hundreds of ways of achieving the same thing. :)

aedrin
11-21-2007, 02:42 PM
I'm having trouble understanding this line...

I understand that you're removing the part of the line that contains $startsWith by counting the characters in it and lopping it off the start, but I don't get the == $startsWith; at the end. - Is that a shorthand way of making a calculation, then setting it to a variable and returning it, all in one line?

Actually, it does something different.

Substr() returns a subset of a string, determined by a start and an (optional) length. So I'm taking the first X characters (X is the length of the keyword), and compare it to the actual keyword.

You are correct about the latter part though. Everything after the return is considered an expression which is simplified (evaluated) until it is no longer possible to further simplify. In this case, that happens to be a simple boolean (true or false) which is the result of the comparison.

samuurai
11-22-2007, 05:04 PM
I'm struggling with some of the terms, "expression" and "simplify", but I'm fairly sure I've got the meaning.

Regardless, i've got my script working well using the concepts from your example. Thanks again!

Ahri
11-23-2007, 03:57 PM
$title_keyword = 'DTITLE';
$artist = '';

foreach($lines as $line) if(preg_match('#^'.$title_keyword.'(.+)$', $line, $m)) $artist .= $m[1];

Readability? Pah.

Incidentally those 'DTITLE' etc. string literals would be better off as define()s -- you don't need them as variables if they aren't going to vary....



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum