Question

Today I was just playing around for basic conversions from one base to another. I goggled some code for converting from hex to octal, and I noticed that it mostly uses intermediate conversion to either decimal or binary and then back to octal.Is it possible write my own function for converting hex string to octal string without using any intermediate conversion.Also I do not want to use inbuilt printf option like %x or %o. Thanks for your inputs.

Was it helpful?

Solution

Of course it is possible. A number is a number no matter what numeric system it is in. The only problem is that people are used to decimal and that is why they understand it better. You may convert from any base to any other.

EDIT: more info on how to perform the conversion.

First note that 3 hexadecimal digits map to exactly 4 octal digits. So having the number of hexadecimal digits you may find the number of octal digits easily:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int get_val(char hex_digit) {
  if (hex_digit >= '0' && hex_digit <= '9') {
    return hex_digit - '0';
  } else {
    return hex_digit - 'A' + 10;
  }
}
void convert_to_oct(const char* hex, char** res) {
  int hex_len = strlen(hex);
  int oct_len = (hex_len/3) * 4;
  int i;

  // One hex digit left that is 4 bits or 2 oct digits.
  if (hex_len%3 == 1) {
    oct_len += 2;
  } else if (hex_len%3 == 2) { // 2 hex digits map to 3 oct digits
    oct_len += 3;
  }

  (*res) = malloc((oct_len+1) * sizeof(char));
  (*res)[oct_len] = 0; // don't forget the terminating char.

  int oct_index = oct_len - 1; // position we are changing in the oct representation.
  for (i = hex_len - 1; i - 3 >= 0; i -= 3) {
    (*res)[oct_index] = get_val(hex[i]) % 8 + '0';
    (*res)[oct_index - 1] = (get_val(hex[i])/8+ (get_val(hex[i-1])%4) * 2) + '0';
    (*res)[oct_index - 2] = get_val(hex[i-1])/4 + (get_val(hex[i-2])%2)*4 + '0';
    (*res)[oct_index - 3] = get_val(hex[i-2])/2 + '0'; 
    oct_index -= 4;
  }

  // if hex_len is not divisible by 4 we have to take care of the extra digits:
  if (hex_len%3 == 1) {
     (*res)[oct_index] = get_val(hex[0])%8 + '0';
     (*res)[oct_index - 1] = get_val(hex[0])/8 + '0';
  } else if (hex_len%3 == 2) {
     (*res)[oct_index] = get_val(hex[1])%8 + '0';
     (*res)[oct_index - 1] = get_val(hex[1])/8 + (get_val(hex[0])%4)*4 + '0';
     (*res)[oct_index - 2] = get_val(hex[0])/4 + '0';
  }
}

Also here is the example on ideone so that you can play with it: example.

OTHER TIPS

It's a little tricky as you will be converting groups of 4 bits to groups of 3 bits - you'll probably want to work with 12 bits at a time, i.e. 3 hex digits to 4 octal digits and you'll then have to deal with any remaining bits separately.

E.g. to convert 5274 octal to hex:

5    2    7    4
101  010  111  100

|||/   \\//   \|||

1010   1011   1100
A      B      C

All numbers in computer's memory are base 2. So whenever you want to actually DO something with the values (mathematical operations), you'll need them as ints, floats, etc. So it's handy or may come handy in the future to do the conversion via computable types.

I'd avoid direct string to string conversions, unless the values can be too big to fit into a numeric variable. It is surprisingly hard to write reliable converter from scratch.

(Using base 10 makes very little sense in a binary computer.)

Yes, you can do it relatively easily: four octal digits always convert to three hex digits, so you can split your string into groups of three hex digits, and process each group from the back. If you do not have enough hex digits to complete a group of three, add leading zeros.

Each hex digit gives you four bits; take the last three, and convert them to octal. Add the next four, and take three more bits to octal. Add the last group of four - now you have six bits in total, so convert them to two octal digits.

This avoids converting the entire number to a binary, although there will be a "sliding" binary window used in the process of converting the number.

Consider an example: converting 62ABC to octal. Divide into groups of three digits: 062 and ABC (note the added zero in front of 62 to make a group of three digits).

Start from the back:

  • C, or 1100, gets chopped into 1 and 100, making octal 4, and 1 extra bit for the next step
  • B, or 1011, gets chopped into 10 for the next step and 11 for this step. The 1 from the previous step is attached on the right of 11, making an octal 7
  • A, or 1010, gets chopped into 101 and 0. The 10 from the previous step is attached on the right, making 010, or octal 2. The 101 is octal 5, so we have 5274 so far.
  • 2 becomes 2 and 0 for the next step;
  • 6 becomes 4 and 01 for the next step;
  • 0 becomes 0 and 1 (because 01 from the previous step is added).

