【问题标题】:Read In Hex Values (C)读入十六进制值 (C)
【发布时间】:2010-12-07 12:37:07
【问题描述】:

我目前正在尝试从文本文件中读取十六进制值。

可以有多行Hex,每行可以任意长:

  f53d6d0568c7c7ce

  1307a7a1c84058

  b41af04b24f3eb83ce

目前,我整理了一个简单的循环,以使用 fscanf 将十六进制值读入unsigned char line[500]

  for(i=0; i < 500; i++)
  {
        if (fscanf(fp, "%02x", &line[i]) != 1) break;
  }

目前,这仅读取第一行。同样,在其中随机放入 500 个进行阅读绝对不是最好的方法。

我假设我可以使用 sscanffgets 或类似的东西。但我不确定这是否是最好的方法。

如果有人能帮助我指出正确的方向,我将不胜感激。

【问题讨论】:

    标签: c hex io scanf


    【解决方案1】:

    fgets()sscanf() 你走在正确的轨道上;这将使您可以适当地调整所有内容。如果您的数据确实是那种格式,sscanf() 可能是矫枉过正;您可以自己编写一个快速转换循环并保存所有这些可变参数函数调用。

    【讨论】:

    • 在我们推出自己的十六进制转换器之前,只需记住 ctype.h 标头中的 toupper()tolower()。支持不区分大小写的十六进制数据绝不是一件坏事。
    【解决方案2】:

    请注意,sscanf 很慢(库调用、内存使用和过度杀伤)。此外,它太危险了(b/c 可能的缓冲区溢出)。

    使用自己的解析器可能会得到更好的结果。它可能显示为更大的源代码,但它让您有机会完全根据需要控制和扩展您的代码,而不会影响安全性和速度。

    通常的方法是在读取十六进制数字时将它们一一累加,并建立相应的整数:

    hexDigit = one letter from "0123456789ABCDEF" remapped to a number within 0-15
    accumulating_number= accumulating_number * 16 + hexDigit
    

    这是一个小型独立解析器作为完整示例。它接受小写和大写,并忽略任何非十六进制字符(因此您可以使用空格或逗号来提高源代码的可读性):

    #include <stdio.h>
    
    #define SPLIT_CHAR_SIZE 8   // size of the hex numbers to parse (eg. 6 for RGB colors)
    
    void do_something_with(unsigned int n)
    {
        printf("%08X ",n);
    }
    
    int main(int argc, char** argv)
    {
        FILE* fp= (argc!=2) ? stdin : fopen(argv[1],"r");
        if(!fp) { fprintf(stderr,"Usage: %s fileToRead\n", argv[0]); return(-1); }
    
        unsigned int i=0, accumulator=0;
        char c;
        while(!feof(fp)) // you could parse a c-string via fscanf() to handle other file contents
        {
            c= fgetc(fp);
    
            // The "<<4" gives room for 4 more bits, aka a nibble, aka one hex digit, aka a number within [0,15]
            if(c>='0' && c<='9')
                accumulator= (accumulator<<4) | (c - '0');
            else if(c>='a' && c<='f') // lower case
                accumulator= (accumulator<<4) | (c - 'a' + 10);
            else if(c>='A' && c<='F') // upper case
                accumulator= (accumulator<<4) | (c - 'A' + 10);
            else
                continue; // skip all other (invalid) characters
    
            // When you want to parse more than one hex number you can use something like this:
            if(++i % SPLIT_CHAR_SIZE == 0)
            {
                do_something_with(accumulator);
                accumulator= 0; // do not forget this
            }
        }
    
        printf("\n");
        return 0;
    }
    

    如果你给这个解析器以下(有点奇怪)文件内容:

    ca 53,
    FF 00
    aa bb cc dd
    

    然后函数 do_something_with() 将输出:

    CA53FF00 AABBCCDD
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-30
      • 2010-10-03
      • 2015-05-01
      • 2018-07-26
      • 2011-07-30
      • 2011-08-04
      • 1970-01-01
      相关资源
      最近更新 更多