Convert hex string to int

I apologize if this is a novice question, but I've been googling for a while now and couldn't find a solution. I have a string, string bs02 that outputs a 2 char hex piece from "00" to "FF". My ultimate goal is turning this string into an integer. Could anyone give me some code that can do that? Would i have to convert the string bs02 to hex first and then convert it to int or is already understood to be hex and just needs to be converted from hex to int? thanks again for your time!

Is the hex in a string (null terminated char array) or a String (object created using the String library) ?

You don't have to convert the string to hex, because it's not possible :P A number can be written in few different way (decimal, binary, hex..) but the difference is only visual.

All these are exactly the same thing once compiled:

byte b = 255;
byte b = 0b11111111;
byte b = 0xFF;

To convert a hex string to int, you can use function strtol ( or strtoul if you want a unsigned result). Alternatively (because I like and use this function a lot), sscanf .

If it is truly a 2 char array that holds the hex string, then try this:

void setup() {
  Serial.begin(9600);
}

void loop() {
  char input[3];
  int charsRead;
  int val;
  
  if (Serial.available() > 0) {
    charsRead = Serial.readBytesUntil('\n', input, 2);  // fetch the two characters
    input[charsRead] = '\0';                            // Make it a string

    val = StrToHex(input);                              // Convert it

    Serial.print("Hex input was: ");                    // Show it...
    Serial.print(input);
    Serial.print("   decimal = ");
    Serial.println(val);
  }
}

int StrToHex(char str[])
{
  return (int) strtol(str, 0, 16);
}

I'm not a big fan of sscanf() because it eats more memory than is usually necessary.

econjack: I'm not a big fan of sscanf() because it eats more memory than is usually necessary.

How much functions can sscanf replace? I haven't tested but I think that if in your code you use many atoi, strtol, strtod, strcat, and more... possibly strtok, etc... Then it might be worth replacing all those with sscanf, maybe it will use less memory then :P

Edit: not strcat, that's a replacement job for sprintf :P

How much functions can sscanf replace? I haven't tested but I think that if in your code you use many atoi, strtol, strtod, strcat, and more... possibly strtok, etc... Then it might be worth replacing all those with sscanf, maybe it will use less memory then

True, but how many programs need atoi(), strtol(), strcat(), and all of the other features built into sscanf() in the same program? If you need all of those tools, then it might save some memory. Still, if the only tool you have is a hammer, pretty soon all your problems start to look like a nail.

@UKhelibob the hex isn't in a char array, bs02 is just a plain old string. I used to import simple integers and in that case i had to use bs02.toint() to convert the string into an int, but now since the string is 2 letters or numbers combined in one string i can't just use .toint().

Would it be way better if i just used a 2 char array instead of the string?

Would it be way better if i just used a 2 char array instead of the string?

It would be most memory efficient if it were in a null terminated array of chars. Please, if you are going to refer to ‘strings’ use capital S if it is a String created using the String library.

wow ok, I didn't know arduino handled "String" and "string" differently. Oh my. Good to know!

To clarify my question, if i have 2 chars, "c[0]" and "c[1]" that both hold hex values and together they are a two digit hex val FF, how do i convert that to 255?

@econjack I'm sorry but I just didn't understand the answer you gave me

See reply #2

could you possibly elaborate, please? also, the problem isn't just converting a single hex char to integer, but the fact that i have two separate strings, c[0] and c[1] that need to be combined together to a single string and then converted to int

To clarify my question, if i have 2 chars, “c[0]” and “c[1]” that both hold hex values and together they are a two digit hex val FF, how do i convert that to 255?

Try something along these lines maybe…

char hexValue[] = {'F', 'F'};

void setup()
{
  Serial.begin(115200);

  byte tens = (hexValue[0] < '9') ? hexValue[0] - '0' : hexValue[0] - '7';
  byte ones = (hexValue[1] < '9') ? hexValue[1] - '0' : hexValue[1] - '7';
  byte number = (16 * tens) + ones;
  Serial.println(number);
}

void loop()
{
}

@econjack I'm sorry but I just didn't understand the answer you gave me

Take the program that I wrote, compile and run it. Then run the Serial monitor (Tools --> Serial Monitor) and type two hex digits into the top box and click Send and observe the output. The function I wrote, StrToHex(), does nothing but call the standard library function strtol(), which converts a string to a long. However, a long is 4 bytes and you want an int which is two bytes. Simply trying to pour 4 bytes of data (i.e., the long) into a 2-byte bucket (i.e., the int) runs of the risk of losing information. When that situation is possible, you should use a cast, which is what the expression (int) does before returning from the function call.

Spend a little time studying that program and a lot of what the others have said here will make more sense.

econjack:

int StrToHex(char str[])

{
 return (int) strtol(str, 0, 16);
}

That type cast is not needed. The value returned from strtol() will automatically be converted to int when it’s returned from StrToHex(). I believe it’s best not to use a type cast unless you understand why it’s needed–otherwise you run the risk of suppressing compiler warnings that expose actual bugs in your code.

you run the risk of suppressing compiler warnings that expose actual bugs in your code

The IDE is already pretty effective at suppressing warnings

I believe it's best not to use a type cast unless you understand why it's needed--otherwise you run the risk of suppressing compiler warnings that expose actual bugs in your code.

True, but the sequence point is usually the reverse: the code doesn't work as expected because the cast is missing. As to my use of the cast, it's really there for documentation purposes since, as you mentioned, the function type specifier will force it to an int anyway. That's what I call a "silent cast" which I am not a big fan of. A silent cast occurs when you assign a smaller data type (e.g., a 2-byte int) into a larger data type (e.g., a 4-byte long). Even though the compiler doesn't complain in those cases, I would still use the cast to document the intent. If they don't understand what a cast is, they probably have other fish to fry.

AWOL: The IDE is already pretty effective at suppressing warnings

LOL. That's true enough.

The verbose compiling option in the Arduino IDE would be a lot more attractive to use if some of the built-in libraries themselves (I'm looking at you, HardwareSerial.cpp) didn't throw compiler warnings. I bet the Arduino library developers don't even use verbose compiling because the warnings are so simple and easy to fix, like "comparison between signed and unsigned integer expressions".

econjack: True, but the sequence point is usually the reverse: the code doesn't work as expected because the cast is missing.

Yeah, there are cases where a cast is needed, such as to expand an integer to a larger (or smaller) type inside an expression. But as I said--"it's best not to use a type cast unless you understand why it's needed".

econjack, I think I've missed something in your code on reply #3. It is only converting 1 character at a time. Entering "FF" into serial monitor gets a response of Hex input was: F decimal = 15 Hex input was: F decimal = 15

instead of Hex input was: FF decimal = 255

Any ideas what it could be?