str_replace wrong decimal - php

this is my first question here at Stackoverflow so please bear with me :)
What I have been trying to do for the last couple of hours is replacing symbols on upload and download from the database.
How it should be:
Input: 100.000,25
Stored in database: 100000.25
Output: 100.200,25
The reason hereof is that i need the comma as decimal separator, and dot as thousand separators. I need to still be able to add/multiply and more with the numbers stored in the database.
What works the best of what I have tried so far:
// Value from form input:
$value = 100.200,25;
// Removing all but numbers and comma
$remove_symbols = array("+"," ",".","-","'","\"","&","!","?",":",";","#","~","=","/","$","£","^","(",")","_","<",">");
$db_value = str_replace($remove_symbols, '', $value);
// $db_value  insert into db
// Pulling out the data
$db_pulled = number_format($row['liter'],2,',','.');
echo $db_pulled;
:( returns: 100.200,00 (should return 100.200,25)

Your questions are a bit confusing and you don't tag them well. For example a php tag would be more appropriate and sufficient. (I've modified it for you now)
OK. The problem you are having is because you need to replace comma with a dot because that's how float values are represented. In your example it probably gets truncated when you insert it in the DB.
here is what you can do:
<?php
$numString = "100.200,25";
$numString = str_replace(array('.', ','), array('','.'), $numString);
$num = floatval($numString);
echo $num;
?>

Seeing that your code returns: 100.200,00 (should return 100.200,25)
Your databases table field seems to be in Int format instead of Decimal format.
For more information about Numeric field types visit http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html

Related

Trying to count non English characters gives wrong results

So on my webpage I have an input form (with 'accept-charset="UTF-8"') for the user to enter text, which will get posted to a php page. In the php page, the input should be separated by spaces, then stored in an array, with a key value which equals the total count of letters in that word. There is no worry about words with the same length.
Example:
User inputs "def ghijk a bc"
$stringArr[1][0] = "a"
$stringArr[2][0] = "bc"
$stringArr[3][0] = "def"
$stringArr[5][0] = "ghijk"
I have this working all fine when it comes to English letters, but if I try to input letters from other languages, the key value is always wrong. Take this letter from Hindi for example: "मैं", it gives it a key value of 21 instead of just 1. What is the workaround to this?
$string = "मैं मैंमैं";
$stringLenArr = preg_split('/\s+/', $string);
$stringArr = array();
foreach($stringLenArr as $value) {
// What I used before:
// $stringArr[strlen($value)][] = $value;
// Attempted solution which still only works with English
$stringArr[mb_strlen($value, "UTF-8")][] = $value;
}
Just to make things clearer: There should only ever be a single language entered, so if the solution requires a language selection box on the input page, that is no issue.

User inputted string, when containing certain special characters, does not match database string though they appear to be equivalent strings

