How to convert Hexadecimal to Decimal?

2019-08-14 16:12发布

问题:

I have different hexadecimal data are coming and stored into an integer type register.

When I use fprint I can see the following:

0x3076
0x307c
.
.
.

However, I would like to show a Decimal version of above-mention Hex data as follows.

12406
12412
.
.
.

In theory, let's say for the first value you do the following to convert it to decimal.

(6* 16^0)+(7 * 16^1)+(0*16^2)+(3*16^3)=6 + 112+ 0 + 12288 = 12406

So IF I have the character-based version of "0x3076" and also, IF I am able to get each single characters 6 - 7 - 0 - 3, I can calculate the decimal amount!

So, I decided to divide "3076" by 1000. I was expected to get 3, but I got TWO characters instead! however, if I was able to get 3 for the remainder of "307c" I am not able to get "C". If it was decimal this might work not hex!

Also, I tried "strtol" command. As I use Cygwin to compile my code, I am not sure where the error is! What did I do wrong?

So, I just need to find a way to get EACH SINGLE character out of the HEX data!

Any idea please?

P.S.

Here is my code in order to help you to give me an idea.

   int get_readings(int source, int phase, int max_tries)
{
    uint8_t buf[MAX_IEC1107_MSG_BODY];
    uint8_t inbuf[MAX_IEC1107_MSG_BODY];
    int inlen;
    uint8_t *s;
    int32_t value;
    int status;
    double voltage;
    double current;
    double active_power;
    double reactive_power;
    double apparent_power;
    double power_factor;
    double frequency;

    s = buf;
    *s++ = HOST_CMD_GET_READINGS_PHASE_1 + phase;
    *s++ = 0x00;
    if (max_tries != 1)
        meter_set_max_tries(&emeter[source].meter_msg, max_tries);
    if (meter_exchange(&emeter[source].meter_msg, buf, 2, inbuf, &inlen)
        &&
        inbuf[1] != 0xFF)
    {
        emeter[source].no_response = FALSE;
        s = inbuf;
        /* Get current readings */
        value = (s[3] << 8) | s[2];

        fprint(stderr, "value:" %p\n, value); // this give me HEX code

. . .

回答1:

When reading in a string representing a number in hexadecimal, use strtol() to convert it to a long. Then if you want to print the number in decimal, use printf() with a %d format specifier.

char num[]="0x3076";
long n = strtol(num, NULL, 16);
printf("n=%ld\n", n);  // prints 12406

Once you read in the strings as longs using strtol and operate on the longs, the math should work itself out.



回答2:

unsigned n;
sscanf("0x3076", "%x", &n);
printf("%u\n", n);


回答3:

Only with the following line I could solve the issue!

fprintf(stderr, "Voltage: %.2f\n", value/100.00);

value was shown as HEX as I used to use %p! Then I changed to x! and as I need to have 124.06 not 12406, in other words 2 decimal points, I added .2f!

Thank you all!



回答4:

You are confusing "integer" and "decimal" -- an "integer" is a number stored in a register or variable, while a "decimal" is a string of characters that represent a number in base 10.

So converting from hexadecimal to decimal is a two-step process. You first convert the hexadecimal to integer (which you appear to have done, with your "In theory" equation). You then convert the integer to decimal.

There are lots of ways to do either of these tasks, strtol and scanf will convert either hexadecimal or decimal to integer. printf can convert integer to either hexedecimal or decimal. Or you can write your own routines that manipulate characters to do either of these things.



回答5:

1) for printing only:

#include <stdio.h>
#include <stdlib.h>

int main(){
  int a=0;
  scanf("%x",&a);
  printf("%d\n",a);
  system("pause");
  return 0;
}

2) for calculation use:

#include<stdio.h>
#include<stdlib.h>
int CharToDec(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 0;
}
int main(int argc, char *argv[]){
  char H[10];
  char *P;
  int p=1,d=0;
  printf("Entrez Hexadecimale nombre:");
  scanf("%s",H);
  for(P=H;*P;P++);
  for(P--;P>=H;P--){
    d = d + (CharToDec(*P) * p);
    p =  p*16;
  }
  printf("%d\n",d);
system("pause");
return 0
}