Случай с символом переключения, php

Как я могу поменять / переключить случай символов в строке, например:

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

После запуска кода я получаю такой результат:

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

Возможно ли это?

Вам нужно будет перебирать строку, проверяя случай каждого символа, вызывая strtolower() или strtoupper() в зависимости от ситуации, добавляя измененный символ к новой строке.

Если ваша строка является только ASCII, вы можете использовать XOR:

 $str = "Hello, My Name is Tom"; print strtolower($str) ^ strtoupper($str) ^ $str; 

Выходы:

 hELLO, mY nAME IS tOM 

ОК. Я знаю, что у вас уже есть ответ, но какая-то неясная функция strtr () кричит, что будет использоваться для этого;)

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

Очень похоже в функции ответа Марка.

 preg_replace_callback( '/[az]/i', function($matches) { return $matches[0] ^ ' '; }, $str ) 

Я полагаю, что решение может состоять в следующем:

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

Который доставит вам:

 hELLO, mY nAME IS tOM 

т.е. вы:

  • цикл над каждым символом исходной строки
  • если он находится между A и Z, вы помещаете его в нижний регистр
  • если он находится между a и z, вы помещаете его в верхний регистр
  • иначе, вы держите его как есть

Проблема в том, что это, вероятно, не будет работать с особым характером, как акценты 🙁

И вот быстрое предложение, которое могло бы (или не могло) работать для некоторых других персонажей:

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

Идея, теперь, будет заключаться в использовании mb_strtolower и mb_strtoupper : это может помочь со специальными символами и многобайтовыми кодировками …

Я знаю, что этот вопрос старый, но вот мои 2 варианта многобайтовой реализации.

Многофункциональная версия: ( здесь функция mb_str_split ):

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

Версия одной функции:

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

Следующий скрипт поддерживает символы UTF-8, такие как «±» и т. Д.

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

Самый быстрый способ – с битовой маской. Никаких неуклюжих строковых функций или регулярных выражений. PHP – это оболочка для C, поэтому мы можем легко манипулировать битами, если вы знаете свою логическую функцию, такую ​​как OR, NOT, AND, XOR, NAND и т. Д.:

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

Вот что это меняет:

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

Мы берем N-й символ в $string и выполняем XOR (^), говоря интерпретатору, чтобы взять целочисленное значение $char и заменить 6-й бит (32) с 1 на 0 или 0 на 1.

Все символы ASCII находятся в 32 от своих копий (из-за этого ASCII был гениальным дизайном. Поскольку 32 имеет мощность 2 (2 ^ 5), легко сдвинуть биты. Чтобы получить значение ASCII для буквы, используйте встроенную в функции PHP ord() :

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

Итак, вы перебираете строку, используя strlen() в качестве средней части цикла for , и она будет циклически повторяться столько раз, сколько ваша строка имеет буквы. Если символ в позиции $i является буквой (az (65-90) или AZ (97-122)), он будет заменять этот символ для прописного или нижнего регистра с использованием битовой маски.

Вот как работает битовая маска:

 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) 

Мы можем отменить это:

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

Нет необходимости в str_replace или preg_replace , мы просто preg_replace биты, чтобы добавить или вычесть 32 из значения ASCII символа, и мы заменим случаи. 6-й бит (6-й справа) определяет, имеет ли символ верхний или нижний регистр. Если это 0, это строчные буквы и 1, если в верхнем регистре. Изменение бита от 0 до 1 объявления 32, получение значения в верхнем регистре chr() и изменение от 1 до 0 вычитает 32, превращая прописную букву в нижнем регистре.

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

Мы можем также иметь функцию, которая меняет случай на конкретный символ:

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