Testing if an integer is an uppercase ASCII letter using bit manipulation

后端 未结 4 774
南方客
南方客 2021-01-28 11:35

For an assignment, I\'m trying to make some code in C that uses only bit manipulation to test if an integer is an ASCII uppercase letter. The letter will be given by its ASCII c

4条回答
  •  萌比男神i
    2021-01-28 12:32

    You can test if an ASCII letter c is upper case by checking its 0x20 bit, it must be 0 for uppercase and 1 for lowercase:

    if (!(c & 0x20))
        printf("ASCII letter %c is uppercase\n", c);
    

    but be aware that this test does not work if you don't already know that c is a letter. It would erroneously match '@' and '[', '\\', ']', '^' and '_', and the whole range of characters with the high bit set from 192 to 223, which are not part of ASCII but are valid unsigned char values.

    If you want a single test to verify if c is an uppercase ASCII letter, try:

    if ((unsigned)(c - 'A') <= (unsigned)('Z' - 'A'))
         printf("%c is an uppercase ASCII letter\n", c);
    

    EDIT: it is unclear what you mean by I am not allowed to use if statements, or any kind of type casting operations. I must test to see if the number is between the two numbers, including numbers far outside the range of the ASCII code, and return 1 if it is or else 0.

    • If you know c is a letter, both !(c & 0x20) and (((c >> 5) & 1) ^ 1) will have value 1 if c is uppercase and 0 if not.
    • If c can be any integer value, just write the regular comparison (c >= 'A' && c <= 'Z') and the compiler will produce better code than you would by attempting hazardous bit-twiddling tricks.

    EDIT again:

    Since c can be any integer value and you are only allowed bit manipulations, here is another solution: !((c >> 5) ^ 2) & (0x07fffffeU >> (c & 31)). Below is a program to test this:

    #include 
    #include 
    
    static int uppertest(int c) {
        return !((c >> 5) ^ 2) & (0x07fffffeU >> (c & 31));
    }
    
    int main(int argc, char *argv[]) {
        for (int i = 1; i < argc; i++) {
            int c = strtol(argv[i], NULL, 0);
            printf("uppertest(%d) -> %d\n", c, uppertest(c));
        }
        return 0;
    }
    

提交回复
热议问题