2017-07-30 385 views
0

我需要将十六进制字符串转换为十进制值。我已经使用了以下方法。但有时它会返回错误的十进制值。Arduino十六进制到十进制转换

十六进制字符串在此格式“00 00 0C 6E”

unsigned long hexToDec(String hexString) { 
    unsigned long decValue = 0; 
    int nextInt; 
    for (long i = 0; i < hexString.length(); i++) { 
    nextInt = long(hexString.charAt(i)); 
    if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9); 
    if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15); 
    if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15); 
    nextInt = constrain(nextInt, 0, 15); 
    decValue = (decValue * 16) + nextInt; 
    } 
    return decValue; 
} 
+1

什么是String类型? map()函数做了什么?这是真的C给'hexString.length()'?它可能是,除了'nextInt = long(hexString.charAt(i));'在C中肯定是无效的(尽管它在C++中可能是有效的)。你没有展示如何调用代码,或者样例输入转换OK,或者样本输入失败(不清楚“00 00 0C 6E”通过还是失败)。 “ –

+0

”有时会返回错误的十进制值。“首先找到一个返回错误十进制值的具体示例。然后使用调试器或在您的代码中添加'printf()'语句来查看变量运行时的值。当你浏览你的代码时,找出哪些值是意想不到的,然后找出它们不符合你的期望的原因。 –

+0

[将HEX字符串转换为arduino中的十进制](https:// stackoverflow。com/questions/31830143/convert-hex-string-to-decimal-in-arduino) – TomServo

回答

1

你的十六进制字符串包含空格,但您的代码不跳过他们,constrain()功能有效地把白色空间变成0xF其中最终导致错误的结果。除此之外,你的代码是确定的。

如果我要提出修改建议的最小量我会说,后:

nextInt = long(hexString.charAt(i)); 

这个添加到代码:

if(isspace(nextInt)) 
    continue; 

并注意isspace()函数是C标准库函数在ctype.h头文件中原型化。

但是,如果我要对整个代码发表评论,那么您调用了太多的函数来完成一项可以在没有任何函数调用的情况下完成的工作。

2

空白区正在污染转换。试试这个:

#include <iostream> 
#include <string> 
#include <cctype> 
using namespace std; 

unsigned long hexToDec(string hexString) { 
    unsigned long decValue = 0; 
    char nextInt; 
    for (long i = 0; i < hexString.length(); i++) { 
    nextInt = toupper(hexString[i]); 
    if(isxdigit(nextInt)) { 
     if (nextInt >= '0' && nextInt <= '9') nextInt = nextInt - '0'; 
     if (nextInt >= 'A' && nextInt <= 'F') nextInt = nextInt - 'A' + 10; 
     decValue = (decValue << 4) + nextInt; 
    } 
    } 
    return decValue; 
} 

int main() { 
    string test = "00 00 00 0c 1e"; 
    printf("'%s' in dec = %ld\n", test.c_str(), hexToDec(test)); 
    return 0; 
} 

output: 
'00 00 00 0c 1e' in dec = 3102 
+0

鉴于你正在检查有效的转换范围,你可以不用'isxdigit';通过简单地复制第二个“if”与小写字母,也可以避免“toupper”。最后,*从'ctype.h'调用字符分类/转换函数时,必须始终将'char'强制转换为'unsigned char' *。 –

+0

你试过了吗? 'isxdigit'块在那里忽略包含左移和原始问题的空白。 “toupper”是一种权衡,可以采取任何一种方式,现在我认为它更清晰但效率更低。 – Grifplex

+0

关于'isxdigit',正如我所说的那样没用。你可以简单地删除它,将第二个if语句改成else if语句(应该已经是这样了),然后在continue语句中添加else语句。对于'toupper',确切地说,它效率不高。但是,最重要的是,如果您选择使用这些函数,则必须将其转换为'unsigned char'。 –

0
  1. 你为什么要硬编码的ASCII值?只需使用文字char - '0','9','a','f',...;他们更可读。
  2. 有没有必要所有那些map,简单的数学操作将做;同样,没有必要为constrain,它只是隐藏你的问题(见下一点)。
  3. 如果你遇到一个不在[0-9a-fA-F]范围内的字符,而不是跳过它,你只是将其ASCII值限制在0-15,这绝对不是你想要做的。

所以:

unsigned long hexToDec(String hexString) { 
    unsigned long ret; 
    for(int i=0, n=hexString.length(); i!=n; ++i) { 
     char ch = hexString[i]; 
     int val = 0; 
     if('0'<=ch && ch<='9')  val = ch - '0'; 
     else if('a'<=ch && ch<='f') val = ch - 'a' + 10; 
     else if('A'<=ch && ch<='F') val = ch - 'A' + 10; 
     else continue; // skip non-hex characters 
     ret = ret*16 + val; 
    } 
    return ret; 
} 

注意,这将提供正确的结果,如果你所得到的数据是大端转储某个整数。