Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invert case of all letters in a string (uppercase to lowercase and lowercase to uppercase)

Tags:

string

php

case

How can I swap around / toggle the case of the characters in a string, for example:

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

After I run the code I get a result like this:

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

Is this even possible?

like image 431
tarnfeld Avatar asked Feb 14 '10 00:02

tarnfeld


People also ask

What inverts case for all letters in string?

You can invert case for all letters in a string using the brute force approach where we traverse through the entire string and check if it is a lower case or upper case and invert it using the upper() and the lower() method.

How do you convert all the letters in a string to uppercase?

Java String toUpperCase() Method The toUpperCase() method converts a string to upper case letters.

How do you change lower case letters to upper case letters without retyping it again?

Look for the “Change Case” button on the Ribbon or use keyboard shortcuts after selecting text. In Word and Outlook for Windows hold SHIFT + F3 (tap to cycle) until the case you want is applied (if you have a laptop you may also need to hold the FN key).

How do I change all letters to lowercase in string?

The toLowerCase() method converts a string to lower case letters. Note: The toUpperCase() method converts a string to upper case letters.


2 Answers

If your string is ASCII only, you can use XOR:

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

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

Outputs:

hELLO, mY nAME IS tOM
like image 183
Mike Avatar answered Nov 15 '22 15:11

Mike


The quickest way is with a bitmask. No clunky string functions or regex. PHP is a wrapper for C, so we can manipulate bits quite easily if you know your logical function like OR, 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;
}

This is what changes it:

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

We take the Nth character in $string and perform an XOR (^) telling the interpreter to take the integer value of $char and swapping the 6th bit (32) from a 1 to 0 or 0 to 1.

All ASCII characters are 32 away from their counterparts (ASCII was an ingenious design because of this. Since 32 is a power of 2 (2^5), it's easy to shift bits. To get the ASCII value of a letter, use the built in PHP function ord():

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

So you loop through the string using strlen() as the middle part of the for loop, and it will loop exactly the number of times as your string has letters. If the character at position $i is a letter (a-z (65-90) or A-Z (97-122)), it will swap that character for the uppercase or lowercase counterpart using a bitmask.

Here's how the bitmask works:

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)

We can reverse it:

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

No need for str_replace or preg_replace, we just swap bits to add or subtract 32 from the ASCII value of the character and we swap cases. The 6th bit (6th from the right) determines if the character is uppercase or lowercase. If it's a 0, it's lowercase and 1 if uppercase. Changing the bit from a 0 to a 1 ads 32, getting the uppercase chr() value, and changing from a 1 to a 0 subtracts 32, turning an uppercase letter lowercase.

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

We can also have a function that swaps the case on a particular character:

// $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
like image 35
mwieczorek Avatar answered Nov 15 '22 14:11

mwieczorek