Support negative values - php

I'm in a situation where the CSV file is getting rid of the leading zero before my import and I need to be able to account for that. Let's say that I have my value as the following:
-.0982739 -> I would want all case scenarios where it's -. to turn into -0. - Here are my attempts:
if (str_contains($this->longitude, '-.')) {
$this->longitude = '0' . $this->longitude;
};
Outputs: 00-.0989070
if ($this->longitude[0] == '.') {
$this->longitude = '0' . $this->longitude;
}
Outputs: -.0989070
To simplify things, basically any . that has nothing before it, add in a 0, otherwise use the value given.
I will need it for both longitude and latitude.

/^([-+])?\./
The above regex matches the signs - and + if they are present and immediately followed by a .. Now, capture the matched group 1 in the regex which is ([-+])? and append 0. followed by all digits after . by taking substr of the current string.
<?php
$a = ".0982739";
if(preg_match('/^([-+])?\./',$a, $matches) === 1){
$prefix = $matches[1] ?? '';
$a = $prefix . '0.' . substr($a,$prefix == '' ? 1 : 2);
}
echo $a;

Try this :
<?php
$x = -.54321 ;
echo $x . "\r\n" ;
$x = "-.12345" ;
echo $x . "\r\n" ;
echo floatval($x) . "\r\n" ;
echo sprintf("%0.5f", $x) ;
?>
I assume your CSV is returning only string values, because as soon as I echo a "native" float, the echo is just fine.
As soon as your float is correctly formatted, you can catch it in a string value if needed.

You could use str_replace:
$this->longitude = ltrim($this->longitude, '+');// remove leading +
if ($this->longitude[0]=='.' || substr($this->longitude, 0, 2)=='-.')) {
$this->longitude = str_replace('.', '0.', $this->longitude);
}
The if condition matches any string that begins with '.' or '-.' And if so, str_replace replaces the . with 0.

`$var = 0.0989070;
$neg = -$var; // easiest
$neg = -1 * $var; // bit more explicit
$neg = 0 - $var; // another version`

You could check for numbers before dot....
<?php
if (str_contains($this->longitude, '.')) {
$beforedot = strstr($this->longitude,'.',true); //Get anything before
if (is_numeric($beforedot)) { echo "do nothing"; } //check if is number do nothing
else {
$this->longitude = str_replace('.', '0.', $this->longitude); //else do replace . with 0.
}
};
?>

I created a class and assigned -.0982739 to a property called $longitude. In the constructor I did echo $this->longitude and it came out as -0.0982739 which I believe is exactly as you want it to be. I couldn't manage to reproduce it.
<?php
class Test
{
private $longitude = -.0982739;
public function __construct()
{
}
public function test()
{
echo $this->longitude;
}
}
<?php
include "Test.php";
$test = new Test();
$test->test();

Related

How to convert string operation into a number?

I have a string '1/2' and i need to get a float value 0.5 from it.
Other examples:
Operation: $operation = '5/8';
Wanted value: $value = 0.625;
You can use eval, also please note your are not looking for an int as they are whole numbers.
<?php
$operation = '1/2';
eval('$value = ' . $operation . ';');
echo $value;
?>
This will work if you only have one "/".
$str = '2/5';
$newStr = explode('/', $str);
echo $newStr[0]/$newStr[1];
Edited.
Not elegant because eval is used, but working.
$operation = '1/2';
function stringCalc($operation){
return eval('return '.$operation.';');
}
$value = stringCalc($operation);

Substract a part of a string considering some delimiters in php

I have a variable in php witch can have this shape:
$a = 'help&type=client';
$b = 'account#client';
$c = 'info&type=client#new';
I need to create a substract function that will work like this:
echo myFunction($a); //&type=client
echo myFunction($b); //#client
echo myFunction($c); //&type=client#new
I will rate the more simplified answere.
I think that the simplest way would be using strpbrk.
$a = 'help&type=client';
$b = 'account#client';
$c = 'info&type=client#new';
echo strpbrk($a, '&#') . PHP_EOL; //&type=client
echo strpbrk($b, '&#') . PHP_EOL; //#client
echo strpbrk($c, '&#') . PHP_EOL; //&type=client#new
myFunction would be something like this:
function myFunction($string) {
$amp = strpos($string, '&');
if($amp) {
return substr($string,$amp,strlen($string)-$amp);
} else {
$hash= strpos($string, '#');
return substr($string,$hash,strlen($string)-$hash);
}
}
You might have to change if($amp) to if($amp > 0) depending on what the output of strpos is.
What about this.
$re = "/[&#]([a-z=]+)/";
$str = "help&type=client\naccount#client";
preg_match_all($re, $str, $matches);
http://regex101.com/r/cW3yL6/1
You can use regular expressions for this
preg_match('[^help](.*)', $help, $match)
echo $match[0]; //&type=client
and
preg_match('[^account](.*)', $help, $match)
echo $match[0]; //#client
You can see this website: http://regex101.com/r/zR9eD1/1 for more information about these expressions.
Just a quick explanation:
we do NOT match 'help' and we DO match everything else (after 'help')
edit:
If you only have & or # as a delimiter you can use this:
preg_match('([#].+)', $help, $match)
echo $match[0]; //#client
This matches everything starting with a #
Use a simple preg_split:
function myFunction($var) {
return $var . "\n";
}
$a = 'help&type=client';
$b = 'account#client';
$as = preg_split('/(\w+)/', $a, 2);
$bs = preg_split('/(\w+)/', $b, 2);
echo myFunction($as[1]); // &type=client
echo myFunction($bs[1]); // #client

