代码之家  ›  专栏  ›  技术社区  ›  Sam

将十六进制转换为循环中的一个字符串

c99 c
  •  -3
  • Sam  · 技术社区  · 7 年前

    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

    1 回复  |  直到 7 年前
        1
  •  1
  •   ad absurdum    7 年前

    请注意,在问题中发布的代码中, string[] test() sizeof(hex_arr) 但是 hex_arr 是指向 char 字符串[] .还有,这里 string 是一个自动变量,其生存期仅限于函数 ; 如果唯一的目标是打印结果,这很好,但是如果需要在代码的其他地方使用结果,则必须找到另一种解决方案。

    一种方法是将输出数组和输入数组一起传递到转换函数中。函数可以返回 -1 0 ,输出数组可以保存由十六进制数输入字符串生成的标识符字符串。

    输入中的每对数字表示一个十六进制数,可以是三位十进制数,每个三位十进制数(最后一个数字后面有一个空终止符除外)后面都添加了一个分隔符;因此,每对输入数字最多转换为四个字符。这意味着分配 output[] input

    此处使用的方法 id_from_hexstring() sscanf() 在循环中,将一对字符作为字符串从输入读入临时缓冲区 val_str[] 这个 %n offset 并使用该值将指针递增到 input[]

    这个 strtoul() val_str[] unsigned long 价值观当第一对字符在 输入[] 如果转换的值不匹配,则转换 IN_PREFIX ,函数返回错误代码。否则 OUT_PREFIX 输出[] 而不是转换后的值。在第一对之后,剩余的转换值打印到 一串

    转换循环终止后,一个 . 分隔符留在 0 输入[] 输出[] 可以容纳额外的 . 分隔符。

    这段代码可以做更多的工作来验证输入。就目前而言 id\u from\u 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