如果我有一个数字字符串(字符数组),一个数字是一个字符,导致四位数的空格是5个字节,包括空终止。
unsigned char num[] ="1024";
printf("%d", sizeof(num)); // 5
但是,1024可以写为
unsigned char binaryNum[2];
binaryNum[0] = 0b00000100;
binaryNum[1] = 0b00000000;
如何有效地实现从字符串到二进制的转换? 在我的程序中,我将使用≈30位数字,因此空间增益会很大。 我的目标是创建通过UDP / TCP发送的数据包。
我不希望使用库来执行此任务,因为代码占用的可用空间很小。
编辑: 感谢您的快速回复。
char num = 0b0000 0100 // "4"
--------------------------
char num = 0b0001 1000 // "24"
-----------------------------
char num[2];
num[0] = 0b00000100;
num[1] = 0b00000000;
// num now contains 1024
我需要≈10个字节来包含二进制形式的数字。所以,如果我建议逐个解析数字,从后面开始,那将如何构建最终的大二进制数?
答案 0 :(得分:1)
通常,将字符串表示中的数字转换为十进制很容易,因为每个字符都可以单独解析。例如。要将"1024"
转换为1024
,您只需查看'4'
,将其转换为4
,乘以10
,然后转换为2
并添加它,乘以10
,依此类推,直到你解析了整个字符串。
对于二进制文件来说,这并不容易,例如您可以将4
转换为100
,将2
转换为010
,但42
不是100 010
或110
或类似的内容。因此,您最好的选择是将整个事物转换为数字,然后使用数学运算(位移等)将该数字转换为二进制数。这适用于适合其中一种C ++数字类型的数字,但是如果你想处理任意大数字,你需要一个BigInteger
类,这对你来说似乎是一个问题,因为代码必须很小
从你的问题我收集到你想要压缩字符串表示以便通过网络传输数字,所以我提供的解决方案不会严格转换为二进制,但仍然会使用比字符串表示更少的字节和很容易使用。它基于以下事实:您可以以4位存储数字0..9
,因此您可以在一个字节中输入其中两个数字。因此,您可以在n
字节中存储n/2
位数字。算法可以如下:
'4'
'0'
以获取4
(即值为4的int)。0
digits[0] = (4 << 4) + 0
。digits[1] = (2 << 4) + 1
。您在记忆中的表现现在看起来像
4 0 2 1
0100 0000 0010 0001
digits[0] digits[1]
即
digits = { 64, 33 }
这不是1024的二进制表示,但它更短,它允许您通过反转算法轻松恢复原始数字。
您甚至还有5个值,不用于存储数字(即大于1010
的所有内容),您可以将其用于存储符号,小数点等其他内容,字节顺序或数字结束分隔符。)
我相信如果你选择使用它,你将能够实现它。
答案 1 :(得分:0)
如果我理解你的问题,你会想要这样做:
string
表示转换为integer
。integer
转换为binary
表示。对于第1步:
'0'
char
10^n
(取决于位置)并加总。对于第2步(对于int x
),一般来说:
x%2
为您提供最低有效位(LSB)。x /= 2
&#34;删除&#34; LSB。例如,取x = 6
。
x%2 = 0
(LSB),x /= 2
- &gt; x becomes 3
x%2 = 1
,x /= 2
- &gt; x becomes 1
x%2 = 1
(MSB),x /= 2
- &gt; x becomes 0
。所以我们看到(6)decimal == (110)bin
。
关于实施(针对N=2
,其中N
的最大数量为bytes
):
int x = 1024;
int n=-1, p=0, p_=0, i=0, ex=1; //you can use smaller types of int for this if you are strict on memory usage
unsigned char num[N] = {0};
for (p=0; p<(N*8); p++,p_++) {
if (p%8 == 0) { n++; p_=0; } //for every 8bits, 1) store the new result in the next element in the array. 2) reset the placing (start at 2^0 again).
for (i=0; i<p_; i++) ex *= 2; //ex = pow(2,p_); without using math.h library
num[n] += ex * (x%2); //add (2^p_ x LSB) to num[n]
x /= 2; // "remove" the last bit to check for the next.
ex = 1; // reset the exponent
}
我们可以查看x = 1024
的结果:
for (i=0; i<N; i++)
printf("num[%d] = %d\n", i, num[i]); //num[0] = 0 (0b00000000), num[1] = 4 (0b00000100)
答案 2 :(得分:0)
要将表示为字符串的最多30位十进制数转换为严重的字节,实际上基数为256的表示形式最多需要13个字节。 (天花板30 / log10(256))
简单算法
dest = 0
for each digit of the string (starting with most significant)
dest *= 10
dest += digit
作为C代码
#define STR_DEC_TO_BIN_N 13
unsigned char *str_dec_to_bin(unsigned char dest[STR_DEC_TO_BIN_N], const char *src) {
// dest[] = 0
memset(dest, 0, STR_DEC_TO_BIN_N);
// for each digit ...
while (isdigit((unsigned char) *src)) {
// dest[] = 10*dest[] + *src
// with dest[0] as the most significant digit
int sum = *src - '0';
for (int i = STR_DEC_TO_BIN_N - 1; i >= 0; i--) {
sum += dest[i]*10;
dest[i] = sum % 256;
sum /= 256;
}
// If sum is non-zero, it means dest[] overflowed
if (sum) {
return NULL;
}
}
// If stopped on something other than the null character ....
if (*src) {
return NULL;
}
return dest;
}