2010-02-14 27 views
10

Làm thế nào tôi có thể trao đổi xung quanh/chuyển đổi trường hợp của các ký tự trong một chuỗi, ví dụ:Chuyển kiểu chữ, php

$str = "Hello, My Name is Tom"; 

Sau khi tôi chạy mã tôi nhận được một kết quả như thế này:

$newstr = "hELLO, mY nAME Is tOM"; 

Điều này có thể thực hiện được không?

Trả lời

1

Bạn sẽ cần phải lặp qua chuỗi kiểm tra trường hợp của mỗi ký tự, gọi strtolower() hoặc strtoupper() khi thích hợp, thêm ký tự đã sửa đổi vào chuỗi mới.

+0

Bất kỳ ý tưởng làm thế nào để kiểm tra các trường hợp của một chuỗi? – tarnfeld

+2

Điều này có thể chỉ hoạt động đối với các ký tự ASCII. Thay thế cho 'strotolower()' có thể là 'mb_strtolower()'. – Messa

+2

'ctype_lower()' http://php.net/manual/en/function.ctype-lower.php –

0

Tôi cho rằng một giải pháp có thể được sử dụng một cái gì đó như thế này:

$str = "Hello, My Name is Tom"; 
$newStr = ''; 
$length = strlen($str); 
for ($i=0 ; $i<$length ; $i++) { 
    if ($str[$i] >= 'A' && $str[$i] <= 'Z') { 
     $newStr .= strtolower($str[$i]); 
    } else if ($str[$i] >= 'a' && $str[$i] <= 'z') { 
     $newStr .= strtoupper($str[$i]); 
    } else { 
     $newStr .= $str[$i]; 
    } 
} 
echo $newStr; 

nào giúp bạn:

hELLO, mY nAME IS tOM 


tức là bạn:

  • lặp trên mỗi ký tự của chuỗi gốc
  • nếu nó giữa A và Z, bạn đặt nó để giảm trường hợp
  • nếu nó giữa a và z, bạn đặt nó để chữ hoa
  • khác, bạn giữ nó như nó vốn có

Vấn đề là này có thể sẽ không làm việc độc đáo với ký tự đặc biệt như dấu :-(


Và đây là một đề nghị nhanh chóng mà có thể (hoặc có thể không) làm việc cho một số nhân vật khác:

$str = "Hello, My Name is Tom"; 
$newStr = ''; 
$length = strlen($str); 
for ($i=0 ; $i<$length ; $i++) { 
    if (strtoupper($str[$i]) == $str[$i]) { 
     // Putting to upper case doesn't change the character 
     // => it's already in upper case => must be put to lower case 
     $newStr .= strtolower($str[$i]); 
    } else { 
     // Putting to upper changes the character 
     // => it's in lower case => must be transformed to upper case 
     $newStr .= strtoupper($str[$i]); 
    } 
} 
echo $newStr; 

Một ý tưởng, bây giờ, sẽ được sử dụng mb_strtolowermb_strtoupper: nó có thể giúp với các nhân vật đặc biệt, và đa byte mã hóa ...

9

OK Tôi biết bạn đã có một câu trả lời, nhưng hơi tối nghĩa strtr() chức năng đang khóc ra sẽ được sử dụng cho điều này;)

$str = "Hello, My Name is Tom"; 
echo strtr($str, 
      'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 
      'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'); 
+0

Nếu bạn muốn xử lý các ký tự UTF-8 nhiều byte, bạn sẽ cần sử dụng strtr ($ str, $ replaceutions_array). Đây thực sự là phương tiện tôi sử dụng để tách dấu trọng âm khỏi tất cả các chữ cái của chuỗi UTF8. – user272563

48

Nếu chuỗi của bạn là ASCII chỉ, bạn có thể sử dụng XOR:

$str = "Hello, My Name is Tom"; 

print strtolower($str)^strtoupper($str)^$str; 

Đầu ra:

hELLO, mY nAME IS tOM 
+6

đẹp! – Juddling

+1

Juddling: Cảm ơn :-) – Mike

+2

Tôi không hiểu tại sao đây không phải là câu trả lời được chấp nhận. – vascowhite

3

Chức năng tương tự như câu trả lời của Mark.

preg_replace_callback(
    '/[a-z]/i', 
    function($matches) { 
     return $matches[0]^' '; 
    }, 
    $str 
) 
+0

Làm thế nào để làm việc này? ''a'^''' dường như trả lại '0' cho tôi. – Sukima

+0

@Sukima không có ý tưởng, http://3v4l.org/8fG9E – Leigh

+0

'a'^'' trả về 'A'. Nó hoạt động vì 'A' là 0x41 và 'a' là 0x61 (và tương tự như vậy đối với tất cả A-Z), và bởi vì '' là 0x20. Bởi xor-ing bạn đang lật một chút. Nói một cách đơn giản, bạn đang thêm 32 vào các chữ cái viết hoa làm cho chúng viết thường và trừ 32 từ các chữ cái thường làm cho chúng trở thành chữ thường. – xtempore

0

Tôi biết câu hỏi này cũ - nhưng đây là 2 hương vị của việc triển khai nhiều byte của tôi.

phiên bản đa chức năng: (mb_str_split function found here):