I have searched for similar questions and have found this
but it has not helped for my situation. On my site, a user inputs an answer. The string is sent via an ajax call to a php file. The string may or may not contain special characters, so I use
encodeURIComponent()
before the string is sent to the php file.
The user-inputted string is compared in the php file with a string that represents the "correct answer", and if the strings are found to be equivalent strings after processing, the user-inputted answer is "correct". I have not had a problem with any strings lately until today. Until today, strings with letters, special characters (parentheses, minus sign, plus sign) and numbers have worked fine using the following processing in php:
<?php include 'connect.php';
$UserInput = trim($_GET['userinput']);
$QID = mysqli_real_escape_string($cxn, $_GET['qid']);
$sqlIQ = mysqli_fetch_assoc(mysqli_query($cxn, "SELECT answer FROM IndexQuestions WHERE sampqid = $QID"));
$StrReplaceArray = array("<i>", "</i>", "</sup>", " ");
$CorrectAnswer1 = str_replace($StrReplaceArray, "", $sqlIQ['answer']);
$CorrectAnswer2 = str_replace("<sup>", "^", $CorrectAnswer1);
$UserAnswer1 = str_replace(" ", "", $UserInput);
$UserAnswer2 = str_replace("+-", "-", $UserAnswer1);
if (strcasecmp($UserAnswer2, $CorrectAnswer2) == 0) {
$CorrectOrNot = 'Correct';
} else {
$CorrectOrNot = 'Incorrect';
}
However, the latest string is not working. The user-inputted string is -2 ± √3 which is sent to the php file as -2 ± √3 (with or without the whitespace). The "correct answer" saved in another table is -2 ± √3. I have echoed the following:
echo $UserAnswer2 . " " . $CorrectAnswer2; //after str_replace processing shown above
and the html output for each variable looks identical to me. I have also tried the following for comparative purposes (instead of strcasecmp):
if ($UserAnswer2 == htmlentities($CorrectAnswer2)) { //etc.
but still the same.
When I check a separate table (which stores the user's answer), the answer is stored the way I want it to be:
$unixtime = time();
$AnswerID = substr(md5(rand(0, 1000000)), 0, 10).$unixtime;
$sqlIQStats = mysqli_query($cxn, "INSERT INTO IQStats (answer_id, useranswer) VALUES ('$AnswerID', '".htmlentities($UserAnswer2)."')");
and appears in the database as -2 ± √3.
The html charset the site uses is charset=utf-8.
var_dump gives the following (with no spaces for user answer): $UserInput and $UserAnswer2 both give string(8) "-2±√3" whereas $CorrectAnswer2 gives string(18) "-2±√3"
Does anyone have any ideas as to why the strings, after string-processing and comparison in the php file, are found to be inequivalent strings?
OK...solved it by changing $UserInput to:
$UserInput = htmlentities(trim($_GET['userinput']));

Pulling a number and prefix from filename using PHP

I am currently using the following function to grab the product code number for a filename such as "62017 THOR.jpg"
$number = (int) $value;
Leaving me with 62017
The trouble is some of these files have prefixes which need to be left in place ie "WST 62017.jpg"
So im after
WST 62017
not
62017
Could someone help me, either redo what im using or alter ?
replace all characters except the numbers from the image name and get only numbers.
$number = preg_replace("~[^0-9]~", "", $value);
If you want to capture everything before the number and the number as well, you can use:
$value = "WST 62017.jpg";
$number = preg_replace('/^(.*?\d*)\..*/',"$1",trim($value));
// $number is "WST 62017"
See it
You could do it like this:
$value = preg_replace('/^(.*\d+).*$/', '\1', $filename);
It should replace everything after the first numeric value with nothing, leaving everything in front of it in place. Note that you wont't be able to cast the number to int, then.

getting only certain data from table

I have a field that is in this format
5551112391^HUMAN^HUMAN-800-800^6-main^^
How would I only grab the numbers 5551112391 before the character ^?
Would you do this with regex?
You can make use of explode:
$var = '5551112391^HUMAN^HUMAN-800-800^6-main^^';
$arr = explode('^',$var);
$num = $arr[0];
Using regex:
$var = '5551112391^HUMAN^HUMAN-800-800^6-main^^';
if(preg_match('/^(\d+)/',trim($var),$m)){
$num = $m[1];
}
Regex overkill, nice...
What about simple cast to int? Will work perfectly OK if the number is in the beginning of data. And definitely faster than regexps...
$var = '5551112391^HUMAN^HUMAN-800-800^6-main^^';
$num = (int)$var;
http://www.php.net/manual/en/language.types.type-juggling.php
You're doing it in completely wrong way.
You treat mysql database as a flat text file. But it is not.
All these fields must be separated and stored in separate columns.
To get only certain data from the table, you should not select all rows and then compare one by one but make database do it for you:
SELECT * FROM table WHERE number=5551112391

Using regex to fix phone numbers in a CSV with PHP

My new phone does not recognize a phone number unless its area code matches the incoming call. Since I live in Idaho where an area code is not needed for in-state calls, many of my contacts were saved without an area code. Since I have thousands of contacts stored in my phone, it would not be practical to manually update them. I decided to write the following PHP script to handle the problem. It seems to work well, except that I'm finding duplicate area codes at the beginning of random contacts.
<?php
//the script can take a while to complete
set_time_limit(200);
function validate_area_code($number) {
//digits are taken one by one out of $number, and insert in to $numString
$numString = "";
for ($i = 0; $i < strlen($number); $i++) {
$curr = substr($number,$i,1);
//only copy from $number to $numString when the character is numeric
if (is_numeric($curr)) {
$numString = $numString . $curr;
}
}
//add area code "208" to the beginning of any phone number of length 7
if (strlen($numString) == 7) {
return "208" . $numString;
//remove country code (none of the contacts are outside the U.S.)
} else if (strlen($numString) == 11) {
return preg_replace("/^1/","",$numString);
} else {
return $numString;
}
}
//matches any phone number in the csv
$pattern = "/((1? ?\(?[2-9]\d\d\)? *)? ?\d\d\d-?\d\d\d\d)/";
$csv = file_get_contents("contacts2.CSV");
preg_match_all($pattern,$csv,$matches);
foreach ($matches[0] as $key1 => $value) {
/*create a pattern that matches the specific phone number by adding slashes before possible special characters*/
$pattern = preg_replace("/\(|\)|\-/","\\\\$0",$value);
//create the replacement phone number
$replacement = validate_area_code($value);
//add delimeters
$pattern = "/" . $pattern . "/";
$csv = preg_replace($pattern,$replacement,$csv);
}
echo $csv;
?>
Is there a better approach to modifying the CSV? Also, is there a way to minimize the number of passes over the CSV? In the script above, preg_replace is called thousands of times on a very large String.
If I understand you correctly, you just need to prepend the area code to any 7-digit phone number anywhere in this file, right? I have no idea what kind of system you're on, but if you have some decent tools, here are a couple options. And of course, the approaches they take can presumably be implemented in PHP; that's just not one of my languages.
So, how about a sed one-liner? Just look for 7-digit phone numbers, bounded by either beginning of line or comma on the left, and comma or end of line on the right.
sed -r 's/(^|,)([0-9]{3}-[0-9]{4})(,|$)/\1208-\2\3/g' contacts.csv
Or if you want to only apply it to certain fields, perl (or awk) would be easier. Suppose it's the second field:
perl -F, -ane '$"=","; $F[1]=~s/^[0-9]{3}-[0-9]{4}$/208-$&/; print "#F";' contacts.csv
The -F, indicates the field separator, the $" is the output field separator (yes, it gets assigned once per loop, oh well), the arrays are zero-indexed so second field is $F[1], there's a run-of-the-mill substitution, and you print the results.
Ah programs... sometimes a 10-min hack is better.
If it were me... I'd import the CSV into Excel, sort it by something - maybe the length of the phone number or something. Make a new col for the fixed phone number. When you have a group of similarly-fouled numbers, make a formula to fix. Same for the next group. Should be pretty quick, no? Then export to .csv again, omitting the bad col.
A little more digging on my own revealed the issues with the regex in my question. The problem is with duplicate contacts in the csv.
Example:
(208) 555-5555, 555-5555
After the first pass becomes:
2085555555, 208555555
and After the second pass becomes
2082085555555, 2082085555555
I worked around this by changing the replacement regex to:
//add escapes for special characters
$pattern = preg_replace("/\(|\)|\-|\./","\\\\$0",$value);
//add delimiters, and optional area code
$pattern = "/(\(?[0-9]{3}\)?)? ?" . $pattern . "/";

Categories