Search code examples
cbinarybitbit-shift

Convert a string to binary and then count the number of unset bits


In C, I want to take a string (from the user), scan it by bit, and print out the number of unset bit. The string length will not be greater than 127. I also want to exclude the null character that is at the end of the string. For the string "hi", my output is 25 even though it should be 9. Not sure what I am doing incorrectly.

int unset(char* s){
    size_t len = strlen(s);
    char *bin = malloc(len*8);
    char x;

    bin[0] = '\0';

    for(int i=0; i<=len; ++i) { //convert the string to binary
        if (s[i] != '\0'){ 
            x = s[i];
            for(int j=7; j>=0; --j){
                if((x & (1 << j)) == 0) {
                    strcat(bin,"0");
                }
                else {
                    strcat(bin,"1");
                }
            }
        }
        else {
            break;
        }
    }
    int n = strtol(bin, NULL, 2);
    int count = 0;
    for(int i=0; i<INT_SIZE; i++){ //count the unset bits
        if((n & 1) == 0){
            ++count;
        }
        n >>= 1;
    }
    return count;
}

int main{
    char sen[128];
    printf("String: ");
    scanf("%s", sen);

    printf("%d", unset(sen));
    return 0; 
}

Solution

  • Your mistakes are:

    • You are counting zeros of 00000000 00000000 01011000 01101001. (only 2 characters is read, but it seems you are counting among full int)
    • 127 byte will be too long to fit in int.
    • The buffer assigned to bin has no room for terminating null-character, but strcat() will add that. Therefore out-of-bound write will be performed.
    • (void) is missing after int main.
    • Required headers are missing.

    Instead of converting strings to binary string, you can count bits in characters directly:

    #include <stdio.h>
    
    int unset(const char* s){
        int count = 0;
        while(*s != '\0'){
            for(int i=7; i>=0; --i){
                if((*s & (1 << i)) == 0) count++;
            }
            s++;
        }
        return count;
    }
    
    int main(void){
        char sen[128];
        printf("String: ");
        scanf("%127s", sen);
    
        printf("%d", unset(sen));
        return 0; 
    }