[PHP]strrev関数を完全解説!文字列を反転する方法

PHP

こんにちは!今回は、PHPの標準関数であるstrrev()について詳しく解説していきます。文字列を逆順にする、シンプルだけど便利な関数です!

strrev関数とは?

strrev()関数は、文字列を反転(逆順に)する関数です。

“string reverse”の略で、文字列の最後の文字が最初に、最初の文字が最後になります。回文のチェックやデータの検証など、意外と使い道がある関数です!

基本的な構文

strrev(string $string): string
  • $string: 反転する文字列
  • 戻り値: 反転された文字列

基本的な使用例

シンプルな反転

// 英数字の反転
$text = "Hello";
echo strrev($text) . "\n";
// 出力: olleH

// 数字の反転
$number = "12345";
echo strrev($number) . "\n";
// 出力: 54321

// 文章の反転
$sentence = "Hello World";
echo strrev($sentence) . "\n";
// 出力: dlroW olleH

空文字列と1文字

// 空文字列
$empty = "";
echo strrev($empty) . "\n";
// 出力: (空)

// 1文字
$single = "A";
echo strrev($single) . "\n";
// 出力: A

マルチバイト文字の扱い

// 日本語(注意が必要)
$japanese = "こんにちは";
echo strrev($japanese) . "\n";
// 出力: は���に���ん���こ���(文字化けする)

// マルチバイト対応の反転が必要な場合
function mb_strrev($str, $encoding = 'UTF-8') {
    $length = mb_strlen($str, $encoding);
    $reversed = '';
    
    for ($i = $length - 1; $i >= 0; $i--) {
        $reversed .= mb_substr($str, $i, 1, $encoding);
    }
    
    return $reversed;
}

echo mb_strrev("こんにちは") . "\n";
// 出力: はちにんこ

実践的な使用例

例1: 回文(パリンドローム)のチェック

class PalindromeChecker {
    /**
     * 回文かどうかチェック
     */
    public static function isPalindrome($text) {
        // 大文字小文字を統一
        $normalized = strtolower($text);
        
        // 空白と記号を除去
        $cleaned = preg_replace('/[^a-z0-9]/', '', $normalized);
        
        // 反転したものと比較
        return $cleaned === strrev($cleaned);
    }
    
    /**
     * 回文かどうかチェック(完全一致)
     */
    public static function isStrictPalindrome($text) {
        return $text === strrev($text);
    }
    
    /**
     * 数値回文のチェック
     */
    public static function isNumericPalindrome($number) {
        $str = (string)$number;
        return $str === strrev($str);
    }
    
    /**
     * 単語単位の回文チェック
     */
    public static function isWordPalindrome($sentence) {
        $words = preg_split('/\s+/', trim($sentence));
        $reversed = array_reverse($words);
        
        return $words === $reversed;
    }
    
    /**
     * マルチバイト対応回文チェック
     */
    public static function isMbPalindrome($text, $encoding = 'UTF-8') {
        $length = mb_strlen($text, $encoding);
        $reversed = '';
        
        for ($i = $length - 1; $i >= 0; $i--) {
            $reversed .= mb_substr($text, $i, 1, $encoding);
        }
        
        return $text === $reversed;
    }
}

// 使用例
echo "=== 回文チェック ===\n";

$words = [
    'racecar',
    'madam',
    'hello',
    'A man a plan a canal Panama',
    'noon',
    'world'
];

foreach ($words as $word) {
    $isPalindrome = PalindromeChecker::isPalindrome($word);
    echo "{$word}: " . ($isPalindrome ? '回文' : '非回文') . "\n";
}

echo "\n=== 数値回文 ===\n";
$numbers = [12321, 12345, 1001, 9009];

foreach ($numbers as $num) {
    $isPalindrome = PalindromeChecker::isNumericPalindrome($num);
    echo "{$num}: " . ($isPalindrome ? '回文' : '非回文') . "\n";
}

echo "\n=== 日本語回文 ===\n";
$japanese = ['しんぶんし', 'たけやぶやけた', 'こんにちは'];

foreach ($japanese as $word) {
    $isPalindrome = PalindromeChecker::isMbPalindrome($word);
    echo "{$word}: " . ($isPalindrome ? '回文' : '非回文') . "\n";
}

例2: 文字列の比較と検証

class StringValidator {
    /**
     * 対称性をチェック
     */
    public static function isSymmetric($text) {
        return $text === strrev($text);
    }
    
    /**
     * 反転してもユニークかチェック
     */
    public static function isUniqueWhenReversed($text) {
        $reversed = strrev($text);
        return $text !== $reversed;
    }
    
