【问题标题】:store binary of decimal in char array将十进制的二进制存储在 char 数组中
【发布时间】:2015-09-12 00:17:06
【问题描述】:

我想通过应用下面的代码在char 数组中存储十进制数的二进制等价物,但问题是我无法保存十进制数的最后一位。我得到了垃圾值。

 int k,j;
 char c[40];
 j=32;
 scanf("%d",&k);

 while(k)
 {    
     k=k>>1;
     c[j]=k|1;
     j--;
 }

 puts("number is");
 puts(c);

【问题讨论】:

  • 负值的右移是实现定义的,因此可能会产生意想不到的结果。
  • @Olaf 你能说出一个架构,其中将负值右移 1 会产生意想不到的结果吗?
  • 您应该向函数puts 传递一个以空字符结尾的字符数组,而不仅仅是任何字符数组。此函数打印所有字符,直到第一次出现空字符。在您的示例中,只要您有一个等于 0 的二进制数字,就会出现这样的字符。如果不存在这样的数字(即在 k == 0xFFFFFFFF 的情况下),那么您的程序会产生未定义的行为。在任何情况下,它都不会打印输入数字的二进制表示,因为您将数组中的字符设置为01,而不是'0''1'
  • @hyde:有各种 CPU 只提供逻辑(无符号)右移。对于这些,编译器很可能(并且将)不保留符号。注意:我不是向您指出特定的架构,而是您要证明它永远不会发生,因为标准实际上允许。我宁愿依靠(也是 IDB)将 int 转换为 unsigned,因为 that 不太可能失败。注意:如果您确实 expect 改变符号的值,那宁愿不是“意外”。

标签: c arrays binary bit-shift


【解决方案1】:

除了@SouravGhosh 指出的问题,您还需要

(5) 通过添加字符'0' 的值[实际上Sourav 也注意到了],将数字0/1 转换为'0''1' 的字符值,并且

(6) 将k 右移一位之前 取出低位。

这是一个工作版本:

char c[40];
int j=39;
c[j--]='\0';
while(k)
    {
    c[j]=(k&1)+'0';
    j--;
    k=k>>1;
    }

puts("number is ");
puts(&c[j+1]);

【讨论】:

  • 你的观点 (5) 是我的观点 (3) 第二部分还是我遗漏了什么? :-)
  • @SouravGhosh 不,我错过了,抱歉。 (固定。)
  • @SouravGhosh 我是初学者,很抱歉问为什么使用 char '0'
  • @madara 询问信息时永远不要后悔,你问得很好。要将数字1 表示为char,我们需要ASCII 值,并且整数文字的所有ASCII 值都从48(即'0')开始。请参阅this 表。
  • 考虑k==0,没有打印出来。使用do { ...} while (k)
【解决方案2】:

我假设您想要二进制的字典表示。

你需要注意一些事情。

  1. 必须在使用前初始化k。要求用户输入(或“硬编码”,如我们所说)k 的值。

  2. 如果你想使用数组c作为字符串,你需要空终止它。

  3. 你需要执行&,值为1取出最后一位。添加 '0' (记住,lexicographical)。存储它。

  4. 当前的数组索引会给您带来麻烦。您可以使用j 的普通数组索引,从0 开始。循环结束后,需要对最后一个索引进行空终止,然后进行打印。

伪代码如下所示

#include <stdio.h>

int main(void) {

    int val = 16;
    char  bin [128] = {0};
    int index = 0;

    while(val)
    {
        bin[index] = '0' + (val&1u);
        val = val >> 1;
        index++;
    }
    bin[index] = 0;

    puts(bin);


    return 0;
}

SEE A LIVE DEMO


注意:您可能想在打印之前反转字符串。

【讨论】:

  • 也需要初始化k
  • 您好,Sourav,先生。我可以建议您将代码(或链接提供的任何内容)添加到您的答案中吗?如果 ideone 决定更改任何内容,您的回答可能会变得毫无用处。
  • @Olaf 您好,先生,您好吗?其实我不想spoonfeed 代码。您是否建议在此处添加代码?
  • 很好,坦克们,希望你们也好。关于链接:我主要参考对应的FAQ。请注意,我不建议这样删除链接;如果链接离线怎么办?您正在根据外部站点确定答案的价值。但是,这只是一个友好的建议。如果你不遵循它,我很好。
  • @Olaf 感谢您的建议,随时欢迎。我已经在此处添加了代码,如果 OP 正在单击链接,他将看到代码无论如何。 :-)
【解决方案3】:

如果有兴趣,这里有一个稍微不同的方法...

考虑到对于 32 位整数的图形二进制表示,您需要包含 33 个字节:32 表示 1 和 0,1 表示字符串 NULL 终止符。当您遍历整数值的任何 32 位表示时,您可以对输入整数值的每个位位置进行逻辑和 (&amp;) 2^32 (2147483648) 的相应位,以确定该位置是否应该是“ 1" 或 "0",将 10(48 或 49)的结果字符 (ASCII) 表示堆叠到一个字符串。

这是将整数转换为 32 位二进制表示的示例...

const char *byte_to_binary32(long x)
{
    static char b[33]; // bits plus '\0'
    b[0] = '\0';
    char *p = b;  
    //unsigned long long z; required only if 64 bit conversion
    unsigned long z;//this is sufficient for 32 bit conversion
    for (z = 2147483648; z > 0; z >>= 1)       //2^32
    {
        *p++ = (x & z) ? '1' : '0';
    }
    return b;
}

int main(void)
{
    printf("Binary: %s\n\n", byte_to_binary32(100));
    return 0;
}

【讨论】:

  • 您应该关心的一些细节:最好使用 unsigned long z 而不是 unsigned int z,因为 int/unsigned 只需 16 位 - 在 2015 年的嵌入式世界中仍然很常见。此外,它符合您的使用long 中的 byte_to_binary32(long x)
  • @Chux - 好点。由于这确实是一个很少使用的客厅技巧,我想知道在任何嵌入式系统中多久会实施一次。但是点了,编辑了。再次感谢。
猜你喜欢
  • 1970-01-01
  • 2012-02-24
  • 1970-01-01
  • 2018-04-21
  • 2020-11-06
  • 2010-12-15
  • 1970-01-01
  • 2022-01-22
  • 2020-09-10
相关资源
最近更新 更多