二进制字符串转十进制函数超出32位后结果异常求助
二进制字符串转十进制:超长串溢出问题解决
你的问题核心在于固定长度整数类型的位数限制导致溢出。size_t的长度依赖系统:32位系统下是32位,64位系统下是64位。当二进制字符串长度超过对应位数时,r << 1操作会触发无符号整数溢出——根据C标准,无符号溢出会按2^N(N为类型位数)取余,最终得到的是截断后的值,并非完整的十进制结果。
下面是几种针对性的解决方案:
方案1:用更大的标准整数类型(适配≤64位二进制串)
如果你的二进制串长度不超过64位,可以改用unsigned long long类型(C99及以上标准支持),它的位数至少是64位,能覆盖更长的二进制串:
#include <stdio.h> unsigned long long strBinaryToDecimal(char* s) { char c; char *p = s; unsigned long long r = 0; while (p && *p) { c = *p++; if (c == '0') { r = (r << 1); } else if (c == '1') { r = (r << 1) + 1; } else { break; } } return r; } int main(void) { char reading[33] = "100110011001100110011001100110011"; printf("Binary: %s\n", reading); printf("Decimal: %llu\n", strBinaryToDecimal(reading)); return 0; }
注意:这种方法最多处理64位二进制串,超过后仍会溢出。
方案2:字符串模拟十进制运算(支持任意长度二进制串)
要处理任意长度的二进制串,必须用字符串存储十进制结果,模拟手工计算逻辑:每读取一位二进制,就将当前十进制结果乘2,再加上当前位的0或1。
#include <stdio.h> #include <string.h> // 二进制字符串转十进制字符串,结果存入dec_str(需提前分配足够空间) void strBinaryToDecimalStr(char* s, char* dec_str) { // 初始化十进制字符串为"0" strcpy(dec_str, "0"); char *p = s; int dec_len = 1; while (p && *p) { int bit = *p++ - '0'; if (bit != 0 && bit != 1) break; // 步骤1:十进制数乘2 int carry = 0; for (int i = dec_len - 1; i >= 0; i--) { int val = (dec_str[i] - '0') * 2 + carry; dec_str[i] = (val % 10) + '0'; carry = val / 10; } // 处理乘法进位 if (carry != 0) { memmove(dec_str + 1, dec_str, dec_len); dec_str[0] = carry + '0'; dec_len++; } // 步骤2:加上当前二进制位的值 if (bit == 1) { carry = 1; for (int i = dec_len - 1; i >= 0 && carry; i--) { int val = (dec_str[i] - '0') + carry; dec_str[i] = (val % 10) + '0'; carry = val / 10; } // 处理加法进位 if (carry != 0) { memmove(dec_str + 1, dec_str, dec_len); dec_str[0] = carry + '0'; dec_len++; } } } } int main(void) { char reading[100] = "1001100110011001100110011001100111110000"; char dec_str[200] = {0}; // 分配足够大的存储空间 strBinaryToDecimalStr(reading, dec_str); printf("Binary: %s\n", reading); printf("Decimal: %s\n", dec_str); return 0; }
该方法支持任意长度的二进制串,只要提前为dec_str分配足够的空间即可。
方案3:使用标准库函数(适配≤ULLONG_MAX的二进制串)
C标准库的strtoull函数可以直接将二进制字符串转为unsigned long long,还能检测溢出:
#include <stdio.h> #include <stdlib.h> #include <errno.h> int main(void) { char reading[33] = "100110011001100110011001100110011"; char *endptr; errno = 0; unsigned long long val = strtoull(reading, &endptr, 2); if (errno == ERANGE) { printf("二进制字符串超出unsigned long long的范围\n"); } else if (*endptr != '\0') { printf("二进制字符串包含无效字符\n"); } else { printf("Binary: %s\n", reading); printf("Decimal: %llu\n", val); } return 0; }
当二进制串超过unsigned long long的最大值时,errno会被设为ERANGE,可据此处理溢出场景。
内容的提问来源于stack exchange,提问作者Cem
相关产品推荐
相关产品推荐