    /**
     * 反転ペアを生成
     */
    public static function generateReversePair($text) {
        return [
            'original' => $text,
            'reversed' => strrev($text)
        ];
    }
    
    /**
     * 2つの文字列が反転関係にあるかチェック
     */
    public static function areReverseOfEachOther($str1, $str2) {
        return $str1 === strrev($str2);
    }
    
    /**
     * 反転して同じ値になるか検証
     */
    public static function validateSymmetry($data) {
        $results = [];
        
        foreach ($data as $item) {
            $results[$item] = [
                'original' => $item,
                'reversed' => strrev($item),
                'is_symmetric' => self::isSymmetric($item)
            ];
        }
        
        return $results;
    }
}

// 使用例
echo "=== 対称性チェック ===\n";
$strings = ['12321', '12345', 'abcba', 'hello'];

foreach ($strings as $str) {
    $symmetric = StringValidator::isSymmetric($str);
    echo "{$str}: " . ($symmetric ? '対称' : '非対称') . "\n";
}

echo "\n=== 反転ペア ===\n";
$pairs = StringValidator::generateReversePair('hello');
print_r($pairs);

echo "\n=== 反転関係チェック ===\n";
var_dump(StringValidator::areReverseOfEachOther('abc', 'cba'));  // true
var_dump(StringValidator::areReverseOfEachOther('abc', 'xyz'));  // false

例3: データのエンコード・デコード

class SimpleEncoder {
    /**
     * 簡易エンコード(反転 + Base64)
     */
    public static function encode($data) {
        $reversed = strrev($data);
        return base64_encode($reversed);
    }
    
    /**
     * 簡易デコード
     */
    public static function decode($encoded) {
        $decoded = base64_decode($encoded);
        return strrev($decoded);
    }
    
    /**
     * 2重反転エンコード
     */
    public static function doubleReverse($text) {
        $first = strrev($text);
        $second = strrev($first);
        return $second;  // 元に戻る
    }
    
    /**
     * チェックサム生成(簡易版)
     */
    public static function generateChecksum($data) {
        $combined = $data . strrev($data);
        return md5($combined);
    }
    
    /**
     * 難読化
     */
    public static function obfuscate($text) {
        $reversed = strrev($text);
        $encoded = base64_encode($reversed);
        return str_rot13($encoded);
    }
    
    /**
     * 難読化解除
     */
    public static function deobfuscate($obfuscated) {
        $unrotated = str_rot13($obfuscated);
        $decoded = base64_decode($unrotated);
        return strrev($decoded);
    }
}

// 使用例
echo "=== エンコード・デコード ===\n";

$original = "secret message";
$encoded = SimpleEncoder::encode($original);
$decoded = SimpleEncoder::decode($encoded);

echo "元のデータ: {$original}\n";
echo "エンコード: {$encoded}\n";
echo "デコード: {$decoded}\n";

echo "\n=== チェックサム ===\n";
$data = "important data";
$checksum = SimpleEncoder::generateChecksum($data);
echo "データ: {$data}\n";
echo "チェックサム: {$checksum}\n";

echo "\n=== 難読化 ===\n";
$text = "confidential";
$obfuscated = SimpleEncoder::obfuscate($text);
$deobfuscated = SimpleEncoder::deobfuscate($obfuscated);

echo "元: {$text}\n";
echo "難読化: {$obfuscated}\n";
echo "復元: {$deobfuscated}\n";

例4: 数値処理

class NumberReverser {
    /**
     * 数値を反転
     */
    public static function reverseNumber($number) {
        $str = (string)abs($number);
        $reversed = strrev($str);
        $result = (int)$reversed;
        
        return $number < 0 ? -$result : $result;
    }
    
    /**
     * 反転した数値を加算
     */
    public static function addReversed($number) {
        $reversed = self::reverseNumber($number);
        return $number + $reversed;
    }
    
    /**
     * 196問題をチェック(回文になるまで加算)
     */
    public static function findPalindrome($number, $maxIterations = 100) {
        $steps = [];
        $current = $number;
        
        for ($i = 0; $i < $maxIterations; $i++) {
            $reversed = self::reverseNumber($current);
            $steps[] = [
                'number' => $current,
                'reversed' => $reversed,
                'sum' => $current + $reversed
            ];
            
            if (PalindromeChecker::isNumericPalindrome($current)) {
                return [
                    'found' => true,
                    'iterations' => $i,
                    'result' => $current,
                    'steps' => $steps
                ];
            }
            
            $current = $current + $reversed;
        }
        
        return [
            'found' => false,
            'iterations' => $maxIterations,
            'steps' => $steps
        ];
    }
    
    /**
     * 数値のミラーリング
     */
    public static function mirrorNumber($number) {
        $str = (string)$number;
        return $str . strrev($str);
    }
}

