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

问题描述 投票:4回答:7

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

c hex octal
7个回答
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


3
投票

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

例如。把5274八进制转换为十六进制:

5    2    7    4
101  010  111  100

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

1010   1011   1100
A      B      C

1
投票

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

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

(使用base 10在二进制计算机中几乎没有意义。)


1
投票

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

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

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

考虑一个例子:将62ABC转换为八进制。分成三个数字的组:062ABC(注意在62前面添加的零以组成一组三位数)。

从后面开始:

  • C,或1100,切入1100,制作八角4,和1额外位为下一步
  • B,或1011,切入10为下一步和11这一步。上一步的1附在11的右边,制作一个八角形7
  • A,或1010,被切入1010。上一步的10附在右边,制作010或八角形2101是octal 5,所以到目前为止我们有5274
  • 2成为下一步的20;
  • 6成为下一步的401;
  • 0成为01(因为添加了上一步的01)。

最终结果是01425274


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

这告诉我们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;
}

所以这个函数会将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);

0
投票

所有八进制数字都包含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位,然后从表中查找十六进制值。两种变体是静态输入表格,或动态填充表格。

  1. 使用math替换查找表

您可以计算它们,而不是输入每个解决方案

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

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

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


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。

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

CHAR to UNICODE

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

UNICODE到OCTAL:

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

等... :)

© www.soinside.com 2019 - 2024. All rights reserved.