Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/245.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
标记字符串的标准算法,保留分隔符(在PHP中)_Php_Algorithm_Parsing - Fatal编程技术网

标记字符串的标准算法,保留分隔符(在PHP中)

标记字符串的标准算法,保留分隔符(在PHP中),php,algorithm,parsing,Php,Algorithm,Parsing,我想将一个算术表达式拆分为标记,将其转换为RPN Java有StringTokenizer,它可以选择保留分隔符。这样,我就可以使用操作符作为分隔符。不幸的是,我需要在PHP中完成这项工作,它有strtok,但这会丢弃分隔符,所以我需要自己编写一些东西 这听起来像是编译器设计101的经典教科书示例,但恐怕我在这里缺乏一些正规的教育。有没有一个标准的算法你可以告诉我 我的另一个选择是使用可用的字符串函数快速阅读或滚动内容。这可能会有所帮助 通常,我会使用正则表达式来实现这一点: $expr = '

我想将一个算术表达式拆分为标记,将其转换为RPN

Java有StringTokenizer,它可以选择保留分隔符。这样,我就可以使用操作符作为分隔符。不幸的是,我需要在PHP中完成这项工作,它有strtok,但这会丢弃分隔符,所以我需要自己编写一些东西

这听起来像是编译器设计101的经典教科书示例,但恐怕我在这里缺乏一些正规的教育。有没有一个标准的算法你可以告诉我

我的另一个选择是使用可用的字符串函数快速阅读或滚动内容。

这可能会有所帮助


通常,我会使用正则表达式来实现这一点:

$expr = '(5*(7 + 2 * -9.3) - 8 )/ 11';
$tokens = preg_split('/([*\/^+-]+)\s*|([\d.]+)\s*/', $expr, -1,
        PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
$tts = print_r($tokens, true);
echo "<pre>x=$tts</pre>";
$expr='(5*(7+2*-9.3)-8)/11';
$tokens=preg\u split('/([*\/^+-]+)\s*\;([\d.]+)\s*/',$expr,-1,
PREG_SPLIT_DELIM_CAPTURE(PREG_SPLIT_NO_EMPTY);
$tts=print\u r($tokens,true);
回音“x=$tts”;

接受带指数的数字(如-9.2e-8)需要做更多的工作。

好的,多亏了PhiLho,如果有人需要,我的最终代码是这个。它甚至都不脏。:-)

静态函数rgTokenize($s)
{
$rg=array();
//删除空白
$s=预替换(“/\s+/”,“$s”);
//在数字、标识符、函数名和运算符处拆分
$rg=preg\u split('/([*\/^+\(\)-]))(preg\u split([\d.]+)(\w+)/”,$s,-1,preg\u split\u DELIM\u CAPTURE(preg\u split\u NO\u EMPTY);
//找到正确的关联“-”,并将其作为符号放在下面的数字上
对于($ix=0,$ixMax=count($rg);$ix<$ixMax;$ix++){
如果('-'=$rg[$ix]){
if(isset($rg[$ix-1])&&self::f操作数($rg[$ix-1])){
继续;
}else if(isset($rg[$ix+1])&&self::f操作数($rg[$ix+1])){
$rg[$ix+1]=$rg[$ix]。$rg[$ix+1];
未结算($rg[$ix]);
}否则{
抛出新异常(“语法错误:找到正确的关联'-'而没有操作数”);
}
}
}
$rg=数组_值($rg);
回显联接(“,$rg)。“\n”;
返回$rg;
}

嘿,谢谢!我忽略了PREG_SPLIT_DELIM_CAPTURE,现在它很简单。标记器很好,但它的某些方面妨碍了我:a)你必须将字符串包装到“”中;b)如果你没有使用与PHP相同的格式,你必须重新格式化标记数组并反/重新编码标记类型。
static function rgTokenize($s)
{
    $rg = array();

    // remove whitespace
    $s = preg_replace("/\s+/", '', $s);

    // split at numbers, identifiers, function names and operators
    $rg = preg_split('/([*\/^+\(\)-])|(#\d+)|([\d.]+)|(\w+)/', $s, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);

    // find right-associative '-' and put it as a sign onto the following number
    for ($ix = 0, $ixMax = count($rg); $ix < $ixMax; $ix++) {
        if ('-' == $rg[$ix]) {
            if (isset($rg[$ix - 1]) && self::fIsOperand($rg[$ix - 1])) {
                continue;
            } else if (isset($rg[$ix + 1]) && self::fIsOperand($rg[$ix + 1])) {
                $rg[$ix + 1] = $rg[$ix].$rg[$ix + 1];
                unset($rg[$ix]);
            } else {
                throw new Exception("Syntax error: Found right-associative '-' without operand");
            }
        }
    }
    $rg = array_values($rg);

    echo join(" ", $rg)."\n";

    return $rg;
}