// 使用例
echo "=== 数値反転 ===\n";
$numbers = [123, 9876, -456, 1000];

foreach ($numbers as $num) {
    $reversed = NumberReverser::reverseNumber($num);
    echo "{$num} → {$reversed}\n";
}

echo "\n=== 反転数値を加算 ===\n";
$num = 123;
$sum = NumberReverser::addReversed($num);
echo "{$num} + " . NumberReverser::reverseNumber($num) . " = {$sum}\n";

echo "\n=== 回文を見つける ===\n";
$result = NumberReverser::findPalindrome(89, 10);
if ($result['found']) {
    echo "回文発見: {$result['result']} ({$result['iterations']}ステップ)\n";
}

echo "\n=== ミラー数値 ===\n";
echo NumberReverser::mirrorNumber(123) . "\n";  // 123321

例5: テキスト処理

class TextProcessor {
    /**
     * 単語を反転
     */
    public static function reverseWords($sentence) {
        $words = explode(' ', $sentence);
        $reversed = array_map('strrev', $words);
        return implode(' ', $reversed);
    }
    
    /**
     * 文の順序を反転
     */
    public static function reverseSentenceOrder($text) {
        return strrev($text);
    }
    
    /**
     * 各行を反転
     */
    public static function reverseLines($text) {
        $lines = explode("\n", $text);
        $reversed = array_map('strrev', $lines);
        return implode("\n", $reversed);
    }
    
    /**
     * 母音と子音の位置を確認
     */
    public static function analyzeReversed($word) {
        $reversed = strrev($word);
        
        return [
            'original' => $word,
            'reversed' => $reversed,
            'length' => strlen($word),
            'same' => $word === $reversed
        ];
    }
    
    /**
     * アナグラムチェックの補助
     */
    public static function sortedString($text) {
        $chars = str_split(strtolower($text));
        sort($chars);
        return implode('', $chars);
    }
}

// 使用例
echo "=== 単語反転 ===\n";
$sentence = "Hello World from PHP";
echo "元: {$sentence}\n";
echo "反転: " . TextProcessor::reverseWords($sentence) . "\n";
// olleH dlroW morf PHP

echo "\n=== 文全体反転 ===\n";
echo TextProcessor::reverseSentenceOrder($sentence) . "\n";
// PHP morf dlroW olleH

$multiline = "Line 1\nLine 2\nLine 3";
echo "\n=== 各行反転 ===\n";
echo TextProcessor::reverseLines($multiline) . "\n";

echo "\n=== 分析 ===\n";
$analysis = TextProcessor::analyzeReversed('racecar');
print_r($analysis);

例6: ゲームやパズル

class WordGame {
    /**
     * リバースワードゲーム
     */
    public static function createReverseChallenge($word) {
        return [
            'hint' => strrev($word),
            'answer' => $word,
            'length' => strlen($word)
        ];
    }
    
    /**
     * ヒントを生成
     */
    public static function generateHint($word, $revealCount = 2) {
        $reversed = strrev($word);
        $hint = str_repeat('*', strlen($word));
        
        // 最初と最後の文字を表示
        if (strlen($word) > 0) {
            $hint[0] = $word[0];
        }
        if (strlen($word) > 1) {
            $hint[strlen($hint) - 1] = $word[strlen($word) - 1];
        }
        
        return [
            'hint' => $hint,
            'reversed' => $reversed,
            'length' => strlen($word)
        ];
    }
    
    /**
     * スコア計算
     */
    public static function calculateScore($word, $timeTaken) {
        $baseScore = strlen($word) * 10;
        $timeBonus = max(0, 60 - $timeTaken) * 2;
        
        $isPalindrome = PalindromeChecker::isPalindrome($word);
        $palindromeBonus = $isPalindrome ? 50 : 0;
        
        return $baseScore + $timeBonus + $palindromeBonus;
    }
}

// 使用例
echo "=== リバースワードゲーム ===\n";

$words = ['elephant', 'computer', 'racecar'];

foreach ($words as $word) {
    $challenge = WordGame::createReverseChallenge($word);
    echo "\nヒント(反転): {$challenge['hint']}\n";
    echo "文字数: {$challenge['length']}\n";
    echo "答え: {$challenge['answer']}\n";
    
    $hint = WordGame::generateHint($word);
    echo "部分ヒント: {$hint['hint']}\n";
}

例7: セキュリティとハッシュ

class SecurityHelper {
    /**
     * 反転ハッシュ生成
     */
    public static function reverseHash($data) {
        $reversed = strrev($data);
        $hash = hash('sha256', $reversed);
        return $hash;
    }
    
