2010-02-14 7 views
10

Comment puis-je troque autour/basculer le cas des caractères d'une chaîne, par exemple:Commutateur de cas de caractère, php

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

Après je lance le code que j'obtenir un résultat comme celui-ci:

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

Est-ce encore possible?

Répondre

1

Vous devrez parcourir la chaîne en testant le cas de chaque caractère, en appelant strtolower() ou strtoupper() selon le cas, en ajoutant le caractère modifié à une nouvelle chaîne.

+0

Toute idée comment vérifier le cas d'une chaîne? – tarnfeld

+2

Cela fonctionnera probablement uniquement pour les caractères ASCII. Une alternative à 'strotolower()' pourrait être 'mb_strtolower()'. – Messa

+2

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

0

Je suppose que une solution pourrait être d'utiliser quelque chose comme ceci:

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

Ce qui vous permet de vous:

hELLO, mY nAME IS tOM 


-à-dire vous:

boucle
  • sur chaque caractère la chaîne originale
  • si elle est entre A et Z, vous le mettez à Minuscules
  • si elle est entre un et z, vous le mettez en majuscules
  • autre, vous garder en l'état

Le problème étant cela ne fonctionnera probablement pas bien avec le caractère spécial comme les accents :-(


et voici une proposition rapide qui pourrait (ou non) travail pour d'autres personnages:

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

Une idée, maintenant, serait d'utiliser mb_strtolower et mb_strtoupper: il peut aider avec des caractères spéciaux, et encodages multi-octets ...

9

OK Je sais que vous avez déjà une réponse, mais la fonction quelque peu obscure strtr() est criant à utiliser pour cela;)

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

Si vous voulez traiter les caractères UTF-8 multi-octets, vous devrez utiliser strtr ($ str, $ substitutions_array). C'est en fait le moyen que j'utilise pour supprimer les accents de toutes les lettres d'une chaîne UTF8. – user272563

48

Si votre chaîne est ASCII seulement, vous pouvez utiliser XOR:

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

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

Sorties:

hELLO, mY nAME IS tOM 
+6

c'est magnifique! – Juddling

+1

Juddling: Merci :-) – Mike

+2

Je ne comprends pas pourquoi ce n'est pas la réponse acceptée. – vascowhite

3

Très similaire à la réponse de Mark.

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

Comment ça marche? '' a '^' ''semble retourner' 0' pour moi. – Sukima

+0

@Sukima aucune idée, http://3v4l.org/8fG9E – Leigh

+0

'a'^'' renvoie 'A'. Cela fonctionne parce que 'A' est 0x41 et 'a' est 0x61 (et de même pour tout A-Z), et parce que '' est 0x20. En xor-ing, vous renversez ce bit. En termes simples, vous ajoutez 32 aux lettres majuscules, ce qui les rend en minuscules et en soustrayant 32 des lettres minuscules en les faisant majuscules. – xtempore

0

Je sais que cette question est ancienne - mais voici mes deux versions d'une implémentation multi-octets.

version multi fonction: (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); 
} 

version monofonction:

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

script suivant prend en charge les caractères UTF-8 comme "å" 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

Le moyen le plus rapide est avec un masque de bits. Aucune fonction de chaîne maladroite ou regex. PHP est un wrapper C, donc on peut manipuler des bits assez facilement si vous savez que votre fonction logique comme OR, NOT, AND, XOR, NON-ET, 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; 
} 

C'est ce qui le change:

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

Nous prenons le caractère Nième $string et effectuer un XOR (^) indiquant l'interpréteur de prendre la valeur entière de $char et échangeant le sixième bit (32) à partir d'un 1 à 0 ou de 0 à 1.

Tous les caractères ASCII sont à 32 de leurs homologues (ASCII était un conception ingénieuse à cause de cela. Puisque 32 est une puissance de 2 (2^5), il est facile de décaler les bits. Pour obtenir la valeur ASCII d'une lettre, utilisez la fonction intégrée de PHP ord():

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

Vous boucle à travers la chaîne en utilisant strlen() comme la partie centrale de la boucle for, et il bouclera sur exactement le nombre de fois comme votre chaîne a des lettres. Si le caractère à la position $i est une lettre (a-z (65-90) ou A-Z (97-122)), il échangera ce caractère pour la contrepartie majuscule ou minuscule en utilisant un masque de bits.

Voilà comment le bitmask fonctionne:

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) 

Nous pouvons inverser:

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

Pas besoin de str_replace ou preg_replace, on échange seulement des bits pour ajouter ou soustraire 32 de la valeur ASCII le personnage et nous échangeons les cas. Le 6ème bit (6ème à partir de la droite) détermine si le caractère est en majuscule ou en minuscule. Si c'est 0, c'est minuscule et 1 si majuscule. Changer le bit d'un 0 à un 1 annonces 32, obtenant la valeur chr() majuscule, et changeant d'un 1 à un 0 soustrait 32, tournant une majuscule minuscule.

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

Nous pouvons aussi avoir une fonction qui intervertit le cas sur un caractère particulier:

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