将C字符串转换为二进制表示

3
在ANSI C中,如何将字符串转换为二进制字节数组?我搜索了很多,但都只有C++等其他语言的答案,没有C语言的。
我有一个想法是将字符串转换为ASCII码,然后将每个ASCII值转换为它的二进制。虽然这是最愚蠢的想法,但我不确定是否有其他选项。
我听说过Java中的编码函数,但我不确定它是否适用于相同的目的并且能够在C中使用。
string = "Hello"
bytearr[] = 10100101... some byte array..

希望有人能给我们解答一下这个问题,非常感谢!

2
“二进制字节数组”是什么意思?在C语言中,“字符串”只是一个包含值(字节)的内存块(数组),这些值被映射为ASCII字符。 - Brian Roach
类似于Java中的字节数组,可以将字符串处理成字节数组的形式。 - Maverickgugu
1
你似乎对术语非常困惑。在C中,字符串“已经是”二进制字节的数组,这几乎是定义。它可能已经是ASCII码(除非它是支持U+0000到U+007F之外字符的Unicode的其他编码)。因此,请再次尝试解释您希望“bytearr”的内容是什么。 - zwol
6个回答

10

你是指如何将C字符串转换为二进制表示吗?

这里有一个解决方案,可以将字符串转换为二进制表示。可以很容易地进行修改,将二进制字符串保存到字符串数组中。

#include <stdio.h>

int main(int argc, char *argv[])
{
    if(argv[1] == NULL) return 0; /* no input string */

    char *ptr = argv[1];
    int i;

    for(; *ptr != 0; ++ptr)
    {
        printf("%c => ", *ptr);

        /* perform bitwise AND for every bit of the character */
        for(i = 7; i >= 0; --i) 
            (*ptr & 1 << i) ? putchar('1') : putchar('0');

        putchar('\n');
    }

    return 0;
}

示例输入和输出:

./ascii2bin hello

h => 01101000
e => 01100101
l => 01101100
l => 01101100
o => 01101111

3

C语言中没有字符串。任何字符串都是字节数组。


我是指“任何字符串都是字节数组”。 - Jurlie

1

在我工作的大多数系统中,char 的宽度为1字节,因此 char[]char* 一个字节数组。

在大多数其他语言(如Java)中,字符串数据类型通过使用诸如UTF-8之类的编码来处理一定程度上的概念,但在C中并非如此。如果我要读取一个包含多字节值的UTF-8字符串,则我的字符将由数组中的两个桶表示(或者可能更多)。

从另一个角度来看,考虑到C中所有类型都对于您的系统具有固定的宽度(尽管它们可能在实现之间有所不同)。

因此,您正在操作的字符串一个字节数组。

那么下一个问题就是如何显示这些字节? 这很简单:

char* x = ???; /* some string */
unsigned int xlen = strlen(x);
int i = 0;

for ( i = 0; i < xlen; i++ )
{
    printf("%x", x[i]);
}

我想不出你为什么要将输出转换为二进制,但如果你愿意,这是可以做到的。


1
这与“char的宽度为1字节”不完全相同,但在这种情况下可能值得再次强调:根据定义,sizeof(char)==1。它永远不会是其他任何值。(但是,CHAR_BIT的值不一定为8。) - zwol

1

字符串是字节的数组。

如果你想以十六进制形式显示每个字符的ASCII值,你可以简单地这样做:

while (*str != 0)
  printf("%02x ", (unsigned char) *str++);

0

如果您只想迭代(或随机访问)单个字节的数字值,则根本不需要进行任何转换,因为C字符串已经是数组:

void dumpbytevals(const char *str)
{
    while (*str)
    {
        printf("%02x ", (unsigned char)*str);
        str++;
    }
    putchar('\n');
}

如果你在处理这种代码时不小心,当你需要支持非ASCII字符时,你可能会陷入困境。


0

由于在转换大型二进制数组时,printf 函数速度较慢。这里提供另一种不使用 printf 的方法:

#define BASE16VAL               ("x0x1x2x3x4x5x6x7x8x9|||||||xAxBxCxDxExF") 
#define BASE16_ENCODELO(b)      (BASE16SYM[((uint8)(b)) >> 4])
#define BASE16_ENCODEHI(b)      (BASE16SYM[((uint8)(b)) & 0xF]) 
#define BASE16_DECODELO(b)      (BASE16VAL[Char_Upper(b) - '0'] << 4)
#define BASE16_DECODEHI(b)      (BASE16VAL[Char_Upper(b) - '0']). 

要将十六进制字符串转换为字节数组,您需要执行以下操作:
while (*Source != 0)   
    {   
    Target[0]  = BASE16_DECODELO(Souce[0]);   
    Target[0] |= BASE16_DECODEHI(Souce[1]);    

    Target += 1;   
    Source += 2;   
    } 

*Target = 0;

源是一个指向包含十六进制字符串的字符数组的指针。 目标是一个指向将包含字节数组的字符数组的指针。

要将字节数组转换为十六进制字符串,您需要执行以下操作:

while (*Source != 0)   
    {   
    Target[0] = BASE16_ENCODELO(*Source);   
    Target[1] = BASE16_ENCODEHI(*Source);    

    Target += 2;   
    Source += 1;   
    }

目标是一个指向包含十六进制字符串的字符数组的指针。 源是一个指向将包含字节数组的字符数组的指针。

这里有一些缺失的宏:

#define Char_IsLower(C)  ((uint8)(C - 'a') < 26)
#define Char_IsUpper(C)  ((uint8)(C - 'A') < 26)
#define Char_Upper(C)    (Char_IsLower(C) ? (C + ('A' - 'a')) : C)
#define Char_Lower(C)    (Char_IsUpper(C) ? (C + ('a' - 'A')) : C)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接