function mb_str_split($string) { 
    # Split at all position not after the start:^
    # and not before the end: $ 
    return preg_split('/(?<!^)(?!$)/u', $string); 
} 

function mb_is_upper($char) { 
    return mb_strtolower($char, "UTF-8") != $char; 
} 

function mb_flip_case($string) { 
    $characters = mb_str_split($string); 
    foreach($characters as $key => $character) { 
     if(mb_is_upper($character)) 
      $character = mb_strtolower($character, 'UTF-8'); 
     else 
      $character = mb_strtoupper($character, 'UTF-8'); 

     $characters[$key] = $character; 
    } 
    return implode('',$characters); 
} 

đơn chức năng phiên bản:

function mb_flip_case($string) { 
    $characters = preg_split('/(?<!^)(?!$)/u', $string); 
    foreach($characters as $key => $character) { 
     if(mb_strtolower($character, "UTF-8") != $character) 
      $character = mb_strtolower($character, 'UTF-8'); 
     else 
      $character = mb_strtoupper($character, 'UTF-8'); 

     $characters[$key] = $character; 
    } 
    return implode('',$characters); 
} 
0

Tiếp theo kịch bản hỗ trợ ký tự UTF-8 như "a" vv:

<?php 
$str = 'aaAAąAŚĆżź'; 
$newstr = ''; 
preg_match_all('#.#u', $str, $match); 
foreach ($match[0] as $v) 
$newstr.= (($l=mb_strtolower($v, 'UTF-8')) === $v) ? mb_strtoupper($v, 'UTF-8') : $l; 
echo $str, '<br/>', $newstr; 
0

Cách nhanh nhất là với một bitmask. Không có hàm chuỗi hoặc regex. PHP là một wrapper cho C, vì vậy chúng tôi có thể thao tác bit khá dễ dàng nếu bạn biết chức năng logic của bạn như OR, NOT, AND, XOR, NAND, vv ..:

function swapCase($string) { 
    for ($i = 0; $i < strlen($string); $i++) { 
     $char = ord($string{$i}); 
     if (($char > 64 && $char < 91) || ($char > 96 && $char < 123)) { 
      $string{$i} = chr($char^32); 
     } 
    } 
    return $string; 
} 

Đây là những gì thay đổi nó:

$string{$i} = chr($char^32); 

Chúng tôi có nhân vật thứ N trong $string và thực hiện một XOR (^) nói với người phiên dịch để lấy giá trị số nguyên của $char và trao đổi các bit thứ 6 (32) từ một 1-0 hoặc từ 0 đến 1.

Tất cả các ký tự ASCII là 32 từ các đối tác của chúng (ASCII là một thiết kế khéo léo vì điều này. Vì 32 là sức mạnh của 2 (2^5), thật dễ dàng để chuyển bit. Để có được giá trị ASCII của một bức thư, sử dụng được xây dựng trong chức năng PHP ord():

ord('a') // 65 
ord('A') // 97 
// 97 - 65 = 32 

Vì vậy, bạn lặp qua chuỗi sử dụng strlen() như phần giữa của for vòng lặp, và nó sẽ lặp chính xác số lần khi chuỗi của bạn có chữ cái. Nếu ký tự ở vị trí $i là một chữ cái (a-z (65-90) hoặc A-Z (97-122)), ký tự sẽ hoán đổi ký tự đó cho chữ hoa hoặc chữ thường bằng bitmask.

Sau đây là cách bitmask hoạt động:

0100 0001 // 65 (lowercase a) 
0010 0000 // 32 (bitmask of 32) 
--------- // XOR means: we put a 1 if the bits are different, a 0 if they are same. 
0110 0001 // 97 (uppercase A) 

Chúng ta có thể đảo ngược nó:

0110 0001 // 97 (A) 
0010 0000 // Bitmask of 32 
--------- 
0100 0001 // 65 (a) 

Không cần str_replace hoặc preg_replace, chúng tôi chỉ trao đổi bit để thêm hoặc trừ đi 32 từ giá trị ASCII của nhân vật và chúng tôi trao đổi các trường hợp. Bit thứ 6 (thứ 6 từ bên phải) xác định nếu ký tự là chữ hoa hay chữ thường. Nếu đó là 0, đó là chữ thường và 1 nếu chữ hoa. Thay đổi bit từ 0 thành 1 quảng cáo 32, nhận giá trị hoa chr() và thay đổi từ 1 thành 0 bằng trừ 32, chuyển chữ thường viết hoa.

swapCase('userId'); // USERiD 
swapCase('USERiD'); // userId 
swapCase('rot13'); // ROT13 

Chúng tôi cũng có thể có một chức năng mà giao dịch hoán đổi các trường hợp trên một nhân vật đặc biệt:

// $i = position in string 
function swapCaseAtChar($string, $i) { 
    $char = ord($string{$i}); 
    if (($char > 64 && $char < 91) || ($char > 96 && $char < 123)) { 
     $string{$i} = chr($char^32); 
     return $string; 
    } else { 
     return $string; 
    } 
} 

echo swapCaseAtChar('iiiiiiii', 0); // Iiiiiiii 
echo swapCaseAtChar('userid', 4); // userId 

// Numbers are no issue 
echo swapCaseAtChar('12345qqq', 7); // 12345qqQ 
Các vấn đề liên quan