0

Basically, I have a file which contains multiple lines that I have to parse. For example, I may have something of the form: "Homer Simpson ate @0x000000000000BEEF donuts"

Recovering the name is simple, it's recovering the number of donuts he ate that I have trouble with. In other words, I would like to store this number in a uint64_t variable.

My first approach was to simply read the number from character to character and convert it to a decimal (i.e. I would compute 0*16^15 + 0*16^14 + ... + E *16^1 + F*16^0). This method seems very costly to me and I am sure there must be a better way for me to achieve this. However, this technique had the advantage that if the number was written like this "@0x0000 0000 0000 BEEF", I would still be able to convert it to a uint64_t variable.

The second method I tried was to use sscanf or strol (as described in many other posts, such as this one: Convert hex string (char []) to int?). The problem with this method is that I first have to create a substring "@0x000000000000BEEF" from the original string (same goes for strol). Again, this technique works, but it wouldn't work if I had "@0x0000 0000 0000 BEEF.

Is there a clever and easy way for me to recover this number and store it in a uint64_t variable?

This question is not the same as in other posts. All they have to do it to convert a hex string into a uint64_t. My question is different.

I have a string which is not simply composed of the hex-value, the format of the hex-value may changes from line to line and may have whitespace separated words. For example, I may have:

"Bart annoyed @00000000000000AA people today"

Or the hex value may be written like this:

"Bart annoyed @0000 0000 0000 00AA people today"

How can I read each line a form the hex number as a string that can then be converted as shown in the other answers?

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
Skyris
  • 155
  • 1
  • 9

1 Answers1

1

A scanset could be used with sscanf to capture the portion of the line up to the @.
Then scan @0x and use %n to get the number of characters processed to use as an index for further processing.
Use %1x%n to scan each hex digit and count the characters processed. This will iterate through the line skipping spaces. Add the number of scanned characters to index and iterate through the line using input + index.
Incorporate each hex digit into the hex value. This shifts the value and or's the digit.

#include <stdio.h>
#include <inttypes.h>

#define SIZE 100
//so SIZE can be part of sscanf Format String
#define SSFS(x) #x
#define FS(x) SSFS(x)


int main( void) {
    char input[SIZE + 1] = "Homer Simpson ate @0x0000 0000 0000 B E E F donuts";
    char name[SIZE + 1] = "";
    int index = 0;
    int scanned = 0;
    int digit = 0;
    uint64_t hex = 0;
    unsigned int hexdigit = 0;

    sscanf ( input, "%"FS(SIZE)"[^@]@0x%n", name, &index);
    if ( index) {
        while ( digit < 16 && 1 == sscanf ( input + index, "%1x%n", &hexdigit, &scanned)) {
            digit++;
            index += scanned;
            hex <<= 4;
            hex |= hexdigit;
        }
        printf ( "name [%s] [%" PRIu64 "] [%s]\n", name, hex, input + index);
    }

    return 0;
}
xing
  • 2,125
  • 2
  • 14
  • 10