2017-07-30 63 views
-3

我尝试十六进制值转换成一个字符串,我已经看过这个question,但我不知道如何将它转换以动态的方式一个字符串,就像如果我的功能得到了六角系列8或9或更多。我怎样才能优化这个片段与一个循环遍历给定的十六进制值并转换每个十六进制值(第一个除外),然后是.十六进制转换到一个循环

/* 
Input: char[] ="2b06010201010300" 
Output: char[]="1.3.6.1.2.1.1.3.0" 
*/ 
void test(char * hex_arr) 
{ 
    char string[sizeof(hex_arr)*2+1]; 
    string[0] = '1'; 
    string[1] = '.'; 
    string[2] = '3'; 
    string[3] = '.'; 
    sprintf(&string[4], "%x", hex_arr[1]); 
    string[5] = '.'; 
    sprintf(&string[6], "%x", hex_arr[2]); 
    // ... 
    printf("Output: %s\n", string); 
} 

输入char[]表示SNMP OBJECT IDENTIFIER

+3

是对输入的字符串,如'炭输入[] = “06 2B 01 02 01 01 03 00”'?输出是一个字符串吗?而且,'2b'如何产生'1.3'? –

+0

@DavidBowling输入字符串类似于'unsigned char [] =“2b06010201010300”',输出是一个字符串。 '2b'被指定为'1.3'。 – Sam

+1

你能举出更多的输入和输出例子吗?并更详细地描述你的转换!顺便说一句,2b = 43,所以我不认为任何人在这里理解你如何得到1.3 ... –

回答

1

请注意,在问题中发布的代码中,使用sizeof(hex_arr)test()函数中声明string[]。但是hex_arr是一个指向char,而不是一个数组,所以这不会给正确的大小string[]。此外,这里的string是一个自动变量,其使用期限仅限于函数test();如果唯一的目标是打印结果,那很好,但如果结果需要在代码中的其他地方使用,则必须找到另一个解决方案。接近这个

的一种方法是与输入数组的变换函数一起传递的输出阵列。如果输入格式不可接受,则该函数可返回-1,否则返回0,并且输出数组可以保存由十六进制数字输入字符串产生的标识符字符串。

输入中的每个双位数字表示为十六进制数字,它可以是一个三位十进制数,并且每个三位数十进制数(除了最后一个,这之后是空终止)具有在它后面添加一个添加的分隔符;所以每对输入数字最多可以转换为四个字符。这意味着分配output[]input两倍的大小将足以存储任何结果,包括空终止符的空间。这实际上提供了一些额外的空间,这将是需要的。

这里使用的id_from_hexstring()函数来执行转换的方法,包括在循环中使用sscanf()读取对字符从输入字符串到临时缓冲器val_str[]。所述%n转换指定符被用来跟踪每个转换成功后达到的位置的,存储在offset成功匹配的数目并使用该值来递增一个指针到input[]在为下一次转换的准备。

strtoul()函数用于将存储在val_str[]中的两位十六进制字符串转换为unsigned long值。当转换input[]中的第一对字符时,如果转换后的值不匹配IN_PREFIX,则函数返回错误代码。否则,OUT_PREFIX将打印到output[]的开头,而不是转换后的值。在第一对之后,剩余的转换值将打印到output[]字符串的末尾。

转换循环终止后,在output[]的末尾会留下尾随.分隔符,最后一项任务是在返回0以指示成功之前删除此分隔符。由input[]数组的大小加倍(而不是串长度),以确定output[]数组的大小,可以保证output[]可以容纳额外的.定界符。

这段代码可以做更多的验证输入。现在,id_from_hexstring()函数期望输入由有效的十六进制字符组成。下面是完整的程序和它的输出:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define IN_PREFIX  0x2b 
#define OUT_PREFIX  "1.3." 
#define ID_PREFIX_ERR -1 
#define ID_PREFIX_OK 0 

int id_from_hexstring(char *out, char *in); 

int main(void) 
{ 
    char input[] = "2b06010201010300"; 
    char output[sizeof input * 2] = ""; 

    if (id_from_hexstring(output, input) == -1) { 
     fprintf(stderr, "Error in input format\n"); 
    } else { 
     printf("Input: %s\n", input); 
     printf("Output: %s\n", output); 
    } 

    return 0; 
} 

/* Expects that out points to a suitably sized array containing an empty 
* string, and in points to a string containing only unsigned hex digits */ 
int id_from_hexstring(char *out, char *in) 
{ 
    int ret_val = ID_PREFIX_OK; 
    int offset; 
    char *ptr = in; 
    char val_str[3]; 

    while (sscanf(ptr, "%2s%n", val_str, &offset) == 1) { 

     unsigned long dec_val = strtoul(val_str, NULL, 16); 

     /* Handle prefix; return error code if invalid */ 
     if (ptr == in) { 
      if (dec_val != IN_PREFIX) { 
      ret_val = ID_PREFIX_ERR; 
      break; 
      } else { 
       sprintf(out, OUT_PREFIX); 
       ptr += offset; 
       continue; 
      } 
     } 

     /* Print next value to identifier string */ 
     size_t end = strlen(out); 
     sprintf(out + end, "%lu.", dec_val); 
     ptr += offset; 
    } 

    /* Replace trailing point */ 
    size_t out_len = strlen(out); 
    if (out_len > 0) { 
     out[out_len - 1] = '\0'; 
    } 

    return ret_val; 
} 
Input: 2b06010201010300 
Output: 1.3.6.1.2.1.1.3.0 
+0

谢谢你的回答。如果输入是指向数组的指针,则不起作用。 'printf(“%02x \ n”,ptr [0]);'适用于指针,但我不能用'id_from_hexstring'将指针转换为 – Sam

+0

@ Sam--答案写在问题提供的规范中,输入是一个数组。如果通过“指向数组的指针”表示类似'char * input =“2b06010201010300”;''的类型,则可以使用'strlen()'而不是'sizeof'运算符,如下所示:'char output [(strlen(input )+ 1)* 2];'。这要求您的编译器支持VLA(在C99中是必需的,但在C11中是可选的)。答案中的原始代码没有使用VLA,如果移动了一些声明,它甚至会在C89下编译。 –

+0

@ David - 谢谢,我用'char input [ * 2]; sprintf(&input [i * 2],“%02x”,ptr [i]);'将十六进制表示为字符串。 – Sam