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

时间:2013-01-10 15:13:22

标签: c hex octal

今天我只是在玩一个从一个基地到另一个基地的基本转换。我调整了一些代码,用于从十六进制转换为八进制,我注意到它主要使用中间转换为十进制或二进制,然后返回到八进制。是否可以编写我自己的函数将十六进制字符串转换为八进制字符串而不使用任何中间转换。我也不想使用printf%x这样的内置%o选项。感谢您的投入。

7 个答案:

答案 0 :(得分:5)

当然有可能。数字是一个数字,无论它处于什么数字系统。唯一的问题是人们习惯于十进制,这就是为什么他们更好地理解它。您可以从任何基地转换为任何其他基地。

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

首先请注意,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

答案 1 :(得分:3)

这有点棘手,因为您将4位组转换为3位组 - 您可能希望一次使用12位,即3个十六进制数字到4个八进制数字,然后您将拥有分别处理任何剩余的比特。

E.g。把5274八进制转换为十六进制:

5    2    7    4
101  010  111  100

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

1010   1011   1100
A      B      C

答案 2 :(得分:1)

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

每个十六进制数字为您提供四位;取最后三个,并将它们转换为八进制。添加接下来的四个,并将另外四个位添加到八进制。添加最后一组四个 - 现在总共有六个位,因此将它们转换为两个八进制数字。

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

考虑一个例子:将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

答案 3 :(得分:1)

计算机内存中的所有数字都是基数2.因此,每当你想要实际使用值(数学运算)做某事时,你需要它们作为整数,浮点数等。所以它很方便或者将来可能会派上用场通过可计算类型进行转换。

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

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

答案 4 :(得分:1)

对我来说似乎是一个非常直接的任务...你想要一个十六进制字符串,并且你想将它转换为八进制字符串。让我们取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

这告诉我们123 16 == 443 8 所以我们要做的就是将数学写入基本函数并将最终值放回字符串中:

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

所以这个函数会将hex(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 %o\n", value, value);

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

答案 5 :(得分:0)

这是将字符转换为javascript的简单功能。对ALERT或您的页面(最多65536 32BITS)有效。您遇到的问题通常是127以上代码的文本。最安全的值是OCTAL。避免使用ParseXX。

感谢您的喜欢(^ _ ^)。免费享受。

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

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

您的计算机将所有内容视为0到255。

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

要加入的字符

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

UNICODE总计:

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

等...:)

答案 6 :(得分:0)

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

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

FORM return_fm   USING i_taskname.
*your code
  get_executed = 'X'.
ENDFORM.                     

现在有了这个主意,您有几种选择:

  1. 构建地图(查找表)

此处的例程将在八进制(字符串)数字前添加零,直到长度为4位,然后从表中查找十六进制值。有两种变体是静态键入表或动态填充表。

  1. 使用数学替换查找表

您无需计算每个解决方案,而是可以计算出它们

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

其中octaldigit1 / hexdigit16 / octaldigit8分别表示“八进制1的位置”,“十六进制16的位置”,“八进制8的位置”。

请注意,在这两种情况下,您都不会“使用二进制”或“使用十进制”,但是由于这些数字可以在这两个系统中的任何一个中表示,因此无法避免有人落后并分析其正确性(或任何)解决方案以十进制或二进制形式表示。