Jörg Reinholz: Verbesserter Input-Spekulierer

Beitrag lesen

Moin!

An solchen Geschichten gibt es immer was zu meckern und ergo immer was zu verbessern:

<?php

function speculateAboutTheNumber($str, $guess='decimal', $type='dec') {
    ## Arguments:
    # $str :: The input
    # $guess :: 'decimal' (Guess the comma or point separate the decimal part) (100,123 or 100.123 -> 100.123) # default
    # $guess :: 'thousends'  (Guess the comma or point separate thousends) (100,123 or 100.123 -> 100123)
    # $guess :: false  - Guess nothing, return false (100,123 and 100,123 -> false)

    # $type :: 'dec' or decimal - for decimal values (float) [ =default ]
    # $type :: 'int' or integer - for integers

    $type = substr(strtolower($type), 0, 3);
    if ($type == 'flo') $type='dec';
    if ($type != 'dec' && $type != 'int') {
        if (! defined('__FILE__') ) define ('__FILE__', 'cli:');
        error_log(__FILE__ . ' : Aufruf speculateAboutTheNumber("' . $str . '", "' . $guess . '", "' . $type . '") : $type muss dec oder int sein');
        return false;
    }
    if ($guess !==false && $guess != 'decimal' && $guess != 'thousends') {
        if (! defined('__FILE__') )     if ( 1 < substr_count($str, ',') ) $str=str_replace(',', '', $str);
    if ( 1 < substr_count($str, '.') ) $str=str_replace('.', '', $str);define ('__FILE__', 'cli:');
        error_log(__FILE__ . ' : Aufruf speculateAboutTheNumber("' . $str .'", "'. $guess . '", "' . $type . '") : $guess muss false, decimal oder thousends sein');
        return false;
    }

    $str=trim($str);

    # french peoples love to separate tousends by a space, others by a single-quota
    $str=str_replace(array(' ', '\''), '', $str);

    # only the thousend-seps can count > 1
    if ( 1 < substr_count($str, ',') ) $str=str_replace(',', '', $str);
    if ( 1 < substr_count($str, '.') ) $str=str_replace('.', '', $str);


    # a simple integer
    if ( 1 === preg_match('/^-{0,1}\d*$/', $str) ) {
        return intval($str);
    }

    $posPoint = strpos($str, '.');
    $posComma = strpos($str, ',');

    if (false === $posPoint) {
        if (1 == preg_match('/^-{0,1}\d{1,3},\d{3}$/', $str) ) {
            if (false===$guess) {
                error_log(__FILE__ . ' : Aufruf speculateAboutTheNumber("'.$str.'", false, "'.$type.'")  decimal-point or thousender-separator? Nobody knows!');
                return false;
            } elseif ('thousends'===$guess) {
                $str=str_replace(',', '', $str);
            }
        }
    }
    
    if (false === $posComma) {
        if (1 == preg_match('/^-{0,1}\d{1,3}\.\d{3}$/', $str) ) {
            if (false===$guess) {
                error_log(__FILE__ . ' : Aufruf speculateAboutTheNumber("'.$str.'", false, "'.$type.'")  decimal-point or thousender-separator? Nobody knows!');
                return false;
            } elseif ('thousends'===$guess) {
                $str=str_replace('.', '', $str);
            }
        }
    }


    # a simple decimal with a point
    if ( 1 == preg_match('/^-{0,1}\d*\.\d+$/', $str) ) {
        if ($type == 'dec') {
            return floatval($str);
        } else {
            return intval($str);
        }
    }

    # a simple decimal with a comma (german format)
    if ( 1 == preg_match('/^-{0,1}\d*,\d+$/', $str) ) {
        $str = str_replace(',', '.', $str);
        if ($type == 'dec') {
            return floatval($str);
        } else {
            return intval($str);
        }
    }


    if ( $posPoint ) {
        if ($posComma < $posPoint) {
            $str = str_replace(',', '', $str);
        }

    }
    if ( $posComma ) {
        if ($posPoint < $posComma) {
            $str = str_replace('.', '', $str);
            $str = str_replace(',', '.', $str);
        }
    }
    if ($type == 'dec') {
        return floatval($str);
    } else {
        return intval($str);
    }
}


## Tests
#/*

$ar=explode(';', "4.8; 4,8; .8; ,8; 1.004,8; 1,004.8; 1 004.8; 1 004,8; -1 004.8; 101.102.103,104; 101,102,103.104");

foreach ($ar as $str) {
    echo trim($str), "\t", speculateAboutTheNumber($str, false, 'int'), "\t", speculateAboutTheNumber($str, false, 'dec'), "\n";
}

echo "------------------------------------------\n";
$ar=explode(';', "2.004; -2,004; 101.102.103; 101,102,103");
foreach ($ar as $str) {
    echo trim($str), "\t", speculateAboutTheNumber($str, 'decimal', 'dec'), "\t", speculateAboutTheNumber($str, 'thousends', 'dec'), "\t", speculateAboutTheNumber($str, false, 'dec'), "\n";
}

#*/

Jörg Reinholz