1

I have a file that contains a matrix of many rows and columns. It looks like something below:

fa ff 00 10 00
ee ee 00 00 30
dd d1 00 aa 00

Each entry in the matrix is a hex number of an eight bit value. I would like to read this file into a two dimensional array.

I have two problems:

  1. Using the read method in my code, *it contains an array that has each entry (two characters) of the matrix. How can I pass each entry into a single variable instead of two characters?

  2. When I pass into the single variable, how to convert it from character to hex? I mean "ff" should be converted to 0xff.

Part of my code is below. I can avoid the tokenize function if better methods can be uesd.

char** tokens;
char** it;

while (fgets(line, sizeof(line), file) != NULL){ /* read a line */
    tokens = tokenize(line);    // split line

    for(it=tokens; it && *it; ++it){
        printf("%s\n", *it);
        free(*it);
    } // end for
} // end while

char** tokenize(const char* str){
    int count = 0;
    int capacity = 10;
    char** result = malloc(capacity*sizeof(*result));

    const char* e=str;

    if (e) do {
        const char* s=e;
        e=strpbrk(s," ");

        if (count >= capacity)
            result = realloc(result, (capacity*=2)*sizeof(*result));

        result[count++] = e? strndup(s, e-s) : strdup(s);
    } while (e && *(++e));

    if (count >= capacity)
        result = realloc(result, (capacity+=1)*sizeof(*result));
    result[count++] = 0;

    return result;
}
3
  • Do you mean take fa ff 00 10 00 as a number, then we will get 1078020018176? Commented Oct 1, 2013 at 1:35
  • No, fa is a single entry. So i will get 0xfa instead of "fa". Commented Oct 1, 2013 at 1:36
  • Just see my post below. Commented Oct 1, 2013 at 1:47

4 Answers 4

7

Here is half an answer: to read a hex string and turn it into a value, you can do the following:

#include <stdio.h>

int main(void) {
  char *myString="8e";
  int myVal;
  sscanf(myString, "%x", &myVal);
  printf("The value was read in: it is %0x in hex, or %d in decimal\n", myVal, myVal);
}

This gets you the answer to the "how do I read two characters into one variable" part of your question, I hope.

As for the second half - if you did the following:

while (fgets(line, sizeof(line), file) != NULL){ /* read a line */
    tokens = tokenize(line);    // split line

    for(int ii=0; tokens[ii]; i++) {
        printf("ii=%d; token = %s\n", ii, tokens[ii]);
    } // end for
} // end while

you would see that your tokens array already contains what you are asking for: the strings. If you convert each of them using sscanf - for example like so:

int myValues[10];
for(int ii=0; ii<10; ii++) {
  sscanf(tokens+ii, "%x", myValues+ii);
  printf("The %dth converted value is %d - or %x in hex\n", ii, myValues[ii], myValues[ii]);
}

You can see that this does everything you want. I used a fixed size array in the above - you clearly know how to use malloc to make a dynamically allocated array of the right size (instead of a fixed value of 10).

One more note - the address of an array element myArray[0] can be written either as &myArray[0], or simply as myArray. For other elements, &myArray[5] is the same as myArray+5. One of the marvels of pointer math in C. I hope this helps.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you for the answer! What about reading each entry into a single variable?
Do you know ahead of time how many tokens per line, and how many lines?
Yes. I know those numbers, they are passed in from stdin.
But i think tokens[i] is the answer as @Theodoros suggested.
Thank you for the answer. One last question. The line: for(it=tokens; it && *it; ++it){ // Although I assign it = tokens, but it[0] is not equal to tokens[0]. What is the reason for this? Thank you!
|
2

Converting to a hexadecimal number is kind of meaningless, since hexadecimal/decimal/binary/etc are just representations of a value that's stored in the same way in memory anyway.

That being said, a simple way to convert the hexadecimal string to the number it represents is this:

  1. Create a temporary buffer where you prepend "0x" to your hex string (so if you have the string "ff" make the buffer contain "0xff").
  2. Give that buffer to a scanning function (sscanf will work for your case) and in the format string give the correct format specifier (in this case %x for hex).
  3. Retrieve the value from the variable (whose address you have provided to sscanf) and use it however you like.

5 Comments

Thank you. This problem is solved. What about reading each matrix entry into a single variable?
How about just tokens[0], tokens[1]? (Unless you mean something else.)
That solves the problem. Could you add a few lines in your answer and I will take it. But I still don't understand why it[0] != tokens[0].
Could you be more specific about what lines you want?
for(it=tokens; it && *it; ++it){ // Although I assign it = tokens, but it[0] is not equal to tokens[0]. What is the reason for this? Thank you!
0

You may just use cin of scanf to read in the data as digit, they automatically take space or newline as split character, take this example:

int main() {
  int val;
  while (scanf("%x", &val) != EOF)
    printf("val we get : %x\n", val);

  return 0;
}

Here is the test.

Comments

0

Checkout Apple's implementation from hexString.c

static char byteMap[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
static int byteMapLen = sizeof(byteMap);

/* utility function to convert hex character representation to their nibble (4 bit) values */
static uint8_t
nibbleFromChar(char c)
{
    if(c >= '0' && c <= '9') return c - '0';
    if(c >= 'a' && c <= 'f') return c - 'a' + 10;
    if(c >= 'A' && c <= 'F') return c - 'A' + 10;
    return 255;
}


/* Utility function to convert nibbles (4 bit values) into a hex character representation */
static char
nibbleToChar(uint8_t nibble)
{
    if(nibble < byteMapLen) return byteMap[nibble];
    return '*';
}

/* Convert a buffer of binary values into a hex string representation */
char * bytesToHexString(uint8_t *bytes, size_t buflen)
{
    char *retval;
    int i;

    retval = malloc(buflen*2 + 1);
    for(i=0; i<buflen; i++) {
        retval[i*2] = nibbleToChar(bytes[i] >> 4);
        retval[i*2+1] = nibbleToChar(bytes[i] & 0x0f);
    }
    retval[i] = '\0';
    return retval;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.