Here's the magic behind it.
If you take a closer look at the ASCII table, you'll notice that the ASCII codes of the uppercase and lowercase of the same letter differ with value 32.
So, for example the ASCII code of A
is 65
while for a
it's 97
and
97 - 65 = 32
.
This means if you take any capital letter (from ASCII) and +32 to it, you'll get the lowercase of the same letter. And -32 for uppercase again.
'A' + 32 = 0100 0001 + 0010 0000 = 0110 0001 = 'a'
Another interesting thing, is that instead of +-32 for upper/lower casing you actually can invert the 6th bit of the character. This will have exact the same result because
32 = 0010 0000
(pay attention that for 32 sixth bit is 1).
And we can use XOR (^
) operation there for that inversion.
So, 'A' ^ 32 = 'a'
and 'a' ^ 32 = 'A'
A : 65 = 0100 0001
XOR
32 = 0010 0000
|
v
a : 97 = 0110 0001
Now let's get back to the code of the question.
Starting from the second part of the code:
for(i=0;s[i];){
putchar(s[i++]^f*32);
}
What it does, it just iterates over the string s
and does inversion ^32*f
based on the value of f
.
So, if the f
is 1
it will do inversion, if 0
then not (as 32*f = 0
).
And the value of the f
is based on the other part of the code:
for(;s[i];){
f&=(s[i++]<'a');
}
which determines whether all the characters of the original s
where capital letters or not. It does that by checking if the characters are <'a'
(as all the capital letters in ASCII are <'a').
P.S. As others also stated, the fix should be s[i++]^(f*32)
.
The brackets are important there because of the operator precedence.
P.P.S In general I'd recommend rewriting that code to make it more readable.
You might want to take a look at the other solutions here.