2010-02-14 11 views
10

Wie kann ich tauschen um/schalten Sie den Fall der Zeichen in einer Zeichenfolge, zum Beispiel:Schalte die Zeichen Fall, php

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

Nachdem ich den Code ausführen bekomme ich ein Ergebnis wie folgt aus:

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

Ist das überhaupt möglich?

Antwort

1

Sie brauchen werden durch den String iterieren Testen der Fall jedes Zeichens, ruft strtolower() oder strtoupper() gegebenenfalls den veränderten Charakter auf eine neue Zeichenfolge hinzugefügt wird.

+0

Jede Idee, wie der Fall einer Zeichenfolge zu überprüfen? – tarnfeld

+2

Dies funktioniert wahrscheinlich nur für ASCII-Zeichen. Eine Alternative zu 'strotolower()' könnte 'mb_strtolower()' sein. – Messa

+2

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

0

Ich nehme eine Lösung könnte wie folgt zu verwenden sein:

$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; 

Welche bekommt man:

hELLO, mY nAME IS tOM 


dh Sie:

  • Schleife über jedes Zeichen von die ursprüngliche Zeichenfolge
  • wenn es zwischen A und Z ist, setzen Sie es Fall
  • zu senken, wenn es zwischen a und z ist, können Sie es in Großbuchstaben setzen
  • sonst, halten Sie es

Das Problem, wie sie ist sein dies funktionieren wird wahrscheinlich nicht gut mit Sonderzeichen wie Akzente :-(


und hier ist ein kurzer Vorschlag das könnte (oder auch nicht) Arbeit für einige andere Zeichen:

$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; 

Eine Idee wäre jetzt, seine mb_strtolower und mb_strtoupper zu verwenden: mit Sonderzeichen helfen kann, und Multi-Byte-Codierungen ...

9

OK Ich weiß, Sie haben bereits eine Antwort bekommen, aber die etwas dunkel strtr() Funktion schreit für diese verwendet werden;)

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

Wenn Sie mit Multi-Byte-UTF-8-Zeichen umgehen wollen, müssen Sie strtr ($ str, $ substitutions_array) verwenden. Dies ist eigentlich das Mittel, das ich verwende, um Akzente von allen Buchstaben einer UTF8-Zeichenfolge zu entfernen. – user272563

48

Wenn Ihr String ASCII nur, können Sie XOR verwenden:

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

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

Ausgänge:

hELLO, mY nAME IS tOM 
+6

das ist schön! – Juddling

+1

Juddling: Danke :-) – Mike

+2

Ich verstehe nicht, warum das nicht die akzeptierte Antwort ist. – vascowhite

3

Sehr ähnlich in der Funktion der Antwort von Mark.

+0

Wie funktioniert das? ''A'^'' scheint für mich "0" zurückzugeben. – Sukima

+0

@Sukima keine Idee, http://3v4l.org/8fG9E – Leigh

+0

'a'^'gibt' A 'zurück. Es funktioniert, weil 'A' 0x41 ist und 'a' 0x61 (und ebenfalls für alle A-Z) und weil '' 0x20 ist. Indem Sie xor-ing sind, spiegeln Sie dieses eine Bit. In einfachen Worten, Sie fügen 32 zu Großbuchstaben hinzu, machen sie Kleinbuchstaben und subtrahieren 32 von Kleinbuchstaben, um sie groß zu schreiben. – xtempore

0

Ich weiß, diese Frage ist alt - aber hier ist meine 2 Aromen einer Multi-Byte-Implementierung.

Multifunktionsversion: (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); 
} 

Einzelfunktionsversion:

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

Nach Skript unterstützt UTF-8-Zeichen wie "a" etc:

<?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

Der schnellste Weg ist mit einer Bitmaske. Keine klobigen String-Funktionen oder Regex. PHP ist ein Wrapper für C, so können wir Bits manipulieren ganz einfach, wenn Sie Ihre logische Funktion wie OR wissen, NOT, AND, XOR, NAND, etc ..:

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; 
} 

Dies ist, was es ändert:

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

Wir nehmen den N-ten Zeichen in $string und eine XOR (^) durchzuführen, den Interpreter zu sagen den ganzzahligen Wert von $char und Vertauschen der 6. Bit (32) von einer 1 auf 0 oder von 0 bis 1.

zu ergreifen

Alle ASCII - Zeichen sind 32 entfernt von ihren Gegenstücken (ASCII war ein geniales Design aus diesem Grund. Da 32 eine Potenz von 2 ist (2^5), ist es einfach Bits zu verschieben. Um den ASCII-Wert eines Briefes zu erhalten, verwenden Sie die in PHP-Funktion gebaut ord():

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

So Sie Schleife durch die Zeichenfolge strlen() als Mittelteil der for Schleife, und es wird Schleife genau die Anzahl der Male wie deine Zeichenfolge Buchstaben hat. Wenn das Zeichen an Position $i ein Buchstabe ist (a-z (65-90) oder A-Z (97-122)), wird das Zeichen für das Groß- oder Kleinbuchstabe mit einer Bitmaske ausgetauscht.

Hier ist, wie die Bitmaske funktioniert:

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) 

Wir können es umkehren:

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

Keine Notwendigkeit für str_replace oder preg_replace, wir tauschen Bits nur zu addieren oder subtrahieren 32 von der ASCII-Wert der Charakter und wir tauschen Fälle aus. Das 6. Bit (6. von rechts) bestimmt, ob das Zeichen Groß- oder Kleinbuchstaben ist. Wenn es eine 0 ist, ist es Kleinbuchstaben und 1 wenn Großbuchstaben. Ändert man das Bit von einer 0 auf eine 1, so wird 32, der Großbuchstabe chr() und der Wechsel von einer 1 zu einer 0 subtrahiert 32, wobei ein Großbuchstabe in Kleinbuchstaben umgewandelt wird.

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

Wir können auch eine Funktion, die den Fall auf einem bestimmten Zeichen tauscht:

// $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