記事で分かる人教えてくださいってお願いしておいたら本当に教えてくださる方が!感謝です!
.@wada811 camel_caseの一番のコーナーケースは_aXYZ0_であるようです。これは_a_x_y_z0_と相互変換できる必要があります。直してみましたが汚いので、正規表現だと綺麗には掛けないのかもしれませんtenka1-2012-qualb.contest.atcoder.jp/submissions/43… #atcoder
— t.yamadaさん (@cielavenir) 9月 8, 2012
回答
AtCoder/tenka1_2012_B_2_preg_replace.php at master · wada811/AtCoder<?php $variable = trim(fgets(STDIN)); if(isCamelCase($variable)){ $variable = toSnakeCase($variable); }else if(isSnakeCase($variable)){ $variable = toCamelCase($variable); } echo $variable.PHP_EOL; function isCamelCase($str){ return preg_match('/^_*[a-z][a-z0-9]*([A-Z][a-z0-9]*)*_*$/', $str, $matches); } function toCamelCase($str){ preg_match('/^(_*).*$/', $str, $matches); $str = substr($str, strlen($matches[1])); return $matches[1].preg_replace('/_([a-z])/e', 'strtoupper("$1")', $str); } function isSnakeCase($str){ return preg_match('/^_*[a-z][a-z0-9]*(_[a-z][a-z0-9]*)*_*$/', $str, $matches); } function toSnakeCase($str){ return preg_replace('/([A-Z])/e', '"_".strtolower("$1")', $str); } ?>AtCoder/tenka1_2012_B_2_preg_replace_callback.php at master · wada811/AtCoder
<?php $variable = trim(fgets(STDIN)); if(isCamelCase($variable)){ $variable = toSnakeCase($variable); }else if(isSnakeCase($variable)){ $variable = toCamelCase($variable); } echo $variable.PHP_EOL; function isCamelCase($str){ return preg_match('/^_*[a-z][a-z0-9]*([A-Z][a-z0-9]*)*_*$/', $str, $matches); } function toCamelCase($str){ preg_match('/^(_*).*$/', $str, $matches); $str = substr($str, strlen($matches[1])); return $matches[1].preg_replace_callback( '/_([a-z])/', create_function('$matches', 'return strtoupper($matches[1]);'), $str); } function isSnakeCase($str){ return preg_match('/^_*[a-z][a-z0-9]*(_[a-z][a-z0-9]*)*_*$/', $str, $matches); } function toSnakeCase($str){ return preg_replace_callback( '/([A-Z])/', create_function('$matches', 'return "_".strtolower($matches[1]);'), $str); } ?>無事に両方通りました。原因としては単語が一文字でもOKだったということ。
ただ、一文字だけの単語を許容しても置換で preg_replace と preg_replace_callback は
_aXYZ0_ を見た際に aX の後は xY ではなく、 YZ を見に行ってしまうので
マッチ方法を変えなければいけませんでした。
判定でガチガチにキャメルケースとスネークケースを判別しているので変換では少し緩めにしました。
キャメルケース → スネークケース の場合は、大文字がマッチした時点で単語の先頭だということになります。
スネークケース → キャメルケース の場合は、先頭に付加されるアンダースコアが判定に影響するので
function toCamelCase($str){ preg_match('/^(_*).*$/', $str, $matches); $str = substr($str, strlen($matches[1])); return $matches[1].preg_replace_callback( '/_([a-z])/', create_function('$matches', 'return strtoupper($matches[1]);'), $str); }先頭のアンダースコアをマッチさせて除去した後に置換をかけて、
プレフィックスとしてアンダースコアを付加することにしました。
おかげさまで解くことができました。@cielavenirさん、本当にありがとうございました!