Php simple algorithm for autoloader

Here's my "simple" algorithm:
if the class is named like 'AaaBbbCccDddEeeFff' loop like this:
include/aaa/bbb/ccc/ddd/eee/fff.php
include/aaa/bbb/ccc/ddd/eee_fff.php
include/aaa/bbb/ccc/ddd_eee_fff.php
include/aaa/bbb/ccc_ddd_eee_fff.php
include/aaa/bbb_ccc_ddd_eee_fff.php
include/aaa_bbb_ccc_ddd_eee_fff.php
if still nothing found, try to look if those files exist:
include/aaa/bbb/ccc/ddd/eee/fff/base.php
include/aaa/bbb/ccc/ddd/eee/base.php
include/aaa/bbb/ccc/ddd/base.php
include/aaa/bbb/ccc/base.php
include/aaa/bbb/base.php
include/aaa/base.php
include/base.php
If still not found then error.
I'm looking for a fast and easy way to convert this:
'AaaBbbCccDddEeeFff'
to this:
include/aaa/bbb/ccc/ddd/eee/fff.php
and then and easy way to remove latest folder (I guess I should look for explode()).
Any idea how to do this? (I'm not asking for the whole code, I'm not lazy).
Since you specifically asked not to have the whole code, here is some code to get you started. This takes the input and divides it into chunks delineated by changes in case. The rest you can work out as an exercise.
<?php
$input = "AaaBbbCccDddEeeFff";
$str_so_far = "";
$last_was_upper = 0;
$chunks = array();
while($next_letter = substr($input,0,1)) {
$is_upper = (strtoupper($next_letter)==$next_letter);
if($str_so_far && $is_upper && !$last_was_upper) {
$chunks[] = $str_so_far;
$str_so_far = "";
}
if($str_so_far && !$is_upper && $last_was_upper) {
$chunks[] = $str_so_far;
$str_so_far = "";
}
$str_so_far .= $next_letter;
$input = substr($input,1);
$last_was_upper = $is_upper;
}
var_dump($chunks);
?>
I think a regular expression would work. Something like preg_match_all('[A-Z][a-z][a-z]'
, $string); might work - that would match a capital letter, followed by a lowercase letter, and another lowercase letter.
As the other answers are regex, here's a non-regex way for completeness:
function transform($str){
$arr = array();
$part = '';
for($i=0; $i<strlen($str); $i++){
$char = substr($str, $i, 1);
if(ctype_upper($char) && $i > 0){
$arr[] = $part;
$part = '';
}
$part .= $char;
}
$arr[] = $part;
return 'include/' . strtolower(implode('/', $arr)) . '.php';
}
echo transform('AaaBbbCccDddEeeFff');
// include/aaa/bbb/ccc/ddd/eee/fff.php
This builds an array of the folders, so you can manipulate it as needed, for example remove a folder by unsetting the desired index, before it gets imploded.
Here is the first part of your algorithm:
AaaBbbCccDddEeeFff -> include/aaa/bbb/ccc/ddd/eee/fff.php
include/aaa/bbb/ccc/ddd/eee_fff.php
include/aaa/bbb/ccc/ddd_eee_fff.php
include/aaa/bbb/ccc_ddd_eee_fff.php
include/aaa/bbb_ccc_ddd_eee_fff.php
include/aaa_bbb_ccc_ddd_eee_fff.php
I think you can do last part independently based on my answer.
<?php
function convertClassToPath($class) {
return strtolower(preg_replace('/([a-z])([A-Z])/', '$1' . DIRECTORY_SEPARATOR . '$2', $class)) . '.php';
}
function autoload($path) {
$base_dir = 'include' . DIRECTORY_SEPARATOR;
$real_path = $base_dir . $path;
var_dump('Checking: ' . $real_path);
if (file_exists($real_path) === true) {
var_dump('Status: Success');
include $real_path;
} else {
var_dump('Status: Fail');
$last_separator_pos = strrpos($path, DIRECTORY_SEPARATOR);
if ($last_separator_pos === false) {
return;
} else {
$path = substr_replace($path, '_', $last_separator_pos, 1);
autoload($path);
}
}
}
$class = 'AaaBbbCccDddEeeFff';
var_dump(autoload(convertClassToPath($class)));

