php how replace characters before and after special characters - php

I have a php string like:
$string = '1234532323%A73823823221A%221312373712';
the string has numbers and 2 special tags (%A and A%) to indicate the begin and the end of the special part, respectively.
My goal is to replace all "1" with "2", but not in the part of the string between %A and A%.
If I use strtr(string,"1","2") all 1 occurrences will be replaced.
Does anyone know how my goal can be achieved?
Special characters may appear several times inside the string.

well you can use this algorithm
note: it's not written in any programmation language
int test = 0;
for(int i=0;i<ch.length();i++){
if(test!=1 && ch(i)!="%"){
if(ch(i)==1)
ch(i)=2;
}else
{
test++;
}
}
Sorry for the bad presentation..

You can do that by breaking them apart and replacing the strings. do look into preg_* to better solve all cases.
$a = "1234532323%A73823823221A%221312373712";
//explode to an array of 3 objects
$b = explode('%',$a);
//replace the numbers in the first and last object
$b[0] = strtr($b[0],"1","2");
$b[2] = strtr($b[2],"1","2") ;
//concatenate them again to get $a
$a = $b[0].$b[1].$b[2];
echo($a);

Related

Increment string from given array of letters or exclude specific letters from incremental with PHP

I have a list of allowed letters
$allowedLetters = array('B','C','D','F','G','H','J','K','L','M','N','P','R','S','T','V','W','X','Y','Z');
And from that array I would like to do string increment to get the following pattern:
BBB, BBC, BBD ... until ZZZ
I know that I can do string increment as simple as this:
$letters = array();
$letter = 'BBB';
while ($letter !== 'ZZZ') {
$letters[] = $letter++;
}
print_r($letters);
But it will not match my allowed letters list, and I just can not find a way how to either do an increment using allowed list or just exclude letters that I do not want such as:
A,E,I,O,Q,U
What could be more simple? I would appreciate if anyone could assist.
I propose a solution starting from your code that involves strcspn() function:
$letters = array();
$letter = 'BBB';
while ($letter !== 'ZZZ') {
$letter++;
if(strcspn($letter, "AEIOU") == 3 )
$letters[] = $letter;
}
print_r($letters);
The mentioned function returns the index of the first occurrence of the characters listed in needle parameter. So, in our case, it will return a value in the range [0-2] if any of the characters is present. According to the manual page, no one of the characters specified in needle list is found, the length of the original string is returned (in our scenario it is always equal to 3).
This means that making sure that it returns 3 we are accepting only strings that don't contain the forbidden characters "AEIOU", appending them to our output array.

preg_replace with a word in an array