The final result is 01425274.

Seems like a pretty straight forward task to me... You want a hex string and you want to convert it to an octal string. Let's take the ASCII hex and convert it to an int type to work with:

char hex_value[] = "0x123";

int value = strtol(hex_value,NULL,16);

It's still hex at this point, then if we want to convert from one base to another there's simple math that can be done:

123 / 8 = 24 R 3
 24 / 8 =  4 R 4
  4 / 8 =  0 R 4

This tells us that 12316 == 4438 so all we have to do is write that math into a basic function and put the final value back into a string:

char * convert_to_oct(int hex)
{
    int ret = 0, quotient = 0, reminder = 0, dividend = hex, counter = 0, i;
    char * ret_str;   // returned string

    while(dividend > 0){             // while we have something to divide
        quotient = dividend / 0x8;   // get the quotient
        reminder = dividend - quotient * 0x8; // get the reminder

        ret += reminder * pow(10, counter);   // add the reminder (shifted) 
                                              // into our return value
        counter++;            // increment our shift
        dividend = quotient;  // get ready for the next divide operation
    }

    ret_str = malloc(counter);   // allocate the right number of characters
    sprintf(ret_str, "%d", ret); // store the result

    return ret_str;
}

So this function will convert a hex (int) value into a oct string. You could call it like:

int main()
{
   char hex_value[] = "0x123";
   char * oct_value;
   int value = strtol(hex_value,NULL,16);

   // sanity check, see what the value should be before the convert
   printf("value is %x, auto convert via printf gives %o\n", value, value);

   oct_value = convert_to_oct(value);
   printf("value is %s\n", oct_value);

All octal digits contain 3 bits of information. All Hex digits contain 12 bits of information. The least common multiple of 3 and 4 is 12.

This means you can build a simple lookup table

0000 = 0x000
0001 = 0x001
0002 = 0x002
...
0007 = 0x007
0010 = 0x008
0011 = 0x009
0012 = 0x00A
...
0017 = 0x00F
0020 = 0x010
...
5274 = 0xABC
...

Now that the idea is there, you have several choices:

  1. Build a Map (lookup table)

The routine here would add leading zeros to the octal (string) number until it was 4 digits long, and then lookup the hexadecimal value from the table. Two variations are typing out the table statically, or populating it dynamically.

  1. Use math to replace the lookup table

Instead of typing out each solution, you could calculate them

hexdigit1 = 01 & octaldigit8 + octaltdigit1;
hexdigit16 = 03 & octaldigit64 << 02 + 06 & octaldigit8 >> 01;
hexdigit256 = octaldigit512 << 01 + 01 & octaldigit64;

where the octaldigit1 / hexdigit16 / octaldigit8 means "octal 1's place", "hexadecimal 16's place", "octal 8's place" respectively.

Note that in either of these cases you don't "use binary" or "use decimal" but as these numbers can be represented in either of those two systems, it's not possible to avoid someone coming along behind and analyzing the correctness of the (or any) solution in decimal or binary terms.

Here is an easy function to convert your characters into javascript. valid for ALERT or for your pages up to 65536 32BITS. The concern you encounter is often for the text for codes beyond 127. The safest value is the OCTAL. ParseXX to avoid.

Thank you for your likes (^ _ ^). it's free to enjoy.

 function enjoyOCTALJS (valuestr){
        var arrstr = valuestr.split('');
        arrstr = arrstr.map(f => (!isNaN(f.charCodeAt(0)))? (f.charCodeAt(0)>127)? '\\'+f.charCodeAt(0).toString(8):f:f);
        return arrstr.join('');
                                }

If you just want to get the octal value of a character do this: Max = 65536 ou 0XFFFF.

var mchar = "à";
var result = mchar.charCodeAt(0).toString(8);

Or completely :

var mchar = 'à';
var result = mchar.codePointAt(0).toString(8);

If value > 65536 return UNDEFINED. You can use the function parameter to increase the value. charCodeAt(x) or codePointAt(x).

Your computer considers everything as 0 to 255.

We do not need to do big functions to convert characters, it's very easy.

CHAR TO UNICIDE

var mchar = 'à';
var result = mchar.codePointAt(0);  or  mchar.charCodeAt();

UNICODE TO OCTAL :

var mcode = 220;
var result = mcode.toString(8);

etc... :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top