    /**
     * 二重ハッシュ
     */
    public static function doubleHash($data) {
        $hash1 = hash('sha256', $data);
        $hash2 = hash('sha256', strrev($data));
        return hash('sha256', $hash1 . $hash2);
    }
    
    /**
     * トークン生成
     */
    public static function generateToken($seed) {
        $timestamp = time();
        $random = bin2hex(random_bytes(16));
        $combined = $seed . $timestamp . $random;
        
        $forward = hash('sha256', $combined);
        $backward = hash('sha256', strrev($combined));
        
        return substr($forward, 0, 16) . substr($backward, 0, 16);
    }
    
    /**
     * チェックサム検証
     */
    public static function verifyChecksum($data, $checksum) {
        $calculated = self::reverseHash($data);
        return hash_equals($checksum, $calculated);
    }
}

// 使用例
echo "=== セキュリティ処理 ===\n";

$data = "sensitive information";

echo "データ: {$data}\n";
echo "反転ハッシュ: " . SecurityHelper::reverseHash($data) . "\n";
echo "二重ハッシュ: " . SecurityHelper::doubleHash($data) . "\n";

$token = SecurityHelper::generateToken('user123');
echo "\nトークン: {$token}\n";

例8: ファイル名処理

class FilenameHelper {
    /**
     * 拡張子を保ったまま名前を反転
     */
    public static function reverseBasename($filename) {
        $info = pathinfo($filename);
        
        $basename = $info['filename'];
        $extension = isset($info['extension']) ? '.' . $info['extension'] : '';
        
        return strrev($basename) . $extension;
    }
    
    /**
     * ユニークなファイル名を生成
     */
    public static function generateUniqueName($originalName) {
        $info = pathinfo($originalName);
        $basename = $info['filename'];
        $extension = isset($info['extension']) ? '.' . $info['extension'] : '';
        
        $reversed = strrev($basename);
        $timestamp = time();
        
        return "{$basename}_{$reversed}_{$timestamp}{$extension}";
    }
    
    /**
     * ペアファイル名を生成
     */
    public static function generatePairName($filename) {
        $reversed = strrev(pathinfo($filename, PATHINFO_FILENAME));
        $extension = pathinfo($filename, PATHINFO_EXTENSION);
        
        return $reversed . ($extension ? '.' . $extension : '');
    }
}

// 使用例
echo "=== ファイル名処理 ===\n";

$files = ['document.txt', 'photo.jpg', 'backup'];

foreach ($files as $file) {
    echo "\n元: {$file}\n";
    echo "反転: " . FilenameHelper::reverseBasename($file) . "\n";
    echo "ユニーク: " . FilenameHelper::generateUniqueName($file) . "\n";
    echo "ペア: " . FilenameHelper::generatePairName($file) . "\n";
}

パフォーマンスの考慮

// 大量の文字列反転
$text = str_repeat("abcdefghijklmnopqrstuvwxyz", 1000);

// strrev()
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
    strrev($text);
}
$time1 = microtime(true) - $start;

// 手動反転
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
    $reversed = '';
    for ($j = strlen($text) - 1; $j >= 0; $j--) {
        $reversed .= $text[$j];
    }
}
$time2 = microtime(true) - $start;

echo "strrev(): {$time1}秒\n";
echo "手動反転: {$time2}秒\n";

// strrev()は非常に高速に最適化されている

まとめ

strrev()関数の特徴をまとめると:

できること:

  • 文字列の反転
  • 回文のチェック
  • 数値の反転
  • データのエンコード補助

推奨される使用場面:

  • 回文(パリンドローム)チェック
  • 文字列の対称性検証
  • 簡易的なエンコード
  • 数値処理
  • ゲームやパズル
  • ユニークなID生成

注意点:

  • マルチバイト文字(日本語など)では正しく動作しない
  • マルチバイト対応が必要な場合はmb_substr()を使った独自実装が必要
  • セキュリティ目的のエンコードには不十分

マルチバイト対応:

function mb_strrev($str, $encoding = 'UTF-8') {
    $length = mb_strlen($str, $encoding);
    $reversed = '';
    for ($i = $length - 1; $i >= 0; $i--) {
        $reversed .= mb_substr($str, $i, 1, $encoding);
    }
    return $reversed;
}

関連関数:

  • str_split(): 文字列を配列に分割
  • array_reverse(): 配列を反転
  • substr(): 部分文字列の取得

パフォーマンス:

  • 非常に高速(C言語レベルで最適化)
  • 大量のデータでも効率的

strrev()はシンプルながら様々な用途に使える関数です。特に回文チェックや数値処理、ゲーム実装などで活躍します。マルチバイト文字を扱う場合は独自実装が必要ですが、ASCII文字列なら非常に効率的に動作します!

タイトルとURLをコピーしました