Sorting strings, in a function, is my logic faulty or?

i need to sort some strings and match them with links, this is what i do:
$name_link = $dom->find('div[class=link] strong');
Returns array [0]-[5] containing strings such as NowDownload.eu
$code_link = $dom->find('div[class=link] code');
Returns links that match the names from 0-5, as in link [0] belongs to name [0]
I do not know the order in which they are returned, NowDownload.Eu, could be $code_link[4] or $code_link [3], but the name array will match it in order.
Now, i need $code_link[4] // lets say its NowDownload.Eu to become $link1 every time
so i do this
$i = 0;
while (!empty($code_link[$i]))
SortLinks($name_link, $code_link, $i); // pass all links and names to function, and counter
$i++;
}
function SortLinks($name_link, $code_link, &$i) { // counter is passed by reference since it has to increase after the function
$string = $name_link[$i]->plaintext; // name_link is saved as string
$string = serialize($string); // They are returned in a odd format, not searcheble unless i serialize
if (strpos($string, 'NowDownload.eu')) { // if string contains NowDownload.eu
$link1 = $code_link[$i]->plaintext;
$link1 = html_entity_decode($link1);
return $link1; // return link1
}
elseif (strpos($string, 'Fileswap')) {
$link2 = $code_link[$i]->plaintext;
$link2 = html_entity_decode($link2);
return $link2;
}
elseif (strpos($string, 'Mirrorcreator')) {
$link3 = $code_link[$i]->plaintext;
$link3 = html_entity_decode($link3);
return $link3;
}
elseif (strpos($string, 'Uploaded')) {
$link4 = $code_link[$i]->plaintext;
$link4 = html_entity_decode($link4);
return $link4;
}
elseif (strpos($string, 'Ziddu')) {
$link5 = $code_link[$i]->plaintext;
$link5 = html_entity_decode($link5);
return $link5;
}
elseif (strpos($string, 'ZippyShare')) {
$link6 = $code_link[$i]->plaintext;
$link6 = html_entity_decode($link6);
return $link6;
}
}
echo $link1 . '<br>';
echo $link2 . '<br>';
echo $link3 . '<br>';
echo $link4 . '<br>';
echo $link5 . '<br>';
echo $link6 . '<br>';
die();
I know they it finds the link, i have tested it before, but i wanted to make it a function, and it messed up, is my logic faulty or is there an issue with the way i pass the variables/ararys ?
I don't know why you pass $i as reference since you use it just for reading it. You could return an array contaning the named links and using it like so :
$all_links = SortLinks($name_link,$code_link);
echo $all_links['link1'].'<br/>';
echo $all_links['link2'].'<br/>';
You will have to put your loop inside the function, not outside.

Problem with numbers and nonexistence

So I have a script that includes forms that are stored in files named like 0101, 0102, and the next category would be 0201, 0202, 0203. The first two set of numbers are the category, second set are the pages in for the forms.
The problem I am having with this numbering is that I am storing the number as 0101 or 0205 and since the first number is only a non-existent thing, 0, it seems to be knocking it off. The only way I managed to actually make it work in some messy way was to do something like this:
"planpages/0" . $nextcat . ".php"
Where $nextcat might be 203. It doesn't seem to like the 0 in front of anything, and must be stored in a string which has something before it (in the case above, you have a "/" sign).
How do I solve the problem with data loss? I did try looking it up in other places, but I didn't know what to put in for the query.
EDIT: More code.
The number is originally stored in $_GET['content'], passed to nextForm($current).
function nextForm($current) {
$next = $current[0] . $current[1] . $current[2] . $current[3] + 1;
$nextcat = $current[0] . $current[1] + 1 . 0 . 1;
if(file_exists("planpages/0" . $next . ".php")) {
return "0" . $next;
} elseif(file_exists("planpages/0" . $nextcat . ".php")) {
return "0" . $nextcat;
} else {
return $current;
}
}
Hopefully that is more information needed. It looks like a mess because I tried my hardest to keep those zeros, but they keep disappearing.
You can zero-pad with sprintf:
$form = 1;
$page = 2;
$string = sprintf('%02d%02d', $form, $page);
This will give you:
$string = '0102';
Or if you have:
$value = 102;
Then:
$string = sprintf('%04d', $value);
Maybe you should use str_pad to zero-pad category and page.
$category = 2;
$pages = 1;
$cat = str_pad($category, 2, "0", STR_PAD_LEFT);
$pag = str_pad($pages, 2, "0", STR_PAD_LEFT);
$filename = $cat . $pag;
// $filename = "0201"

Categories