将字符串转换为二进制,然后计算未设置的位数

问题描述

在C语言中,我想从用户那里获取一个字符串,逐位扫描,然后打印出未设置的位数。字符串长度将不大于127。我还想排除字符串末尾的空字符。对于字符串“ hi”,即使应为9,我的输出也为25。不确定我做错了什么。

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

解决方法

您的错误是:

  • 您正在计算00000000 00000000 01011000 01101001的零。 (仅读取2个字符,但看来您是在完整的int中进行计数)
  • 127个字节太长,无法放入int
  • 分配给bin的缓冲区没有空间来终止空字符,但是strcat()会添加它。因此将执行越界写入。
  • (void)int main之后丢失。
  • 缺少必需的标题。

您无需直接将字符串转换为二进制字符串,而可以直接计算字符中的位数:

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