Проверка правильности расстановки скобок происходит с помощью стека по простому алгоритму: * Все открывающие скобки - помещаем в стек * При встрече закрывающей скобки - проверяем, образует ли закрывающая скобка пару с последней в стеке. * Если пара образуется - извлекаем последний элемент из стека, продолжаем работу. Если нет - скобки не парны * В финале нужно проверить, что стек пуст. Не пустой стек - свидетельство о непарности скобок. Приведенный алгоритм работает красиво, но не сможет корректно отслеживать парность кавычек, слешей, поскольку в этом случае из-за одинаковых открывающего и закрывающего элементов невозможно корректно определить вложенность. /*/////////////////////////////////////////////////////////////// CheckPara "()", PHP, 2011-01-01 Artix, master@7masterov.ru, icq:53666599, skype:artixmaster * Error in code? Nothing is perfect! * Free source for free Linux, use it for free! * Please, do not remove this comment! ///////////////////////////////////////////////////////////////*/ function check($s) { $para = array( '(' => ')', '[' => ']', '{' => '}', '<' => '>' ); $para = array_flip($para); $stack = array(); $stack_size = 0; for($i=0;$i<strlen($s);$i++) { if (in_array($s{$i},array_values($para))) $stack[$stack_size++] = $s{$i}; else if (in_array($s{$i},array_keys($para))) { $last = $stack_size? $stack[$stack_size-1] : ''; if ($last!=$para[$s{$i}]) return false; else unset($stack[--$stack_size]); } } return count($stack)==0; } $s = "(t<es>t[test{test}]tes{t)"; print check($s)?"TRUE\n":"FALSE\n"; Для того, чтобы заставить этот алгоритм работать с кавычками я использовал такой прием: на первом этапе собрал все скобки и кавычки в строку, а затем из этой строки в цикле удалил валидные пары. Если в результате операии в строке ничего не осталось - пары кавычек и скобок расставлены правильно. /*/////////////////////////////////////////////////////////////// CheckMegaPara "()", PHP, 2011-01-01 Artix, master@7masterov.ru, icq:53666599, skype:artixmaster * Error in code? Nothing is perfect! * Free source for free Linux, use it for free! * Please, do not remove this comment! ///////////////////////////////////////////////////////////////*/ function check($s) { $para = array( '(' => ')', '[' => ']', '{' => '}', '<' => '>', '/' => '/', '|' => '|', '"' => '"' ); $stack=''; for($i=0; $i<strlen($s); $i++) { $test = ( in_array(substr($s,$i,1), array_keys($para)) ) || ( in_array(substr($s,$i,1), $para) ); if ($test) $stack .= $s{$i}; } $len = strlen($stack)/2; for($i=0;$i<$len;$i++) { foreach($para as $k=>$v) $stack = str_replace($k.$v, '', $stack); } return (strlen($stack)==0); } $s = '{z(/x/(ka"z"ak)x)z}'; echo $s,': ',check($s)?"TRUE":"FALSE","\n"; К сожалению этот алгоритм не очень хорош как раз потому, что в нем есть вложенные циклы. Есть более быстрый вариант - в той точке, где встречается кавычка, сделать рекурсивное разветвление, рассматривая в одном случае кавычку, как закрывающий символ, а в другом - как открывающий. Такой алгоритм будет работать быстрее, но написать его сложнее.
Справочник алгоритмов v0.05 © 2007-2025 Igor Salnikov aka SunDoctor