十六进制到八进制转换程序,不使用十进制或二进制



今天我只是在玩从一个基地到另一个基地的基本转换。我浏览了一些将十六进制转换为八进制的代码,我注意到它主要使用中间转换到十进制或二进制,然后再转换回八进制。是否有可能编写自己的函数将十六进制字符串转换为八进制字符串,而不使用任何中间转换。此外,我不想使用内置的printf选项,如%x%o。谢谢你的建议。

当然可以。数字就是数字,不管它在哪个数字系统中。唯一的问题是人们习惯了十进制,这就是为什么他们更能理解它。你可以从任何碱基转换成任何其他碱基。

编辑:关于如何执行转换的更多信息。

首先注意3个十六进制数字正好对应4个八进制数字。因此,有了十六进制数字的数量,就可以很容易地找到八进制数字的数量:

#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';
  }
}

这里还有ideone上的例子,这样你就可以使用它了:example。

这有点棘手,因为你将把4位组转换为3位组-你可能想要一次处理12位,即3个十六进制数字到4个八进制数字,然后你必须单独处理任何剩余的位。

。将5274八进制转换为十六进制:

5    2    7    4
101  010  111  100
|||/   \//   |||
1010   1011   1100
A      B      C

计算机内存中的所有数字都是以2为基数的。因此,当你想要对这些值(数学运算)进行实际操作时,你将需要它们作为int型、浮点型等。因此,通过可计算类型进行转换是很方便的,或者将来可能会很方便。

我会避免直接的字符串到字符串的转换,除非值太大而无法放入数字变量中。从头开始编写可靠的转换器是非常困难的。

(在二进制计算机中使用10进制没有什么意义)

是的,您可以相对容易地做到:四个八进制数字总是转换为三个十六进制数字,因此您可以将字符串分成三个十六进制数字的组,并从后面处理每组。如果您没有足够的十六进制数字来完成一组3,请添加前导零。

每个十六进制数字表示4位;把最后三个转换成八进制。加上后面的四位,再取三位八进制。加上最后一组四位——现在总共有六位,所以把它们转换成两位八进制数字。

这避免了将整个数字转换为二进制,尽管在转换数字的过程中会使用一个"滑动"二进制窗口。

考虑一个示例:将62ABC转换为八进制。分为三位数一组:062ABC(注意62前面加了零,构成三位数一组)

从后面开始:

  • C1100被切割成1100,使八进制41成为下一步
  • 的额外位。
  • B1011被切割成10用于下一步,11用于这一步。上一步的1附在11的右边,形成一个八进制的7
  • A1010被切成1010。上一步的10附在右边,成为010,或八进制2101是八进制5,所以目前我们有5274
  • 2变为下一步20;
  • 6变为下一步401;
  • 0变成了01(因为添加了上一步的01)

最后的结果是01425274 .

对我来说似乎是一个相当直接的任务…你想要一个十六进制字符串,你想把它转换成八进制字符串。让我们将ASCII十六进制转换为int类型来使用:

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

现在仍然是十六进制,如果我们想从一种进制转换为另一种进制,可以做简单的数学运算:

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

这告诉我们12316 == 4438所以我们所要做的就是将数学运算写入基本函数并将最终值放回字符串:

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;
}

所以这个函数将十六进制(int)值转换为oct字符串。你可以这样命名它:

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 %on", value, value);
   oct_value = convert_to_oct(value);
   printf("value is %sn", oct_value);

所有八进制数字都包含3位信息。所有十六进制数字包含12位信息。3和4的最小公倍数是12。

这意味着您可以构建一个简单的查找表

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

现在有了这个想法,您有几个选择:

  1. 建立地图(查找表)

这里的例程将向八进制(字符串)数添加前导零,直到它是4位长,然后从表中查找十六进制值。有两种变化是静态输入表,或者动态填充表。

  • 用数学代替查找表
  • 不用把每个解都敲出来,你可以计算它们

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

    其中octaldigit1/hexdigit16/octaldigit8分别表示"八进制1位"、"十六进制16位"、"八进制8位"。

    请注意,在这两种情况下,你都不会"使用二进制"或"使用十进制",但由于这些数字可以用这两种系统中的任何一种来表示,因此不可能避免有人在后面分析(或任何)十进制或二进制解决方案的正确性。

    这是一个将字符转换为javascript的简单函数。对ALERT或您的页面有效,最多65536 32BITS。您经常遇到的问题是代码超过127的文本。最安全的值是OCTAL。

    谢谢你的点赞(^ _ ^)。这是免费的。

     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('');
                                    }
    

    如果你只想得到一个字符的八进制值,这样做:Max = 65536 ou 0XFFFF。

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

    或完全:

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

    如果value> 65536返回UNDEFINED。您可以使用函数参数来增加该值。charCodeAt(x)或codePointAt(x).

    你的计算机认为所有的值都是0到255。

    我们不需要做大的函数来转换字符,这很容易。

    CHAR TO UNICIDE

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

    UNICODE TO OCTAL:

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

    等等……:)

    最新更新