【问题标题】:Best practice to represent bit string in hex (Arduino)以十六进制表示位串的最佳实践(Arduino)
【发布时间】:2015-03-01 20:32:28
【问题描述】:

我有一个由 24 位“000101011110011110101110”组成的字符串(或 cstring),应该用十六进制 (0x15e7ae) 表示。

据我了解,位串需要由 4 位拆分为 6 部分 “0001 0101 1110 0111 1010 1110” 然后将每个部分转换为十六进制

0001 -> 1
0101 -> 5
1110 -> e
0111 -> 7
1010 -> a
1110 -> e

那么将其转换为十六进制表示形式的最简单且具有成本效益的方法是什么:0x15e7ae?

对于我来说,使用 String 或 char[] 哪种字符串类型更好,我也有两难选择。使用 substring 函数可以轻松拆分字符串,但我不知道如何将字符串类型转换为十六进制。

相反,char[] 可以使用 strtoul 函数轻松转换为十六进制,但我没有找到简单的方法来拆分 char 字符串。

【问题讨论】:

  • 您确定您的意思是“转换为十六进制”,因为strtoul 转换为unsigned long int;这种整数的十六进制表示可以由输出函数生成为字符串,例如sprintfprintf。您需要准确了解实际输入和所需输出。
  • 我的意思是可以打印出来的十六进制表示,不管它是什么数据类型。
  • 是的,但理想情况下,您需要在问题中明确说明,而不是在 cmets 中。
  • 将对话更改为表示。现在没有双重含义

标签: c++ c binary arduino hex


【解决方案1】:

在 C 中,这很简单。使用strtoumax(binary, 0, 2) 将二进制字符串转换为uintmax_t,然后使用sprintffprintf 将其转换为十六进制字符串。

【讨论】:

  • 例如:printf("%jx",strtoumax(binary, 0, 2));
【解决方案2】:

让我们尝试一些简单的位移。

std::string sample_str = "000101011110011110101110";
uint32_t result = 0;
for (unsigned int i = 0; i < sample_str.length(); ++i)
{
  result = result << 1;
  result = result | (sample_str[i] & 1);
}

可能有更快的方法,但您必须在网上搜索“bit twiddling string”。

背景
这是基于零的字符表示的最低有效位设置为零的假设。同样,1 的字符表示将最低有效位设置为 1。

算法将结果左移一位,以便为新的位值腾出空间。 将字符值与 1 进行 AND 运算会导致值 0 表示“0”,而值 1 表示“1”。将此结果与result 值进行或运算,以产生正确的值。

尝试使用调试器单步执行,看看它是如何工作的。

【讨论】:

  • 实际上这段代码没有返回“15e7ae”,我得到的是 1435566
  • @user947668 : 1435566 是 0x15e7ae 的十进制表示。 result 是一个整数,你必须选择你希望如何输出它。这就是我对您似乎误解的问题的评论中的要点。给出的几个答案描述了十六进制表示的整数输出。
  • @user947668:将字符串转换为内部表示后,如何查看它取决于您。您可以将其视为十六进制或十进制;内部表示的输出留作练习。 :-)
  • Serial.print(result, HEX);奇迹般有效!谢谢
【解决方案3】:
const char* binary = "000101011110011110101110" ;
char hex[9] = "" ;

uint32_t integer = 0 ;

for( int i = 0; binary[i+1] != '\0'; i++ )
{
    if( binary[i] == '1' )
    {
        integer |= 1 ;
    }
    integer <<= 1 ;
}

sprintf( hex, "0x%06x", integer ) ;

【讨论】:

  • 不需要 'if' 语句,因为最后一位是字符所需的全部内容。看我的回答。 :-)
  • 是的,我已经看到了你的答案,它假设了 '0' 和 '1' 的字符代码(即 '0' 是偶数和 '1' 奇数),而对于无处不在的 ASCII 表示,它可能不太清楚。我认为我会保持这一立场,但你的观点已被注意到并同意。然而,我怀疑优化是否重要。
【解决方案4】:

这在这个链接中确实可以找到:StringConstructors

 // using an int and a base (hexadecimal):
 stringOne =  String(45, HEX);   
 // prints "2d", which is the hexadecimal version of decimal 45:
 Serial.println(stringOne);   

【讨论】:

  • 但是需要的输入是'1'和'0'字符组成的字符串,而不是整数。
  • 一个字符串实际上是一个接一个的多个字节。这样做:最后一个字节和 0x0F 作为字符串转换的输入。然后最后一个字节 & 0xF0 作为字符串转换的输入。移动到下一个字节。然后将多个字符串加在一起。效率不高,但它会起作用。如果您想要一个体面的答案,请发布一段代码。
  • 这不是我的问题,我只是指出这不是对所提问题的回答。它可以用作解决方案的最后一部分,我的答案使用sprintf() - 但被标记为 C、C++ Arduino - 有多种可能性!
  • 我已经检查过了,这似乎也是一个不错的答案。它不像 Clifford 和 Thomas 所建议的那样通用,但它是最简单的。 String 的第一个参数应该是二进制数据类型变量,第二个是 HEX。
猜你喜欢
  • 1970-01-01
  • 2017-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-11
  • 2016-02-06
  • 1970-01-01
  • 2022-09-26
相关资源
最近更新 更多