I am trying to use certain words in a array called keywords, which will be used to be replaced in a string by "as".
for($i = 0; $i<sizeof($this->keywords[$this->lang]); $i++)
{
$word = $this->keywords[$this->lang][$i];
$a = preg_replace("/\b$word\b/i", "as",$this->code);
}
It works with if I replace the variable $word with something like /\bhello\b/i, which then would replace all hello words with "as".
Is the approach am using even possible?
Before to be a pattern, it's a double quoted string, so variables will be replaced, it's not the problem.
The problem is that you use a loop to change several words and you store the result in $a:
the first iteration, all the occurences of the first word in $this->code are replaced and the new string is stored in $a.
but the next iteration doesn't reuse $a as third parameter to replace the next word, but always the original string $this->code
Result: after the for loop $a contains the original string but with only the occurences of the last word replaced with as.
When you want to replace several words with the same string, a way consists to build an alternation: word1|word2|word3.... It can easily be done with implode:
$alternation = implode('|', $this->keywords[$this->lang]);
$pattern = '~\b(?:' . $alternation . ')\b~i';
$result = preg_replace($pattern, 'as', $this->code);
So, when you do that, the string is parsed only once and all the words are replaced in one shot.
If you have a lot of words and a very long string:
Testing a long alternation has a significant cost. Even if the pattern starts with \b that highly reduces the possible positions for a match, your pattern will have hard time to succeed and more to fail.
Only in this particular case, you can use this another way:
First you define a placeholder (a character or a small string that can't be in your string, lets say §) that will be inserted in each positions of word boundaries.
$temp = preg_replace('~\b~', '§', $this->code);
Then you change all the keywords like this §word1§, §word2§ ... and you build an associative array where all values are the replacement string:
$trans = [];
foreach ($this->keywords[$this->lang] as $word) {
$trans['§' . $word . '§'] = 'as';
}
Once you have do that you add an empty string with the placeholder as key. You can now use the fast strtr function to perform the replacement:
$trans['§'] = '';
$result = strtr($temp, $trans);
The only limitation of this technic is that it is case-sensitive.
it will work if you keep it like bellow:
$a = preg_replace("/\b".$word."\b/i", "as",$this->code);

PHP increment operator

<?php
$s = "pa99";
$s++;
echo $s;
?>
The above code outputs to "pb00"
What i wanted was "pa100" and so on.
But also in case its "pa", I want it to go to "pb" which works well with
increment operator.
You are, as Michael says, trying to increment a string - it Does Not Work That Way (tm). What you want to do is this:
<?php
$s = "pa"; //we're defining the string separately!
$i = 99; //no quotes, this is a number
$i++;
echo $s.$i; //concatenate $i onto $s
?>
There's no automated way to increment a string (aa, ab, etc) the way you're asking. You could turn each letter into a number between 1-26 and increment them, and then increment the previous one on overflow. That's kind of messy, though.
To separate the integer from the string, try this:
PHP split string into integer element and string
From the docs:
PHP follows Perl's convention when dealing with arithmetic operations on character variables and not C's. For example, in PHP and Perl $a = 'Z'; $a++; turns $a into 'AA', while in C a = 'Z'; a++; turns a into '[' (ASCII value of 'Z' is 90, ASCII value of '[' is 91). Note that character variables can be incremented but not decremented and even so only plain ASCII characters (a-z and A-Z) are supported. Incrementing/decrementing other character variables has no effect, the original string is unchanged.
<?php
$s_letter = substr($s,0,2);
$s_number = substr($s,2,9);
$s_letter++; $s_number++;
$s_result = $s_letter.$s_number;
echo $s_result;
?>

How to get part of a string in php

I have strings like:
t_est1_1
test213_4
tes_tsdfsdf_9
The common part of every string is the LAST underscore _ character.
I need to get the string before this character.
t_est1_12 --> test1
test213_4 --> test213
tes_tsdfsdf_9343 --> testsdfsdf
How can i achieve this in PHP?
Using the basic string functions strpos and substr.
http://fr.php.net/manual/fr/function.explode.php
$a = "abcdef_12345"
$b = array();
// $b[0] = "abcdef";
$b[0] = explode('_',$a,'1');
you can use preg_match function available in php
you need to write regular expression for that...
for example
to get this test1_12 ->> test1
$string='test1_12';
preg_match('((.+?)\_(.*))',$string,$match);
echo $match[1];
What you want is a simple explode, array_slice and implode, also using explode and end, you can get the "id" that is the common part too:
$description = implode('', array_slice(explode('_', $data), 0, -1));
$id = end(explode('_', $data));
As many _ you will have, you'll still be able to expode on them and retrieve the last item containing your id and the first items (0 to -1) will contain your description...

How to add currency strings (non-standardized input) together in PHP?

I have a form in which people will be entering dollar values.
Possible inputs:
$999,999,999.99
999,999,999.99
999999999
99,999
$99,999
The user can enter a dollar value however they wish. I want to read the inputs as doubles so I can total them.
I tried just typecasting the strings to doubles but that didn't work. Total just equals 50 when it is output:
$string1 = "$50,000";
$string2 = "$50000";
$string3 = "50,000";
$total = (double)$string1 + (double)$string2 + (double)$string3;
echo $total;
A regex won't convert your string into a number. I would suggest that you use a regex to validate the field (confirm that it fits one of your allowed formats), and then just loop over the string, discarding all non-digit and non-period characters. If you don't care about validation, you could skip the first step. The second step will still strip it down to digits and periods only.
By the way, you cannot safely use floats when calculating currency values. You will lose precision, and very possibly end up with totals that do not exactly match the inputs.
Update: Here are two functions you could use to verify your input and to convert it into a decimal-point representation.
function validateCurrency($string)
{
return preg_match('/^\$?(\d{1,3})(,\d{3})*(.\d{2})?$/', $string) ||
preg_match('/^\$?\d+(.\d{2})?$/', $string);
}
function makeCurrency($string)
{
$newstring = "";
$array = str_split($string);
foreach($array as $char)
{
if (($char >= '0' && $char <= '9') || $char == '.')
{
$newstring .= $char;
}
}
return $newstring;
}
The first function will match the bulk of currency formats you can expect "$99", "99,999.00", etc. It will not match ".00" or "99.", nor will it match most European-style numbers (99.999,00). Use this on your original string to verify that it is a valid currency string.
The second function will just strip out everything except digits and decimal points. Note that by itself it may still return invalid strings (e.g. "", "....", and "abc" come out as "", "....", and ""). Use this to eliminate extraneous commas once the string is validated, or possibly use this by itself if you want to skip validation.
You don't ever want to represent monetary values as floats!
For example, take the following (seemingly straight forward) code:
$x = 1.0;
for ($ii=0; $ii < 10; $ii++) {
$x = $x - .1;
}
var_dump($x);
You might assume that it would produce the value zero, but that is not the case. Since $x is a floating point, it actually ends up being a tiny bit more than zero (1.38777878078E-16), which isn't a big deal in itself, but it means that comparing the value with another value isn't guaranteed to be correct. For example $x == 0 would produce false.
http://p2p.wrox.com/topic.asp?TOPIC_ID=3099
goes through it step by step
[edit] typical...the site seems to be down now... :(
not a one liner, but if you strip out the ','s you can do: (this is pseudocode)
m/^\$?(\d+)(?:\.(\d\d))?$/
$value = $1 + $2/100;
That allows $9.99 but not $9. or $9.9 and fails to complain about missplaced thousands separators (bug or feature?)
There is a potential 'locality' issue here because you are assuming that thousands are done with ',' and cents as '.' but in europe it is opposite (e.g. 1.000,99)
I recommend not to use a float for storing currency values. You can get rounding errors if the sum gets large. (Ok, if it gets very large.)
Better use an integer variable with a large enough range, and store the input in cents, not dollars.
I belive that you can accomplish this with printf, which is similar to the c function of the same name. its parameters can be somewhat esoteric though. you can also use php's number_format function
Assuming that you are getting real money values, you could simply strip characters that are not digits or the decimal point:
(pseudocode)
newnumber = replace(oldnumber, /[^0-9.]/, //)
Now you can convert using something like
double(newnumber)
However, this will not take care of strings such as "5.6.3" and other such non-money strings. Which raises the question, "Do you need to handle badly formatted strings?"

Categories